From 421dab29fa32a01d79705d7151862f941ff64294 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Fri, 5 Jan 2024 17:14:26 +0800 Subject: [PATCH 1/4] feat(freertos/smp): Update SMP FreeRTOS files to V11.0.1 This commit updates the source files of Amazon SMP FreeRTOS to upstream V11.0.1 (https://github.com/FreeRTOS/FreeRTOS-Kernel/tree/V11.0.1). This version contains SMP support. --- .../freertos/FreeRTOS-Kernel-SMP/README.md | 39 - .../freertos/FreeRTOS-Kernel-SMP/croutine.c | 361 - .../FreeRTOS-Kernel-SMP/event_groups.c | 269 +- .../include/freertos/FreeRTOS.h | 2034 ++++- .../include/freertos/StackMacros.h | 12 +- .../include/freertos/atomic.h | 10 +- .../include/freertos/croutine.h | 118 +- .../include/freertos/deprecated_definitions.h | 10 +- .../include/freertos/event_groups.h | 190 +- .../include/freertos/list.h | 146 +- .../include/freertos/message_buffer.h | 173 +- .../include/freertos/mpu_prototypes.h | 315 +- .../include/freertos/mpu_syscall_numbers.h | 109 + .../include/freertos/mpu_wrappers.h | 281 +- .../include/freertos/newlib-freertos.h | 66 + .../include/freertos/picolibc-freertos.h | 95 + .../include/freertos/portable.h | 121 +- .../include/freertos/projdefs.h | 46 +- .../include/freertos/queue.h | 315 +- .../include/freertos/semphr.h | 189 +- .../include/freertos/stack_macros.h | 82 +- .../include/freertos/stdint.readme | 52 - .../include/freertos/stream_buffer.h | 173 +- .../include/freertos/task.h | 1219 ++- .../include/freertos/timers.h | 141 +- .../freertos/FreeRTOS-Kernel-SMP/list.c | 60 +- .../freertos/FreeRTOS-Kernel-SMP/queue.c | 1268 ++-- .../FreeRTOS-Kernel-SMP/stream_buffer.c | 719 +- .../freertos/FreeRTOS-Kernel-SMP/tasks.c | 6683 +++++++++++------ .../freertos/FreeRTOS-Kernel-SMP/timers.c | 576 +- .../FreeRTOS-Kernel-SMP/uncrustify.cfg | 673 ++ tools/ci/check_copyright_ignore.txt | 25 - 32 files changed, 11463 insertions(+), 5107 deletions(-) delete mode 100644 components/freertos/FreeRTOS-Kernel-SMP/README.md delete mode 100644 components/freertos/FreeRTOS-Kernel-SMP/croutine.c create mode 100644 components/freertos/FreeRTOS-Kernel-SMP/include/freertos/mpu_syscall_numbers.h create mode 100644 components/freertos/FreeRTOS-Kernel-SMP/include/freertos/newlib-freertos.h create mode 100644 components/freertos/FreeRTOS-Kernel-SMP/include/freertos/picolibc-freertos.h delete mode 100644 components/freertos/FreeRTOS-Kernel-SMP/include/freertos/stdint.readme create mode 100644 components/freertos/FreeRTOS-Kernel-SMP/uncrustify.cfg diff --git a/components/freertos/FreeRTOS-Kernel-SMP/README.md b/components/freertos/FreeRTOS-Kernel-SMP/README.md deleted file mode 100644 index 1cc1b84cea..0000000000 --- a/components/freertos/FreeRTOS-Kernel-SMP/README.md +++ /dev/null @@ -1,39 +0,0 @@ -## Getting started -This repository contains FreeRTOS kernel source/header files and kernel ports only. This repository is referenced as a submodule in [FreeRTOS/FreeRTOS](https://github.com/FreeRTOS/FreeRTOS) repository, which contains pre-configured demo application projects under ```FreeRTOS/Demo``` directory. - -The easiest way to use FreeRTOS is to start with one of the pre-configured demo application projects. That way you will have the correct FreeRTOS source files included, and the correct include paths configured. Once a demo application is building and executing you can remove the demo application files, and start to add in your own application source files. See the [FreeRTOS Kernel Quick Start Guide](https://www.FreeRTOS.org/FreeRTOS-quick-start-guide.html) for detailed instructions and other useful links. - -Additionally, for FreeRTOS kernel feature information refer to the [Developer Documentation](https://www.FreeRTOS.org/features.html), and [API Reference](https://www.FreeRTOS.org/a00106.html). - -### Getting help -If you have any questions or need assistance troubleshooting your FreeRTOS project, we have an active community that can help on the [FreeRTOS Community Support Forum](https://forums.freertos.org). - -## Cloning this repository - -To clone using HTTPS: -``` -git clone https://github.com/FreeRTOS/FreeRTOS-Kernel.git -``` -Using SSH: -``` -git clone git@github.com:FreeRTOS/FreeRTOS-Kernel.git -``` - -## Repository structure -- The root of this repository contains the three files that are common to -every port - list.c, queue.c and tasks.c. The kernel is contained within these -three files. croutine.c implements the optional co-routine functionality - which -is normally only used on very memory limited systems. - -- The ```./portable``` directory contains the files that are specific to a particular microcontroller and/or compiler. -See the readme file in the ```./portable``` directory for more information. - -- The ```./include``` directory contains the real time kernel header files. - -### Code Formatting -FreeRTOS files are formatted using the "uncrustify" tool. The configuration file used by uncrustify can be found in the [FreeRTOS/FreeRTOS repository](https://github.com/FreeRTOS/FreeRTOS/blob/master/tools/uncrustify.cfg). - -### Spelling -*lexicon.txt* contains words that are not traditionally found in an English dictionary. It is used by the spellchecker to verify the various jargon, variable names, and other odd words used in the FreeRTOS code base. If your pull request fails to pass the spelling and you believe this is a mistake, then add the word to *lexicon.txt*. -Note that only the FreeRTOS Kernel source files are checked for proper spelling, the portable section is ignored. - diff --git a/components/freertos/FreeRTOS-Kernel-SMP/croutine.c b/components/freertos/FreeRTOS-Kernel-SMP/croutine.c deleted file mode 100644 index 7f32fb4a7f..0000000000 --- a/components/freertos/FreeRTOS-Kernel-SMP/croutine.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * https://www.FreeRTOS.org - * https://github.com/FreeRTOS - * - */ - -#include "FreeRTOS.h" -#include "task.h" -#include "croutine.h" - -/* Remove the whole file is co-routines are not being used. */ -#if ( configUSE_CO_ROUTINES != 0 ) - -/* - * Some kernel aware debuggers require data to be viewed to be global, rather - * than file scope. - */ - #ifdef portREMOVE_STATIC_QUALIFIER - #define static - #endif - - -/* Lists for ready and blocked co-routines. --------------------*/ - static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */ - static List_t xDelayedCoRoutineList1; /*< Delayed co-routines. */ - static List_t xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */ - static List_t * pxDelayedCoRoutineList = NULL; /*< Points to the delayed co-routine list currently being used. */ - static List_t * pxOverflowDelayedCoRoutineList = NULL; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */ - static List_t xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */ - -/* Other file private variables. --------------------------------*/ - CRCB_t * pxCurrentCoRoutine = NULL; - static UBaseType_t uxTopCoRoutineReadyPriority = 0; - static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0; - -/* The initial state of the co-routine when it is created. */ - #define corINITIAL_STATE ( 0 ) - -/* - * Place the co-routine represented by pxCRCB into the appropriate ready queue - * for the priority. It is inserted at the end of the list. - * - * This macro accesses the co-routine ready lists and therefore must not be - * used from within an ISR. - */ - #define prvAddCoRoutineToReadyQueue( pxCRCB ) \ - { \ - if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \ - { \ - uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \ - } \ - vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \ - } - -/* - * Utility to ready all the lists used by the scheduler. This is called - * automatically upon the creation of the first co-routine. - */ - static void prvInitialiseCoRoutineLists( void ); - -/* - * Co-routines that are readied by an interrupt cannot be placed directly into - * the ready lists (there is no mutual exclusion). Instead they are placed in - * in the pending ready list in order that they can later be moved to the ready - * list by the co-routine scheduler. - */ - static void prvCheckPendingReadyList( void ); - -/* - * Macro that looks at the list of co-routines that are currently delayed to - * see if any require waking. - * - * Co-routines are stored in the queue in the order of their wake time - - * meaning once one co-routine has been found whose timer has not expired - * we need not look any further down the list. - */ - static void prvCheckDelayedList( void ); - -/*-----------------------------------------------------------*/ - - BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, - UBaseType_t uxPriority, - UBaseType_t uxIndex ) - { - BaseType_t xReturn; - CRCB_t * pxCoRoutine; - - /* Allocate the memory that will store the co-routine control block. */ - pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) ); - - if( pxCoRoutine ) - { - /* If pxCurrentCoRoutine is NULL then this is the first co-routine to - * be created and the co-routine data structures need initialising. */ - if( pxCurrentCoRoutine == NULL ) - { - pxCurrentCoRoutine = pxCoRoutine; - prvInitialiseCoRoutineLists(); - } - - /* Check the priority is within limits. */ - if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES ) - { - uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1; - } - - /* Fill out the co-routine control block from the function parameters. */ - pxCoRoutine->uxState = corINITIAL_STATE; - pxCoRoutine->uxPriority = uxPriority; - pxCoRoutine->uxIndex = uxIndex; - pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode; - - /* Initialise all the other co-routine control block parameters. */ - vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) ); - vListInitialiseItem( &( pxCoRoutine->xEventListItem ) ); - - /* Set the co-routine control block as a link back from the ListItem_t. - * This is so we can get back to the containing CRCB from a generic item - * in a list. */ - listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine ); - listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine ); - - /* Event lists are always in priority order. */ - listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) ); - - /* Now the co-routine has been initialised it can be added to the ready - * list at the correct priority. */ - prvAddCoRoutineToReadyQueue( pxCoRoutine ); - - xReturn = pdPASS; - } - else - { - xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; - } - - return xReturn; - } -/*-----------------------------------------------------------*/ - - void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, - List_t * pxEventList ) - { - TickType_t xTimeToWake; - - /* Calculate the time to wake - this may overflow but this is - * not a problem. */ - xTimeToWake = xCoRoutineTickCount + xTicksToDelay; - - /* We must remove ourselves from the ready list before adding - * ourselves to the blocked list as the same list item is used for - * both lists. */ - ( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); - - /* The list item will be inserted in wake time order. */ - listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake ); - - if( xTimeToWake < xCoRoutineTickCount ) - { - /* Wake time has overflowed. Place this item in the - * overflow list. */ - vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); - } - else - { - /* The wake time has not overflowed, so we can use the - * current block list. */ - vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); - } - - if( pxEventList ) - { - /* Also add the co-routine to an event list. If this is done then the - * function must be called with interrupts disabled. */ - vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) ); - } - } -/*-----------------------------------------------------------*/ - - static void prvCheckPendingReadyList( void ) - { - /* Are there any co-routines waiting to get moved to the ready list? These - * are co-routines that have been readied by an ISR. The ISR cannot access - * the ready lists itself. */ - while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE ) - { - CRCB_t * pxUnblockedCRCB; - - /* The pending ready list can be accessed by an ISR. */ - portDISABLE_INTERRUPTS(); - { - pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyCoRoutineList ) ); - ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); - } - portENABLE_INTERRUPTS(); - - ( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) ); - prvAddCoRoutineToReadyQueue( pxUnblockedCRCB ); - } - } -/*-----------------------------------------------------------*/ - - static void prvCheckDelayedList( void ) - { - CRCB_t * pxCRCB; - - xPassedTicks = xTaskGetTickCount() - xLastTickCount; - - while( xPassedTicks ) - { - xCoRoutineTickCount++; - xPassedTicks--; - - /* If the tick count has overflowed we need to swap the ready lists. */ - if( xCoRoutineTickCount == 0 ) - { - List_t * pxTemp; - - /* Tick count has overflowed so we need to swap the delay lists. If there are - * any items in pxDelayedCoRoutineList here then there is an error! */ - pxTemp = pxDelayedCoRoutineList; - pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList; - pxOverflowDelayedCoRoutineList = pxTemp; - } - - /* See if this tick has made a timeout expire. */ - while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE ) - { - pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList ); - - if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) ) - { - /* Timeout not yet expired. */ - break; - } - - portDISABLE_INTERRUPTS(); - { - /* The event could have occurred just before this critical - * section. If this is the case then the generic list item will - * have been moved to the pending ready list and the following - * line is still valid. Also the pvContainer parameter will have - * been set to NULL so the following lines are also valid. */ - ( void ) uxListRemove( &( pxCRCB->xGenericListItem ) ); - - /* Is the co-routine waiting on an event also? */ - if( pxCRCB->xEventListItem.pxContainer ) - { - ( void ) uxListRemove( &( pxCRCB->xEventListItem ) ); - } - } - portENABLE_INTERRUPTS(); - - prvAddCoRoutineToReadyQueue( pxCRCB ); - } - } - - xLastTickCount = xCoRoutineTickCount; - } -/*-----------------------------------------------------------*/ - - void vCoRoutineSchedule( void ) - { - /* Only run a co-routine after prvInitialiseCoRoutineLists() has been - * called. prvInitialiseCoRoutineLists() is called automatically when a - * co-routine is created. */ - if( pxDelayedCoRoutineList != NULL ) - { - /* See if any co-routines readied by events need moving to the ready lists. */ - prvCheckPendingReadyList(); - - /* See if any delayed co-routines have timed out. */ - prvCheckDelayedList(); - - /* Find the highest priority queue that contains ready co-routines. */ - while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) ) - { - if( uxTopCoRoutineReadyPriority == 0 ) - { - /* No more co-routines to check. */ - return; - } - - --uxTopCoRoutineReadyPriority; - } - - /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines - * of the same priority get an equal share of the processor time. */ - listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ); - - /* Call the co-routine. */ - ( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex ); - } - } -/*-----------------------------------------------------------*/ - - static void prvInitialiseCoRoutineLists( void ) - { - UBaseType_t uxPriority; - - for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ ) - { - vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) ); - } - - vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 ); - vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 ); - vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList ); - - /* Start with pxDelayedCoRoutineList using list1 and the - * pxOverflowDelayedCoRoutineList using list2. */ - pxDelayedCoRoutineList = &xDelayedCoRoutineList1; - pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2; - } -/*-----------------------------------------------------------*/ - - BaseType_t xCoRoutineRemoveFromEventList( const List_t * pxEventList ) - { - CRCB_t * pxUnblockedCRCB; - BaseType_t xReturn; - - /* This function is called from within an interrupt. It can only access - * event lists and the pending ready list. This function assumes that a - * check has already been made to ensure pxEventList is not empty. */ - pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); - ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); - vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) ); - - if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority ) - { - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - - return xReturn; - } - -#endif /* configUSE_CO_ROUTINES == 0 */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/event_groups.c b/components/freertos/FreeRTOS-Kernel-SMP/event_groups.c index 3e72547c49..ae7e1f83d3 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/event_groups.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/event_groups.c @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -38,38 +44,22 @@ #include "timers.h" #include "event_groups.h" -/* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified - * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined +/* The MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined * for the header files above, but not in this file, in order to generate the * correct privileged Vs unprivileged linkage and placement. */ -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021 See comment above. */ - -/* The following bit fields convey control information in a task's event list - * item value. It is important they don't clash with the - * taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */ -#if configUSE_16_BIT_TICKS == 1 - #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U - #define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U - #define eventWAIT_FOR_ALL_BITS 0x0400U - #define eventEVENT_BITS_CONTROL_BYTES 0xff00U -#else - #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL - #define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL - #define eventWAIT_FOR_ALL_BITS 0x04000000UL - #define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL -#endif +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE typedef struct EventGroupDef_t { EventBits_t uxEventBits; - List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */ + List_t xTasksWaitingForBits; /**< List of tasks waiting for a bit to be set. */ #if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxEventGroupNumber; #endif #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */ + uint8_t ucStaticallyAllocated; /**< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */ #endif } EventGroup_t; @@ -95,21 +85,26 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, { EventGroup_t * pxEventBits; + traceENTER_xEventGroupCreateStatic( pxEventGroupBuffer ); + /* A StaticEventGroup_t object must be provided. */ configASSERT( pxEventGroupBuffer ); #if ( configASSERT_DEFINED == 1 ) - { - /* Sanity check that the size of the structure used to declare a - * variable of type StaticEventGroup_t equals the size of the real - * event group structure. */ - volatile size_t xSize = sizeof( StaticEventGroup_t ); - configASSERT( xSize == sizeof( EventGroup_t ) ); - } /*lint !e529 xSize is referenced if configASSERT() is defined. */ + { + /* Sanity check that the size of the structure used to declare a + * variable of type StaticEventGroup_t equals the size of the real + * event group structure. */ + volatile size_t xSize = sizeof( StaticEventGroup_t ); + configASSERT( xSize == sizeof( EventGroup_t ) ); + } #endif /* configASSERT_DEFINED */ /* The user has provided a statically allocated event group - use it. */ - pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 !e9087 EventGroup_t and StaticEventGroup_t are deliberately aliased for data hiding purposes and guaranteed to have the same size and alignment requirement - checked by configASSERT(). */ + /* MISRA Ref 11.3.1 [Misaligned access] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */ + /* coverity[misra_c_2012_rule_11_3_violation] */ + pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; if( pxEventBits != NULL ) { @@ -117,12 +112,12 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - { - /* Both static and dynamic allocation can be used, so note that - * this event group was created statically in case the event group - * is later deleted. */ - pxEventBits->ucStaticallyAllocated = pdTRUE; - } + { + /* Both static and dynamic allocation can be used, so note that + * this event group was created statically in case the event group + * is later deleted. */ + pxEventBits->ucStaticallyAllocated = pdTRUE; + } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ traceEVENT_GROUP_CREATE( pxEventBits ); @@ -135,6 +130,8 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, traceEVENT_GROUP_CREATE_FAILED(); } + traceRETURN_xEventGroupCreateStatic( pxEventBits ); + return pxEventBits; } @@ -147,20 +144,12 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, { EventGroup_t * pxEventBits; - /* Allocate the event group. Justification for MISRA deviation as - * follows: pvPortMalloc() always ensures returned memory blocks are - * aligned per the requirements of the MCU stack. In this case - * pvPortMalloc() must return a pointer that is guaranteed to meet the - * alignment requirements of the EventGroup_t structure - which (if you - * follow it through) is the alignment requirements of the TickType_t type - * (EventBits_t being of TickType_t itself). Therefore, whenever the - * stack alignment requirements are greater than or equal to the - * TickType_t alignment requirements the cast is safe. In other cases, - * where the natural word size of the architecture is less than - * sizeof( TickType_t ), the TickType_t variables will be accessed in two - * or more reads operations, and the alignment requirements is only that - * of each individual read. */ - pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */ + traceENTER_xEventGroupCreate(); + + /* MISRA Ref 11.5.1 [Malloc memory assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); if( pxEventBits != NULL ) { @@ -168,21 +157,23 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) - { - /* Both static and dynamic allocation can be used, so note this - * event group was allocated statically in case the event group is - * later deleted. */ - pxEventBits->ucStaticallyAllocated = pdFALSE; - } + { + /* Both static and dynamic allocation can be used, so note this + * event group was allocated statically in case the event group is + * later deleted. */ + pxEventBits->ucStaticallyAllocated = pdFALSE; + } #endif /* configSUPPORT_STATIC_ALLOCATION */ traceEVENT_GROUP_CREATE( pxEventBits ); } else { - traceEVENT_GROUP_CREATE_FAILED(); /*lint !e9063 Else branch only exists to allow tracing and does not generate code if trace macros are not defined. */ + traceEVENT_GROUP_CREATE_FAILED(); } + traceRETURN_xEventGroupCreate( pxEventBits ); + return pxEventBits; } @@ -199,12 +190,14 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, BaseType_t xAlreadyYielded; BaseType_t xTimeoutOccurred = pdFALSE; + traceENTER_xEventGroupSync( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTicksToWait ); + configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( uxBitsToWaitFor != 0 ); #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - { - configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); - } + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } #endif vTaskSuspendAll(); @@ -256,7 +249,7 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, { if( xAlreadyYielded == pdFALSE ) { - vTaskYieldWithinAPI(); + taskYIELD_WITHIN_API(); } else { @@ -308,6 +301,8 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, /* Prevent compiler warnings when trace macros are not used. */ ( void ) xTimeoutOccurred; + traceRETURN_xEventGroupSync( uxReturn ); + return uxReturn; } /*-----------------------------------------------------------*/ @@ -323,15 +318,17 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, BaseType_t xWaitConditionMet, xAlreadyYielded; BaseType_t xTimeoutOccurred = pdFALSE; + traceENTER_xEventGroupWaitBits( xEventGroup, uxBitsToWaitFor, xClearOnExit, xWaitForAllBits, xTicksToWait ); + /* Check the user is not attempting to wait on the bits used by the kernel * itself, and that at least one bit is being requested. */ configASSERT( xEventGroup ); configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( uxBitsToWaitFor != 0 ); #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - { - configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); - } + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } #endif vTaskSuspendAll(); @@ -408,7 +405,7 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, { if( xAlreadyYielded == pdFALSE ) { - vTaskYieldWithinAPI(); + taskYIELD_WITHIN_API(); } else { @@ -464,6 +461,8 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, /* Prevent compiler warnings when trace macros are not used. */ ( void ) xTimeoutOccurred; + traceRETURN_xEventGroupWaitBits( uxReturn ); + return uxReturn; } /*-----------------------------------------------------------*/ @@ -474,6 +473,8 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, EventGroup_t * pxEventBits = xEventGroup; EventBits_t uxReturn; + traceENTER_xEventGroupClearBits( xEventGroup, uxBitsToClear ); + /* Check the user is not attempting to clear the bits used by the kernel * itself. */ configASSERT( xEventGroup ); @@ -492,6 +493,8 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, } taskEXIT_CRITICAL(); + traceRETURN_xEventGroupClearBits( uxReturn ); + return uxReturn; } /*-----------------------------------------------------------*/ @@ -503,8 +506,12 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, { BaseType_t xReturn; + traceENTER_xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ); + traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ); - xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */ + xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); + + traceRETURN_xEventGroupClearBitsFromISR( xReturn ); return xReturn; } @@ -518,33 +525,40 @@ EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) EventGroup_t const * const pxEventBits = xEventGroup; EventBits_t uxReturn; - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + traceENTER_xEventGroupGetBitsFromISR( xEventGroup ); + + uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); { uxReturn = pxEventBits->uxEventBits; } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); + + traceRETURN_xEventGroupGetBitsFromISR( uxReturn ); return uxReturn; -} /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */ +} /*-----------------------------------------------------------*/ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) { - ListItem_t * pxListItem, * pxNext; + ListItem_t * pxListItem; + ListItem_t * pxNext; ListItem_t const * pxListEnd; List_t const * pxList; EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits; EventGroup_t * pxEventBits = xEventGroup; BaseType_t xMatchFound = pdFALSE; + traceENTER_xEventGroupSetBits( xEventGroup, uxBitsToSet ); + /* Check the user is not attempting to set the bits used by the kernel * itself. */ configASSERT( xEventGroup ); configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); pxList = &( pxEventBits->xTasksWaitingForBits ); - pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + pxListEnd = listGET_END_MARKER( pxList ); vTaskSuspendAll(); { traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ); @@ -619,6 +633,8 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, } ( void ) xTaskResumeAll(); + traceRETURN_xEventGroupSetBits( pxEventBits->uxEventBits ); + return pxEventBits->uxEventBits; } /*-----------------------------------------------------------*/ @@ -626,7 +642,13 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, void vEventGroupDelete( EventGroupHandle_t xEventGroup ) { EventGroup_t * pxEventBits = xEventGroup; - const List_t * pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits ); + const List_t * pxTasksWaitingForBits; + + traceENTER_vEventGroupDelete( xEventGroup ); + + configASSERT( pxEventBits ); + + pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits ); vTaskSuspendAll(); { @@ -639,29 +661,31 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) ); vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET ); } - - #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) - { - /* The event group can only have been allocated dynamically - free - * it again. */ - vPortFree( pxEventBits ); - } - #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) - { - /* The event group could have been allocated statically or - * dynamically, so check before attempting to free the memory. */ - if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) - { - vPortFree( pxEventBits ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ } ( void ) xTaskResumeAll(); + + #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) + { + /* The event group can only have been allocated dynamically - free + * it again. */ + vPortFree( pxEventBits ); + } + #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + { + /* The event group could have been allocated statically or + * dynamically, so check before attempting to free the memory. */ + if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) + { + vPortFree( pxEventBits ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + + traceRETURN_vEventGroupDelete(); } /*-----------------------------------------------------------*/ @@ -672,6 +696,8 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) BaseType_t xReturn; EventGroup_t * pxEventBits = xEventGroup; + traceENTER_xEventGroupGetStaticBuffer( xEventGroup, ppxEventGroupBuffer ); + configASSERT( pxEventBits ); configASSERT( ppxEventGroupBuffer ); @@ -680,6 +706,9 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) /* Check if the event group was statically allocated. */ if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdTRUE ) { + /* MISRA Ref 11.3.1 [Misaligned access] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */ + /* coverity[misra_c_2012_rule_11_3_violation] */ *ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits; xReturn = pdTRUE; } @@ -691,11 +720,16 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) #else /* configSUPPORT_DYNAMIC_ALLOCATION */ { /* Event group must have been statically allocated. */ + /* MISRA Ref 11.3.1 [Misaligned access] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */ + /* coverity[misra_c_2012_rule_11_3_violation] */ *ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits; xReturn = pdTRUE; } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + traceRETURN_xEventGroupGetStaticBuffer( xReturn ); + return xReturn; } #endif /* configSUPPORT_STATIC_ALLOCATION */ @@ -703,21 +737,33 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) /* For internal use only - execute a 'set bits' command that was pended from * an interrupt. */ -portTIMER_CALLBACK_ATTRIBUTE void vEventGroupSetBitsCallback( void * pvEventGroup, - const uint32_t ulBitsToSet ) + uint32_t ulBitsToSet ) { - ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */ + traceENTER_vEventGroupSetBitsCallback( pvEventGroup, ulBitsToSet ); + + /* MISRA Ref 11.5.4 [Callback function parameter] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); + + traceRETURN_vEventGroupSetBitsCallback(); } /*-----------------------------------------------------------*/ /* For internal use only - execute a 'clear bits' command that was pended from * an interrupt. */ -portTIMER_CALLBACK_ATTRIBUTE void vEventGroupClearBitsCallback( void * pvEventGroup, - const uint32_t ulBitsToClear ) + uint32_t ulBitsToClear ) { - ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */ + traceENTER_vEventGroupClearBitsCallback( pvEventGroup, ulBitsToClear ); + + /* MISRA Ref 11.5.4 [Callback function parameter] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); + + traceRETURN_vEventGroupClearBitsCallback(); } /*-----------------------------------------------------------*/ @@ -766,8 +812,12 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, { BaseType_t xReturn; + traceENTER_xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ); + traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ); - xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */ + xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ); + + traceRETURN_xEventGroupSetBitsFromISR( xReturn ); return xReturn; } @@ -780,7 +830,13 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, UBaseType_t uxEventGroupGetNumber( void * xEventGroup ) { UBaseType_t xReturn; - EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */ + + /* MISRA Ref 11.5.2 [Opaque pointer] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup; + + traceENTER_uxEventGroupGetNumber( xEventGroup ); if( xEventGroup == NULL ) { @@ -791,6 +847,8 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, xReturn = pxEventBits->uxEventGroupNumber; } + traceRETURN_uxEventGroupGetNumber( xReturn ); + return xReturn; } @@ -802,7 +860,14 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, void vEventGroupSetNumber( void * xEventGroup, UBaseType_t uxEventGroupNumber ) { - ( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */ + traceENTER_vEventGroupSetNumber( xEventGroup, uxEventGroupNumber ); + + /* MISRA Ref 11.5.2 [Opaque pointer] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + ( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber; + + traceRETURN_vEventGroupSetNumber(); } #endif /* configUSE_TRACE_FACILITY */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h index 24dbd653df..6efa94bf27 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -45,7 +51,7 @@ * contains the typedefs required to build FreeRTOS. Read the instructions * in FreeRTOS/source/stdint.readme for more information. */ -#include /* READ COMMENT ABOVE. */ +#include /* READ COMMENT ABOVE. */ /* *INDENT-OFF* */ #ifdef __cplusplus @@ -53,9 +59,47 @@ #endif /* *INDENT-ON* */ +/* Acceptable values for configTICK_TYPE_WIDTH_IN_BITS. */ +#define TICK_TYPE_WIDTH_16_BITS 0 +#define TICK_TYPE_WIDTH_32_BITS 1 +#define TICK_TYPE_WIDTH_64_BITS 2 + /* Application specific configuration options. */ #include "FreeRTOSConfig.h" +#if !defined( configUSE_16_BIT_TICKS ) && !defined( configTICK_TYPE_WIDTH_IN_BITS ) + #error Missing definition: One of configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#if defined( configUSE_16_BIT_TICKS ) && defined( configTICK_TYPE_WIDTH_IN_BITS ) + #error Only one of configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +/* Define configTICK_TYPE_WIDTH_IN_BITS according to the + * value of configUSE_16_BIT_TICKS for backward compatibility. */ +#ifndef configTICK_TYPE_WIDTH_IN_BITS + #if ( configUSE_16_BIT_TICKS == 1 ) + #define configTICK_TYPE_WIDTH_IN_BITS TICK_TYPE_WIDTH_16_BITS + #else + #define configTICK_TYPE_WIDTH_IN_BITS TICK_TYPE_WIDTH_32_BITS + #endif +#endif + +/* Set configUSE_MPU_WRAPPERS_V1 to 1 to use MPU wrappers v1. */ +#ifndef configUSE_MPU_WRAPPERS_V1 + #define configUSE_MPU_WRAPPERS_V1 0 +#endif + +/* Set configENABLE_ACCESS_CONTROL_LIST to 1 to enable access control list support. */ +#ifndef configENABLE_ACCESS_CONTROL_LIST + #define configENABLE_ACCESS_CONTROL_LIST 0 +#endif + +/* Set default value of configNUMBER_OF_CORES to 1 to use single core FreeRTOS. */ +#ifndef configNUMBER_OF_CORES + #define configNUMBER_OF_CORES 1 +#endif + /* Basic FreeRTOS definitions. */ #include "projdefs.h" @@ -69,18 +113,44 @@ /* Required if struct _reent is used. */ #if ( configUSE_NEWLIB_REENTRANT == 1 ) - #include + + #include "newlib-freertos.h" + +#endif /* if ( configUSE_NEWLIB_REENTRANT == 1 ) */ + +/* Must be defaulted before configUSE_PICOLIBC_TLS is used below. */ +#ifndef configUSE_PICOLIBC_TLS + #define configUSE_PICOLIBC_TLS 0 #endif -#ifdef configNEWLIB_REENTRANT_IS_DYNAMIC - #if configNEWLIB_REENTRANT_IS_DYNAMIC == 1 - #if ( configUSE_NEWLIB_REENTRANT != 1 ) - #error configUSE_NEWLIB_REENTRANT must be defined to 1 to enable configNEWLIB_REENTRANT_IS_DYNAMIC - #endif +#if ( configUSE_PICOLIBC_TLS == 1 ) + + #include "picolibc-freertos.h" + +#endif /* if ( configUSE_PICOLIBC_TLS == 1 ) */ + +#ifndef configUSE_C_RUNTIME_TLS_SUPPORT + #define configUSE_C_RUNTIME_TLS_SUPPORT 0 +#endif + +#if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) + + #ifndef configTLS_BLOCK_TYPE + #error Missing definition: configTLS_BLOCK_TYPE must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1. #endif -#else /* configNEWLIB_REENTRANT_IS_DYNAMIC */ - #define configNEWLIB_REENTRANT_IS_DYNAMIC 0 -#endif /* configNEWLIB_REENTRANT_IS_DYNAMIC */ + + #ifndef configINIT_TLS_BLOCK + #error Missing definition: configINIT_TLS_BLOCK must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1. + #endif + + #ifndef configSET_TLS_BLOCK + #error Missing definition: configSET_TLS_BLOCK must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1. + #endif + + #ifndef configDEINIT_TLS_BLOCK + #error Missing definition: configDEINIT_TLS_BLOCK must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1. + #endif +#endif /* if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) */ /* * Check all the required application specific macros have been defined. @@ -108,12 +178,20 @@ #error Missing definition: configUSE_IDLE_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #endif +#if ( configNUMBER_OF_CORES > 1 ) + #ifndef configUSE_PASSIVE_IDLE_HOOK + #error Missing definition: configUSE_PASSIVE_IDLE_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. + #endif +#endif + #ifndef configUSE_TICK_HOOK #error Missing definition: configUSE_TICK_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #endif -#ifndef configUSE_16_BIT_TICKS - #error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#if ( ( configTICK_TYPE_WIDTH_IN_BITS != TICK_TYPE_WIDTH_16_BITS ) && \ + ( configTICK_TYPE_WIDTH_IN_BITS != TICK_TYPE_WIDTH_32_BITS ) && \ + ( configTICK_TYPE_WIDTH_IN_BITS != TICK_TYPE_WIDTH_64_BITS ) ) + #error Macro configTICK_TYPE_WIDTH_IN_BITS is defined to incorrect value. See the Configuration section of the FreeRTOS API documentation for details. #endif #ifndef configUSE_CO_ROUTINES @@ -138,21 +216,23 @@ #ifdef INCLUDE_xTaskDelayUntil #ifdef INCLUDE_vTaskDelayUntil - /* INCLUDE_vTaskDelayUntil was replaced by INCLUDE_xTaskDelayUntil. Backward - * compatibility is maintained if only one or the other is defined, but - * there is a conflict if both are defined. */ + +/* INCLUDE_vTaskDelayUntil was replaced by INCLUDE_xTaskDelayUntil. Backward + * compatibility is maintained if only one or the other is defined, but + * there is a conflict if both are defined. */ #error INCLUDE_vTaskDelayUntil and INCLUDE_xTaskDelayUntil are both defined. INCLUDE_vTaskDelayUntil is no longer required and should be removed #endif #endif #ifndef INCLUDE_xTaskDelayUntil #ifdef INCLUDE_vTaskDelayUntil - /* If INCLUDE_vTaskDelayUntil is set but INCLUDE_xTaskDelayUntil is not then - * the project's FreeRTOSConfig.h probably pre-dates the introduction of - * xTaskDelayUntil and setting INCLUDE_xTaskDelayUntil to whatever - * INCLUDE_vTaskDelayUntil is set to will ensure backward compatibility. - */ - #define INCLUDE_xTaskDelayUntil INCLUDE_vTaskDelayUntil + +/* If INCLUDE_vTaskDelayUntil is set but INCLUDE_xTaskDelayUntil is not then + * the project's FreeRTOSConfig.h probably pre-dates the introduction of + * xTaskDelayUntil and setting INCLUDE_xTaskDelayUntil to whatever + * INCLUDE_vTaskDelayUntil is set to will ensure backward compatibility. + */ + #define INCLUDE_xTaskDelayUntil INCLUDE_vTaskDelayUntil #endif #endif @@ -209,7 +289,7 @@ #endif #ifndef INCLUDE_xTaskGetCurrentTaskHandle - #define INCLUDE_xTaskGetCurrentTaskHandle 0 + #define INCLUDE_xTaskGetCurrentTaskHandle 1 #endif #if configUSE_CO_ROUTINES != 0 @@ -250,10 +330,6 @@ #define configUSE_TASK_PREEMPTION_DISABLE 0 #endif -#ifndef configUSE_CORE_AFFINITY - #define configUSE_CORE_AFFINITY 0 -#endif - #ifndef configUSE_ALTERNATIVE_API #define configUSE_ALTERNATIVE_API 0 #endif @@ -293,6 +369,17 @@ #define configPRECONDITION_DEFINED 1 #endif +#ifndef configCHECK_HANDLER_INSTALLATION + #define configCHECK_HANDLER_INSTALLATION 1 +#else + +/* The application has explicitly defined configCHECK_HANDLER_INSTALLATION + * to 1. The checks requires configASSERT() to be defined. */ + #if ( ( configCHECK_HANDLER_INSTALLATION == 1 ) && ( configASSERT_DEFINED == 0 ) ) + #error You must define configASSERT() when configCHECK_HANDLER_INSTALLATION is 1. + #endif +#endif + #ifndef portMEMORY_BARRIER #define portMEMORY_BARRIER() #endif @@ -301,14 +388,109 @@ #define portSOFTWARE_BARRIER() #endif -#ifndef configNUM_CORES - #define configNUM_CORES 1 -#endif - #ifndef configRUN_MULTIPLE_PRIORITIES #define configRUN_MULTIPLE_PRIORITIES 0 #endif +#ifndef portGET_CORE_ID + + #if ( configNUMBER_OF_CORES == 1 ) + #define portGET_CORE_ID() 0 + #else + #error configNUMBER_OF_CORES is set to more than 1 then portGET_CORE_ID must also be defined. + #endif /* configNUMBER_OF_CORES */ + +#endif /* portGET_CORE_ID */ + +#ifndef portYIELD_CORE + + #if ( configNUMBER_OF_CORES == 1 ) + #define portYIELD_CORE( x ) portYIELD() + #else + #error configNUMBER_OF_CORES is set to more than 1 then portYIELD_CORE must also be defined. + #endif /* configNUMBER_OF_CORES */ + +#endif /* portYIELD_CORE */ + +#ifndef portSET_INTERRUPT_MASK + + #if ( configNUMBER_OF_CORES > 1 ) + #error portSET_INTERRUPT_MASK is required in SMP + #endif + +#endif /* portSET_INTERRUPT_MASK */ + +#ifndef portCLEAR_INTERRUPT_MASK + + #if ( configNUMBER_OF_CORES > 1 ) + #error portCLEAR_INTERRUPT_MASK is required in SMP + #endif + +#endif /* portCLEAR_INTERRUPT_MASK */ + +#ifndef portRELEASE_TASK_LOCK + + #if ( configNUMBER_OF_CORES == 1 ) + #define portRELEASE_TASK_LOCK() + #else + #error portRELEASE_TASK_LOCK is required in SMP + #endif + +#endif /* portRELEASE_TASK_LOCK */ + +#ifndef portGET_TASK_LOCK + + #if ( configNUMBER_OF_CORES == 1 ) + #define portGET_TASK_LOCK() + #else + #error portGET_TASK_LOCK is required in SMP + #endif + +#endif /* portGET_TASK_LOCK */ + +#ifndef portRELEASE_ISR_LOCK + + #if ( configNUMBER_OF_CORES == 1 ) + #define portRELEASE_ISR_LOCK() + #else + #error portRELEASE_ISR_LOCK is required in SMP + #endif + +#endif /* portRELEASE_ISR_LOCK */ + +#ifndef portGET_ISR_LOCK + + #if ( configNUMBER_OF_CORES == 1 ) + #define portGET_ISR_LOCK() + #else + #error portGET_ISR_LOCK is required in SMP + #endif + +#endif /* portGET_ISR_LOCK */ + +#ifndef portENTER_CRITICAL_FROM_ISR + + #if ( configNUMBER_OF_CORES > 1 ) + #error portENTER_CRITICAL_FROM_ISR is required in SMP + #endif + +#endif + +#ifndef portEXIT_CRITICAL_FROM_ISR + + #if ( configNUMBER_OF_CORES > 1 ) + #error portEXIT_CRITICAL_FROM_ISR is required in SMP + #endif + +#endif + +#ifndef configUSE_CORE_AFFINITY + #define configUSE_CORE_AFFINITY 0 +#endif /* configUSE_CORE_AFFINITY */ + +#ifndef configUSE_PASSIVE_IDLE_HOOK + #define configUSE_PASSIVE_IDLE_HOOK 0 +#endif /* configUSE_PASSIVE_IDLE_HOOK */ /* The timers module relies on xTaskGetSchedulerState(). */ #if configUSE_TIMERS == 1 @@ -336,11 +518,11 @@ #endif #ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue + #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) ( uxSavedStatusValue ) #endif #ifndef portCLEAN_UP_TCB - #define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB + #define portCLEAN_UP_TCB( pxTCB ) ( void ) ( pxTCB ) #endif #ifndef portPRE_TASK_DELETE_HOOK @@ -348,7 +530,11 @@ #endif #ifndef portSETUP_TCB - #define portSETUP_TCB( pxTCB ) ( void ) pxTCB + #define portSETUP_TCB( pxTCB ) ( void ) ( pxTCB ) +#endif + +#ifndef portTASK_SWITCH_HOOK + #define portTASK_SWITCH_HOOK( pxTCB ) ( void ) ( pxTCB ) #endif #ifndef configQUEUE_REGISTRY_SIZE @@ -361,6 +547,10 @@ #define pcQueueGetName( xQueue ) #endif +#ifndef configUSE_MINI_LIST_ITEM + #define configUSE_MINI_LIST_ITEM 1 +#endif + #ifndef portPOINTER_SIZE_TYPE #define portPOINTER_SIZE_TYPE uint32_t #endif @@ -479,6 +669,14 @@ #define tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB ) #endif +#ifndef traceMOVED_TASK_TO_DELAYED_LIST + #define traceMOVED_TASK_TO_DELAYED_LIST() +#endif + +#ifndef traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST + #define traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST() +#endif + #ifndef traceQUEUE_CREATE #define traceQUEUE_CREATE( pxNewQueue ) #endif @@ -656,7 +854,7 @@ #endif #ifndef traceEVENT_GROUP_SYNC_END - #define traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred + #define traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) ( xTimeoutOccurred ) #endif #ifndef traceEVENT_GROUP_WAIT_BITS_BLOCK @@ -664,7 +862,7 @@ #endif #ifndef traceEVENT_GROUP_WAIT_BITS_END - #define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred + #define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) ( xTimeoutOccurred ) #endif #ifndef traceEVENT_GROUP_CLEAR_BITS @@ -727,6 +925,18 @@ #define traceTASK_NOTIFY_GIVE_FROM_ISR( uxIndexToNotify ) #endif +#ifndef traceISR_EXIT_TO_SCHEDULER + #define traceISR_EXIT_TO_SCHEDULER() +#endif + +#ifndef traceISR_EXIT + #define traceISR_EXIT() +#endif + +#ifndef traceISR_ENTER + #define traceISR_ENTER() +#endif + #ifndef traceSTREAM_BUFFER_CREATE_FAILED #define traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ) #endif @@ -779,6 +989,1602 @@ #define traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength ) #endif +#ifndef traceENTER_xEventGroupCreateStatic + #define traceENTER_xEventGroupCreateStatic( pxEventGroupBuffer ) +#endif + +#ifndef traceRETURN_xEventGroupCreateStatic + #define traceRETURN_xEventGroupCreateStatic( pxEventBits ) +#endif + +#ifndef traceENTER_xEventGroupCreate + #define traceENTER_xEventGroupCreate() +#endif + +#ifndef traceRETURN_xEventGroupCreate + #define traceRETURN_xEventGroupCreate( pxEventBits ) +#endif + +#ifndef traceENTER_xEventGroupSync + #define traceENTER_xEventGroupSync( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTicksToWait ) +#endif + +#ifndef traceRETURN_xEventGroupSync + #define traceRETURN_xEventGroupSync( uxReturn ) +#endif + +#ifndef traceENTER_xEventGroupWaitBits + #define traceENTER_xEventGroupWaitBits( xEventGroup, uxBitsToWaitFor, xClearOnExit, xWaitForAllBits, xTicksToWait ) +#endif + +#ifndef traceRETURN_xEventGroupWaitBits + #define traceRETURN_xEventGroupWaitBits( uxReturn ) +#endif + +#ifndef traceENTER_xEventGroupClearBits + #define traceENTER_xEventGroupClearBits( xEventGroup, uxBitsToClear ) +#endif + +#ifndef traceRETURN_xEventGroupClearBits + #define traceRETURN_xEventGroupClearBits( uxReturn ) +#endif + +#ifndef traceENTER_xEventGroupClearBitsFromISR + #define traceENTER_xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) +#endif + +#ifndef traceRETURN_xEventGroupClearBitsFromISR + #define traceRETURN_xEventGroupClearBitsFromISR( xReturn ) +#endif + +#ifndef traceENTER_xEventGroupGetBitsFromISR + #define traceENTER_xEventGroupGetBitsFromISR( xEventGroup ) +#endif + +#ifndef traceRETURN_xEventGroupGetBitsFromISR + #define traceRETURN_xEventGroupGetBitsFromISR( uxReturn ) +#endif + +#ifndef traceENTER_xEventGroupSetBits + #define traceENTER_xEventGroupSetBits( xEventGroup, uxBitsToSet ) +#endif + +#ifndef traceRETURN_xEventGroupSetBits + #define traceRETURN_xEventGroupSetBits( uxEventBits ) +#endif + +#ifndef traceENTER_vEventGroupDelete + #define traceENTER_vEventGroupDelete( xEventGroup ) +#endif + +#ifndef traceRETURN_vEventGroupDelete + #define traceRETURN_vEventGroupDelete() +#endif + +#ifndef traceENTER_xEventGroupGetStaticBuffer + #define traceENTER_xEventGroupGetStaticBuffer( xEventGroup, ppxEventGroupBuffer ) +#endif + +#ifndef traceRETURN_xEventGroupGetStaticBuffer + #define traceRETURN_xEventGroupGetStaticBuffer( xReturn ) +#endif + +#ifndef traceENTER_vEventGroupSetBitsCallback + #define traceENTER_vEventGroupSetBitsCallback( pvEventGroup, ulBitsToSet ) +#endif + +#ifndef traceRETURN_vEventGroupSetBitsCallback + #define traceRETURN_vEventGroupSetBitsCallback() +#endif + +#ifndef traceENTER_vEventGroupClearBitsCallback + #define traceENTER_vEventGroupClearBitsCallback( pvEventGroup, ulBitsToClear ) +#endif + +#ifndef traceRETURN_vEventGroupClearBitsCallback + #define traceRETURN_vEventGroupClearBitsCallback() +#endif + +#ifndef traceENTER_xEventGroupSetBitsFromISR + #define traceENTER_xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_xEventGroupSetBitsFromISR + #define traceRETURN_xEventGroupSetBitsFromISR( xReturn ) +#endif + +#ifndef traceENTER_uxEventGroupGetNumber + #define traceENTER_uxEventGroupGetNumber( xEventGroup ) +#endif + +#ifndef traceRETURN_uxEventGroupGetNumber + #define traceRETURN_uxEventGroupGetNumber( xReturn ) +#endif + +#ifndef traceENTER_vEventGroupSetNumber + #define traceENTER_vEventGroupSetNumber( xEventGroup, uxEventGroupNumber ) +#endif + +#ifndef traceRETURN_vEventGroupSetNumber + #define traceRETURN_vEventGroupSetNumber() +#endif + +#ifndef traceENTER_xQueueGenericReset + #define traceENTER_xQueueGenericReset( xQueue, xNewQueue ) +#endif + +#ifndef traceRETURN_xQueueGenericReset + #define traceRETURN_xQueueGenericReset( xReturn ) +#endif + +#ifndef traceENTER_xQueueGenericCreateStatic + #define traceENTER_xQueueGenericCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxStaticQueue, ucQueueType ) +#endif + +#ifndef traceRETURN_xQueueGenericCreateStatic + #define traceRETURN_xQueueGenericCreateStatic( pxNewQueue ) +#endif + +#ifndef traceENTER_xQueueGenericGetStaticBuffers + #define traceENTER_xQueueGenericGetStaticBuffers( xQueue, ppucQueueStorage, ppxStaticQueue ) +#endif + +#ifndef traceRETURN_xQueueGenericGetStaticBuffers + #define traceRETURN_xQueueGenericGetStaticBuffers( xReturn ) +#endif + +#ifndef traceENTER_xQueueGenericCreate + #define traceENTER_xQueueGenericCreate( uxQueueLength, uxItemSize, ucQueueType ) +#endif + +#ifndef traceRETURN_xQueueGenericCreate + #define traceRETURN_xQueueGenericCreate( pxNewQueue ) +#endif + +#ifndef traceENTER_xQueueCreateMutex + #define traceENTER_xQueueCreateMutex( ucQueueType ) +#endif + +#ifndef traceRETURN_xQueueCreateMutex + #define traceRETURN_xQueueCreateMutex( xNewQueue ) +#endif + +#ifndef traceENTER_xQueueCreateMutexStatic + #define traceENTER_xQueueCreateMutexStatic( ucQueueType, pxStaticQueue ) +#endif + +#ifndef traceRETURN_xQueueCreateMutexStatic + #define traceRETURN_xQueueCreateMutexStatic( xNewQueue ) +#endif + +#ifndef traceENTER_xQueueGetMutexHolder + #define traceENTER_xQueueGetMutexHolder( xSemaphore ) +#endif + +#ifndef traceRETURN_xQueueGetMutexHolder + #define traceRETURN_xQueueGetMutexHolder( pxReturn ) +#endif + +#ifndef traceENTER_xQueueGetMutexHolderFromISR + #define traceENTER_xQueueGetMutexHolderFromISR( xSemaphore ) +#endif + +#ifndef traceRETURN_xQueueGetMutexHolderFromISR + #define traceRETURN_xQueueGetMutexHolderFromISR( pxReturn ) +#endif + +#ifndef traceENTER_xQueueGiveMutexRecursive + #define traceENTER_xQueueGiveMutexRecursive( xMutex ) +#endif + +#ifndef traceRETURN_xQueueGiveMutexRecursive + #define traceRETURN_xQueueGiveMutexRecursive( xReturn ) +#endif + +#ifndef traceENTER_xQueueTakeMutexRecursive + #define traceENTER_xQueueTakeMutexRecursive( xMutex, xTicksToWait ) +#endif + +#ifndef traceRETURN_xQueueTakeMutexRecursive + #define traceRETURN_xQueueTakeMutexRecursive( xReturn ) +#endif + +#ifndef traceENTER_xQueueCreateCountingSemaphoreStatic + #define traceENTER_xQueueCreateCountingSemaphoreStatic( uxMaxCount, uxInitialCount, pxStaticQueue ) +#endif + +#ifndef traceRETURN_xQueueCreateCountingSemaphoreStatic + #define traceRETURN_xQueueCreateCountingSemaphoreStatic( xHandle ) +#endif + +#ifndef traceENTER_xQueueCreateCountingSemaphore + #define traceENTER_xQueueCreateCountingSemaphore( uxMaxCount, uxInitialCount ) +#endif + +#ifndef traceRETURN_xQueueCreateCountingSemaphore + #define traceRETURN_xQueueCreateCountingSemaphore( xHandle ) +#endif + +#ifndef traceENTER_xQueueGenericSend + #define traceENTER_xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, xCopyPosition ) +#endif + +#ifndef traceRETURN_xQueueGenericSend + #define traceRETURN_xQueueGenericSend( xReturn ) +#endif + +#ifndef traceENTER_xQueueGenericSendFromISR + #define traceENTER_xQueueGenericSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken, xCopyPosition ) +#endif + +#ifndef traceRETURN_xQueueGenericSendFromISR + #define traceRETURN_xQueueGenericSendFromISR( xReturn ) +#endif + +#ifndef traceENTER_xQueueGiveFromISR + #define traceENTER_xQueueGiveFromISR( xQueue, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_xQueueGiveFromISR + #define traceRETURN_xQueueGiveFromISR( xReturn ) +#endif + +#ifndef traceENTER_xQueueReceive + #define traceENTER_xQueueReceive( xQueue, pvBuffer, xTicksToWait ) +#endif + +#ifndef traceRETURN_xQueueReceive + #define traceRETURN_xQueueReceive( xReturn ) +#endif + +#ifndef traceENTER_xQueueSemaphoreTake + #define traceENTER_xQueueSemaphoreTake( xQueue, xTicksToWait ) +#endif + +#ifndef traceRETURN_xQueueSemaphoreTake + #define traceRETURN_xQueueSemaphoreTake( xReturn ) +#endif + +#ifndef traceENTER_xQueuePeek + #define traceENTER_xQueuePeek( xQueue, pvBuffer, xTicksToWait ) +#endif + +#ifndef traceRETURN_xQueuePeek + #define traceRETURN_xQueuePeek( xReturn ) +#endif + +#ifndef traceENTER_xQueueReceiveFromISR + #define traceENTER_xQueueReceiveFromISR( xQueue, pvBuffer, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_xQueueReceiveFromISR + #define traceRETURN_xQueueReceiveFromISR( xReturn ) +#endif + +#ifndef traceENTER_xQueuePeekFromISR + #define traceENTER_xQueuePeekFromISR( xQueue, pvBuffer ) +#endif + +#ifndef traceRETURN_xQueuePeekFromISR + #define traceRETURN_xQueuePeekFromISR( xReturn ) +#endif + +#ifndef traceENTER_uxQueueMessagesWaiting + #define traceENTER_uxQueueMessagesWaiting( xQueue ) +#endif + +#ifndef traceRETURN_uxQueueMessagesWaiting + #define traceRETURN_uxQueueMessagesWaiting( uxReturn ) +#endif + +#ifndef traceENTER_uxQueueSpacesAvailable + #define traceENTER_uxQueueSpacesAvailable( xQueue ) +#endif + +#ifndef traceRETURN_uxQueueSpacesAvailable + #define traceRETURN_uxQueueSpacesAvailable( uxReturn ) +#endif + +#ifndef traceENTER_uxQueueMessagesWaitingFromISR + #define traceENTER_uxQueueMessagesWaitingFromISR( xQueue ) +#endif + +#ifndef traceRETURN_uxQueueMessagesWaitingFromISR + #define traceRETURN_uxQueueMessagesWaitingFromISR( uxReturn ) +#endif + +#ifndef traceENTER_vQueueDelete + #define traceENTER_vQueueDelete( xQueue ) +#endif + +#ifndef traceRETURN_vQueueDelete + #define traceRETURN_vQueueDelete() +#endif + +#ifndef traceENTER_uxQueueGetQueueNumber + #define traceENTER_uxQueueGetQueueNumber( xQueue ) +#endif + +#ifndef traceRETURN_uxQueueGetQueueNumber + #define traceRETURN_uxQueueGetQueueNumber( uxQueueNumber ) +#endif + +#ifndef traceENTER_vQueueSetQueueNumber + #define traceENTER_vQueueSetQueueNumber( xQueue, uxQueueNumber ) +#endif + +#ifndef traceRETURN_vQueueSetQueueNumber + #define traceRETURN_vQueueSetQueueNumber() +#endif + +#ifndef traceENTER_ucQueueGetQueueType + #define traceENTER_ucQueueGetQueueType( xQueue ) +#endif + +#ifndef traceRETURN_ucQueueGetQueueType + #define traceRETURN_ucQueueGetQueueType( ucQueueType ) +#endif + +#ifndef traceENTER_uxQueueGetQueueItemSize + #define traceENTER_uxQueueGetQueueItemSize( xQueue ) +#endif + +#ifndef traceRETURN_uxQueueGetQueueItemSize + #define traceRETURN_uxQueueGetQueueItemSize( uxItemSize ) +#endif + +#ifndef traceENTER_uxQueueGetQueueLength + #define traceENTER_uxQueueGetQueueLength( xQueue ) +#endif + +#ifndef traceRETURN_uxQueueGetQueueLength + #define traceRETURN_uxQueueGetQueueLength( uxLength ) +#endif + +#ifndef traceENTER_xQueueIsQueueEmptyFromISR + #define traceENTER_xQueueIsQueueEmptyFromISR( xQueue ) +#endif + +#ifndef traceRETURN_xQueueIsQueueEmptyFromISR + #define traceRETURN_xQueueIsQueueEmptyFromISR( xReturn ) +#endif + +#ifndef traceENTER_xQueueIsQueueFullFromISR + #define traceENTER_xQueueIsQueueFullFromISR( xQueue ) +#endif + +#ifndef traceRETURN_xQueueIsQueueFullFromISR + #define traceRETURN_xQueueIsQueueFullFromISR( xReturn ) +#endif + +#ifndef traceENTER_xQueueCRSend + #define traceENTER_xQueueCRSend( xQueue, pvItemToQueue, xTicksToWait ) +#endif + +#ifndef traceRETURN_xQueueCRSend + #define traceRETURN_xQueueCRSend( xReturn ) +#endif + +#ifndef traceENTER_xQueueCRReceive + #define traceENTER_xQueueCRReceive( xQueue, pvBuffer, xTicksToWait ) +#endif + +#ifndef traceRETURN_xQueueCRReceive + #define traceRETURN_xQueueCRReceive( xReturn ) +#endif + +#ifndef traceENTER_xQueueCRSendFromISR + #define traceENTER_xQueueCRSendFromISR( xQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) +#endif + +#ifndef traceRETURN_xQueueCRSendFromISR + #define traceRETURN_xQueueCRSendFromISR( xCoRoutinePreviouslyWoken ) +#endif + +#ifndef traceENTER_xQueueCRReceiveFromISR + #define traceENTER_xQueueCRReceiveFromISR( xQueue, pvBuffer, pxCoRoutineWoken ) +#endif + +#ifndef traceRETURN_xQueueCRReceiveFromISR + #define traceRETURN_xQueueCRReceiveFromISR( xReturn ) +#endif + +#ifndef traceENTER_vQueueAddToRegistry + #define traceENTER_vQueueAddToRegistry( xQueue, pcQueueName ) +#endif + +#ifndef traceRETURN_vQueueAddToRegistry + #define traceRETURN_vQueueAddToRegistry() +#endif + +#ifndef traceENTER_pcQueueGetName + #define traceENTER_pcQueueGetName( xQueue ) +#endif + +#ifndef traceRETURN_pcQueueGetName + #define traceRETURN_pcQueueGetName( pcReturn ) +#endif + +#ifndef traceENTER_vQueueUnregisterQueue + #define traceENTER_vQueueUnregisterQueue( xQueue ) +#endif + +#ifndef traceRETURN_vQueueUnregisterQueue + #define traceRETURN_vQueueUnregisterQueue() +#endif + +#ifndef traceENTER_vQueueWaitForMessageRestricted + #define traceENTER_vQueueWaitForMessageRestricted( xQueue, xTicksToWait, xWaitIndefinitely ) +#endif + +#ifndef traceRETURN_vQueueWaitForMessageRestricted + #define traceRETURN_vQueueWaitForMessageRestricted() +#endif + +#ifndef traceENTER_xQueueCreateSet + #define traceENTER_xQueueCreateSet( uxEventQueueLength ) +#endif + +#ifndef traceRETURN_xQueueCreateSet + #define traceRETURN_xQueueCreateSet( pxQueue ) +#endif + +#ifndef traceENTER_xQueueAddToSet + #define traceENTER_xQueueAddToSet( xQueueOrSemaphore, xQueueSet ) +#endif + +#ifndef traceRETURN_xQueueAddToSet + #define traceRETURN_xQueueAddToSet( xReturn ) +#endif + +#ifndef traceENTER_xQueueRemoveFromSet + #define traceENTER_xQueueRemoveFromSet( xQueueOrSemaphore, xQueueSet ) +#endif + +#ifndef traceRETURN_xQueueRemoveFromSet + #define traceRETURN_xQueueRemoveFromSet( xReturn ) +#endif + +#ifndef traceENTER_xQueueSelectFromSet + #define traceENTER_xQueueSelectFromSet( xQueueSet, xTicksToWait ) +#endif + +#ifndef traceRETURN_xQueueSelectFromSet + #define traceRETURN_xQueueSelectFromSet( xReturn ) +#endif + +#ifndef traceENTER_xQueueSelectFromSetFromISR + #define traceENTER_xQueueSelectFromSetFromISR( xQueueSet ) +#endif + +#ifndef traceRETURN_xQueueSelectFromSetFromISR + #define traceRETURN_xQueueSelectFromSetFromISR( xReturn ) +#endif + +#ifndef traceENTER_xTimerCreateTimerTask + #define traceENTER_xTimerCreateTimerTask() +#endif + +#ifndef traceRETURN_xTimerCreateTimerTask + #define traceRETURN_xTimerCreateTimerTask( xReturn ) +#endif + +#ifndef traceENTER_xTimerCreate + #define traceENTER_xTimerCreate( pcTimerName, xTimerPeriodInTicks, xAutoReload, pvTimerID, pxCallbackFunction ) +#endif + +#ifndef traceRETURN_xTimerCreate + #define traceRETURN_xTimerCreate( pxNewTimer ) +#endif + +#ifndef traceENTER_xTimerCreateStatic + #define traceENTER_xTimerCreateStatic( pcTimerName, xTimerPeriodInTicks, xAutoReload, pvTimerID, pxCallbackFunction, pxTimerBuffer ) +#endif + +#ifndef traceRETURN_xTimerCreateStatic + #define traceRETURN_xTimerCreateStatic( pxNewTimer ) +#endif + +#ifndef traceENTER_xTimerGenericCommandFromTask + #define traceENTER_xTimerGenericCommandFromTask( xTimer, xCommandID, xOptionalValue, pxHigherPriorityTaskWoken, xTicksToWait ) +#endif + +#ifndef traceRETURN_xTimerGenericCommandFromTask + #define traceRETURN_xTimerGenericCommandFromTask( xReturn ) +#endif + +#ifndef traceENTER_xTimerGenericCommandFromISR + #define traceENTER_xTimerGenericCommandFromISR( xTimer, xCommandID, xOptionalValue, pxHigherPriorityTaskWoken, xTicksToWait ) +#endif + +#ifndef traceRETURN_xTimerGenericCommandFromISR + #define traceRETURN_xTimerGenericCommandFromISR( xReturn ) +#endif + +#ifndef traceENTER_xTimerGetTimerDaemonTaskHandle + #define traceENTER_xTimerGetTimerDaemonTaskHandle() +#endif + +#ifndef traceRETURN_xTimerGetTimerDaemonTaskHandle + #define traceRETURN_xTimerGetTimerDaemonTaskHandle( xTimerTaskHandle ) +#endif + +#ifndef traceENTER_xTimerGetPeriod + #define traceENTER_xTimerGetPeriod( xTimer ) +#endif + +#ifndef traceRETURN_xTimerGetPeriod + #define traceRETURN_xTimerGetPeriod( xTimerPeriodInTicks ) +#endif + +#ifndef traceENTER_vTimerSetReloadMode + #define traceENTER_vTimerSetReloadMode( xTimer, xAutoReload ) +#endif + +#ifndef traceRETURN_vTimerSetReloadMode + #define traceRETURN_vTimerSetReloadMode() +#endif + +#ifndef traceENTER_xTimerGetReloadMode + #define traceENTER_xTimerGetReloadMode( xTimer ) +#endif + +#ifndef traceRETURN_xTimerGetReloadMode + #define traceRETURN_xTimerGetReloadMode( xReturn ) +#endif + +#ifndef traceENTER_uxTimerGetReloadMode + #define traceENTER_uxTimerGetReloadMode( xTimer ) +#endif + +#ifndef traceRETURN_uxTimerGetReloadMode + #define traceRETURN_uxTimerGetReloadMode( uxReturn ) +#endif + +#ifndef traceENTER_xTimerGetExpiryTime + #define traceENTER_xTimerGetExpiryTime( xTimer ) +#endif + +#ifndef traceRETURN_xTimerGetExpiryTime + #define traceRETURN_xTimerGetExpiryTime( xReturn ) +#endif + +#ifndef traceENTER_xTimerGetStaticBuffer + #define traceENTER_xTimerGetStaticBuffer( xTimer, ppxTimerBuffer ) +#endif + +#ifndef traceRETURN_xTimerGetStaticBuffer + #define traceRETURN_xTimerGetStaticBuffer( xReturn ) +#endif + +#ifndef traceENTER_pcTimerGetName + #define traceENTER_pcTimerGetName( xTimer ) +#endif + +#ifndef traceRETURN_pcTimerGetName + #define traceRETURN_pcTimerGetName( pcTimerName ) +#endif + +#ifndef traceENTER_xTimerIsTimerActive + #define traceENTER_xTimerIsTimerActive( xTimer ) +#endif + +#ifndef traceRETURN_xTimerIsTimerActive + #define traceRETURN_xTimerIsTimerActive( xReturn ) +#endif + +#ifndef traceENTER_pvTimerGetTimerID + #define traceENTER_pvTimerGetTimerID( xTimer ) +#endif + +#ifndef traceRETURN_pvTimerGetTimerID + #define traceRETURN_pvTimerGetTimerID( pvReturn ) +#endif + +#ifndef traceENTER_vTimerSetTimerID + #define traceENTER_vTimerSetTimerID( xTimer, pvNewID ) +#endif + +#ifndef traceRETURN_vTimerSetTimerID + #define traceRETURN_vTimerSetTimerID() +#endif + +#ifndef traceENTER_xTimerPendFunctionCallFromISR + #define traceENTER_xTimerPendFunctionCallFromISR( xFunctionToPend, pvParameter1, ulParameter2, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_xTimerPendFunctionCallFromISR + #define traceRETURN_xTimerPendFunctionCallFromISR( xReturn ) +#endif + +#ifndef traceENTER_xTimerPendFunctionCall + #define traceENTER_xTimerPendFunctionCall( xFunctionToPend, pvParameter1, ulParameter2, xTicksToWait ) +#endif + +#ifndef traceRETURN_xTimerPendFunctionCall + #define traceRETURN_xTimerPendFunctionCall( xReturn ) +#endif + +#ifndef traceENTER_uxTimerGetTimerNumber + #define traceENTER_uxTimerGetTimerNumber( xTimer ) +#endif + +#ifndef traceRETURN_uxTimerGetTimerNumber + #define traceRETURN_uxTimerGetTimerNumber( uxTimerNumber ) +#endif + +#ifndef traceENTER_vTimerSetTimerNumber + #define traceENTER_vTimerSetTimerNumber( xTimer, uxTimerNumber ) +#endif + +#ifndef traceRETURN_vTimerSetTimerNumber + #define traceRETURN_vTimerSetTimerNumber() +#endif + +#ifndef traceENTER_xTaskCreateStatic + #define traceENTER_xTaskCreateStatic( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer ) +#endif + +#ifndef traceRETURN_xTaskCreateStatic + #define traceRETURN_xTaskCreateStatic( xReturn ) +#endif + +#ifndef traceENTER_xTaskCreateStaticAffinitySet + #define traceENTER_xTaskCreateStaticAffinitySet( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer, uxCoreAffinityMask ) +#endif + +#ifndef traceRETURN_xTaskCreateStaticAffinitySet + #define traceRETURN_xTaskCreateStaticAffinitySet( xReturn ) +#endif + +#ifndef traceENTER_xTaskCreateRestrictedStatic + #define traceENTER_xTaskCreateRestrictedStatic( pxTaskDefinition, pxCreatedTask ) +#endif + +#ifndef traceRETURN_xTaskCreateRestrictedStatic + #define traceRETURN_xTaskCreateRestrictedStatic( xReturn ) +#endif + +#ifndef traceENTER_xTaskCreateRestrictedStaticAffinitySet + #define traceENTER_xTaskCreateRestrictedStaticAffinitySet( pxTaskDefinition, uxCoreAffinityMask, pxCreatedTask ) +#endif + +#ifndef traceRETURN_xTaskCreateRestrictedStaticAffinitySet + #define traceRETURN_xTaskCreateRestrictedStaticAffinitySet( xReturn ) +#endif + +#ifndef traceENTER_xTaskCreateRestricted + #define traceENTER_xTaskCreateRestricted( pxTaskDefinition, pxCreatedTask ) +#endif + +#ifndef traceRETURN_xTaskCreateRestricted + #define traceRETURN_xTaskCreateRestricted( xReturn ) +#endif + +#ifndef traceENTER_xTaskCreateRestrictedAffinitySet + #define traceENTER_xTaskCreateRestrictedAffinitySet( pxTaskDefinition, uxCoreAffinityMask, pxCreatedTask ) +#endif + +#ifndef traceRETURN_xTaskCreateRestrictedAffinitySet + #define traceRETURN_xTaskCreateRestrictedAffinitySet( xReturn ) +#endif + +#ifndef traceENTER_xTaskCreate + #define traceENTER_xTaskCreate( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ) +#endif + +#ifndef traceRETURN_xTaskCreate + #define traceRETURN_xTaskCreate( xReturn ) +#endif + +#ifndef traceENTER_xTaskCreateAffinitySet + #define traceENTER_xTaskCreateAffinitySet( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, uxCoreAffinityMask, pxCreatedTask ) +#endif + +#ifndef traceRETURN_xTaskCreateAffinitySet + #define traceRETURN_xTaskCreateAffinitySet( xReturn ) +#endif + +#ifndef traceENTER_vTaskDelete + #define traceENTER_vTaskDelete( xTaskToDelete ) +#endif + +#ifndef traceRETURN_vTaskDelete + #define traceRETURN_vTaskDelete() +#endif + +#ifndef traceENTER_xTaskDelayUntil + #define traceENTER_xTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ) +#endif + +#ifndef traceRETURN_xTaskDelayUntil + #define traceRETURN_xTaskDelayUntil( xShouldDelay ) +#endif + +#ifndef traceENTER_vTaskDelay + #define traceENTER_vTaskDelay( xTicksToDelay ) +#endif + +#ifndef traceRETURN_vTaskDelay + #define traceRETURN_vTaskDelay() +#endif + +#ifndef traceENTER_eTaskGetState + #define traceENTER_eTaskGetState( xTask ) +#endif + +#ifndef traceRETURN_eTaskGetState + #define traceRETURN_eTaskGetState( eReturn ) +#endif + +#ifndef traceENTER_uxTaskPriorityGet + #define traceENTER_uxTaskPriorityGet( xTask ) +#endif + +#ifndef traceRETURN_uxTaskPriorityGet + #define traceRETURN_uxTaskPriorityGet( uxReturn ) +#endif + +#ifndef traceENTER_uxTaskPriorityGetFromISR + #define traceENTER_uxTaskPriorityGetFromISR( xTask ) +#endif + +#ifndef traceRETURN_uxTaskPriorityGetFromISR + #define traceRETURN_uxTaskPriorityGetFromISR( uxReturn ) +#endif + +#ifndef traceENTER_uxTaskBasePriorityGet + #define traceENTER_uxTaskBasePriorityGet( xTask ) +#endif + +#ifndef traceRETURN_uxTaskBasePriorityGet + #define traceRETURN_uxTaskBasePriorityGet( uxReturn ) +#endif + +#ifndef traceENTER_uxTaskBasePriorityGetFromISR + #define traceENTER_uxTaskBasePriorityGetFromISR( xTask ) +#endif + +#ifndef traceRETURN_uxTaskBasePriorityGetFromISR + #define traceRETURN_uxTaskBasePriorityGetFromISR( uxReturn ) +#endif + +#ifndef traceENTER_vTaskPrioritySet + #define traceENTER_vTaskPrioritySet( xTask, uxNewPriority ) +#endif + +#ifndef traceRETURN_vTaskPrioritySet + #define traceRETURN_vTaskPrioritySet() +#endif + +#ifndef traceENTER_vTaskCoreAffinitySet + #define traceENTER_vTaskCoreAffinitySet( xTask, uxCoreAffinityMask ) +#endif + +#ifndef traceRETURN_vTaskCoreAffinitySet + #define traceRETURN_vTaskCoreAffinitySet() +#endif + +#ifndef traceENTER_vTaskCoreAffinityGet + #define traceENTER_vTaskCoreAffinityGet( xTask ) +#endif + +#ifndef traceRETURN_vTaskCoreAffinityGet + #define traceRETURN_vTaskCoreAffinityGet( uxCoreAffinityMask ) +#endif + +#ifndef traceENTER_vTaskPreemptionDisable + #define traceENTER_vTaskPreemptionDisable( xTask ) +#endif + +#ifndef traceRETURN_vTaskPreemptionDisable + #define traceRETURN_vTaskPreemptionDisable() +#endif + +#ifndef traceENTER_vTaskPreemptionEnable + #define traceENTER_vTaskPreemptionEnable( xTask ) +#endif + +#ifndef traceRETURN_vTaskPreemptionEnable + #define traceRETURN_vTaskPreemptionEnable() +#endif + +#ifndef traceENTER_vTaskSuspend + #define traceENTER_vTaskSuspend( xTaskToSuspend ) +#endif + +#ifndef traceRETURN_vTaskSuspend + #define traceRETURN_vTaskSuspend() +#endif + +#ifndef traceENTER_vTaskResume + #define traceENTER_vTaskResume( xTaskToResume ) +#endif + +#ifndef traceRETURN_vTaskResume + #define traceRETURN_vTaskResume() +#endif + +#ifndef traceENTER_xTaskResumeFromISR + #define traceENTER_xTaskResumeFromISR( xTaskToResume ) +#endif + +#ifndef traceRETURN_xTaskResumeFromISR + #define traceRETURN_xTaskResumeFromISR( xYieldRequired ) +#endif + +#ifndef traceENTER_vTaskStartScheduler + #define traceENTER_vTaskStartScheduler() +#endif + +#ifndef traceRETURN_vTaskStartScheduler + #define traceRETURN_vTaskStartScheduler() +#endif + +#ifndef traceENTER_vTaskEndScheduler + #define traceENTER_vTaskEndScheduler() +#endif + +#ifndef traceRETURN_vTaskEndScheduler + #define traceRETURN_vTaskEndScheduler() +#endif + +#ifndef traceENTER_vTaskSuspendAll + #define traceENTER_vTaskSuspendAll() +#endif + +#ifndef traceRETURN_vTaskSuspendAll + #define traceRETURN_vTaskSuspendAll() +#endif + +#ifndef traceENTER_xTaskResumeAll + #define traceENTER_xTaskResumeAll() +#endif + +#ifndef traceRETURN_xTaskResumeAll + #define traceRETURN_xTaskResumeAll( xAlreadyYielded ) +#endif + +#ifndef traceENTER_xTaskGetTickCount + #define traceENTER_xTaskGetTickCount() +#endif + +#ifndef traceRETURN_xTaskGetTickCount + #define traceRETURN_xTaskGetTickCount( xTicks ) +#endif + +#ifndef traceENTER_xTaskGetTickCountFromISR + #define traceENTER_xTaskGetTickCountFromISR() +#endif + +#ifndef traceRETURN_xTaskGetTickCountFromISR + #define traceRETURN_xTaskGetTickCountFromISR( xReturn ) +#endif + +#ifndef traceENTER_uxTaskGetNumberOfTasks + #define traceENTER_uxTaskGetNumberOfTasks() +#endif + +#ifndef traceRETURN_uxTaskGetNumberOfTasks + #define traceRETURN_uxTaskGetNumberOfTasks( uxCurrentNumberOfTasks ) +#endif + +#ifndef traceENTER_pcTaskGetName + #define traceENTER_pcTaskGetName( xTaskToQuery ) +#endif + +#ifndef traceRETURN_pcTaskGetName + #define traceRETURN_pcTaskGetName( pcTaskName ) +#endif + +#ifndef traceENTER_xTaskGetHandle + #define traceENTER_xTaskGetHandle( pcNameToQuery ) +#endif + +#ifndef traceRETURN_xTaskGetHandle + #define traceRETURN_xTaskGetHandle( pxTCB ) +#endif + +#ifndef traceENTER_xTaskGetStaticBuffers + #define traceENTER_xTaskGetStaticBuffers( xTask, ppuxStackBuffer, ppxTaskBuffer ) +#endif + +#ifndef traceRETURN_xTaskGetStaticBuffers + #define traceRETURN_xTaskGetStaticBuffers( xReturn ) +#endif + +#ifndef traceENTER_uxTaskGetSystemState + #define traceENTER_uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, pulTotalRunTime ) +#endif + +#ifndef traceRETURN_uxTaskGetSystemState + #define traceRETURN_uxTaskGetSystemState( uxTask ) +#endif + +#if ( configNUMBER_OF_CORES == 1 ) + #ifndef traceENTER_xTaskGetIdleTaskHandle + #define traceENTER_xTaskGetIdleTaskHandle() + #endif +#endif + +#if ( configNUMBER_OF_CORES == 1 ) + #ifndef traceRETURN_xTaskGetIdleTaskHandle + #define traceRETURN_xTaskGetIdleTaskHandle( xIdleTaskHandle ) + #endif +#endif + +#ifndef traceENTER_xTaskGetIdleTaskHandleForCore + #define traceENTER_xTaskGetIdleTaskHandleForCore( xCoreID ) +#endif + +#ifndef traceRETURN_xTaskGetIdleTaskHandleForCore + #define traceRETURN_xTaskGetIdleTaskHandleForCore( xIdleTaskHandle ) +#endif + +#ifndef traceENTER_vTaskStepTick + #define traceENTER_vTaskStepTick( xTicksToJump ) +#endif + +#ifndef traceRETURN_vTaskStepTick + #define traceRETURN_vTaskStepTick() +#endif + +#ifndef traceENTER_xTaskCatchUpTicks + #define traceENTER_xTaskCatchUpTicks( xTicksToCatchUp ) +#endif + +#ifndef traceRETURN_xTaskCatchUpTicks + #define traceRETURN_xTaskCatchUpTicks( xYieldOccurred ) +#endif + +#ifndef traceENTER_xTaskAbortDelay + #define traceENTER_xTaskAbortDelay( xTask ) +#endif + +#ifndef traceRETURN_xTaskAbortDelay + #define traceRETURN_xTaskAbortDelay( xReturn ) +#endif + +#ifndef traceENTER_xTaskIncrementTick + #define traceENTER_xTaskIncrementTick() +#endif + +#ifndef traceRETURN_xTaskIncrementTick + #define traceRETURN_xTaskIncrementTick( xSwitchRequired ) +#endif + +#ifndef traceENTER_vTaskSetApplicationTaskTag + #define traceENTER_vTaskSetApplicationTaskTag( xTask, pxHookFunction ) +#endif + +#ifndef traceRETURN_vTaskSetApplicationTaskTag + #define traceRETURN_vTaskSetApplicationTaskTag() +#endif + +#ifndef traceENTER_xTaskGetApplicationTaskTag + #define traceENTER_xTaskGetApplicationTaskTag( xTask ) +#endif + +#ifndef traceRETURN_xTaskGetApplicationTaskTag + #define traceRETURN_xTaskGetApplicationTaskTag( xReturn ) +#endif + +#ifndef traceENTER_xTaskGetApplicationTaskTagFromISR + #define traceENTER_xTaskGetApplicationTaskTagFromISR( xTask ) +#endif + +#ifndef traceRETURN_xTaskGetApplicationTaskTagFromISR + #define traceRETURN_xTaskGetApplicationTaskTagFromISR( xReturn ) +#endif + +#ifndef traceENTER_xTaskCallApplicationTaskHook + #define traceENTER_xTaskCallApplicationTaskHook( xTask, pvParameter ) +#endif + +#ifndef traceRETURN_xTaskCallApplicationTaskHook + #define traceRETURN_xTaskCallApplicationTaskHook( xReturn ) +#endif + +#ifndef traceENTER_vTaskSwitchContext + #define traceENTER_vTaskSwitchContext() +#endif + +#ifndef traceRETURN_vTaskSwitchContext + #define traceRETURN_vTaskSwitchContext() +#endif + +#ifndef traceENTER_vTaskPlaceOnEventList + #define traceENTER_vTaskPlaceOnEventList( pxEventList, xTicksToWait ) +#endif + +#ifndef traceRETURN_vTaskPlaceOnEventList + #define traceRETURN_vTaskPlaceOnEventList() +#endif + +#ifndef traceENTER_vTaskPlaceOnUnorderedEventList + #define traceENTER_vTaskPlaceOnUnorderedEventList( pxEventList, xItemValue, xTicksToWait ) +#endif + +#ifndef traceRETURN_vTaskPlaceOnUnorderedEventList + #define traceRETURN_vTaskPlaceOnUnorderedEventList() +#endif + +#ifndef traceENTER_vTaskPlaceOnEventListRestricted + #define traceENTER_vTaskPlaceOnEventListRestricted( pxEventList, xTicksToWait, xWaitIndefinitely ) +#endif + +#ifndef traceRETURN_vTaskPlaceOnEventListRestricted + #define traceRETURN_vTaskPlaceOnEventListRestricted() +#endif + +#ifndef traceENTER_xTaskRemoveFromEventList + #define traceENTER_xTaskRemoveFromEventList( pxEventList ) +#endif + +#ifndef traceRETURN_xTaskRemoveFromEventList + #define traceRETURN_xTaskRemoveFromEventList( xReturn ) +#endif + +#ifndef traceENTER_vTaskRemoveFromUnorderedEventList + #define traceENTER_vTaskRemoveFromUnorderedEventList( pxEventListItem, xItemValue ) +#endif + +#ifndef traceRETURN_vTaskRemoveFromUnorderedEventList + #define traceRETURN_vTaskRemoveFromUnorderedEventList() +#endif + +#ifndef traceENTER_vTaskSetTimeOutState + #define traceENTER_vTaskSetTimeOutState( pxTimeOut ) +#endif + +#ifndef traceRETURN_vTaskSetTimeOutState + #define traceRETURN_vTaskSetTimeOutState() +#endif + +#ifndef traceENTER_vTaskInternalSetTimeOutState + #define traceENTER_vTaskInternalSetTimeOutState( pxTimeOut ) +#endif + +#ifndef traceRETURN_vTaskInternalSetTimeOutState + #define traceRETURN_vTaskInternalSetTimeOutState() +#endif + +#ifndef traceENTER_xTaskCheckForTimeOut + #define traceENTER_xTaskCheckForTimeOut( pxTimeOut, pxTicksToWait ) +#endif + +#ifndef traceRETURN_xTaskCheckForTimeOut + #define traceRETURN_xTaskCheckForTimeOut( xReturn ) +#endif + +#ifndef traceENTER_vTaskMissedYield + #define traceENTER_vTaskMissedYield() +#endif + +#ifndef traceRETURN_vTaskMissedYield + #define traceRETURN_vTaskMissedYield() +#endif + +#ifndef traceENTER_uxTaskGetTaskNumber + #define traceENTER_uxTaskGetTaskNumber( xTask ) +#endif + +#ifndef traceRETURN_uxTaskGetTaskNumber + #define traceRETURN_uxTaskGetTaskNumber( uxReturn ) +#endif + +#ifndef traceENTER_vTaskSetTaskNumber + #define traceENTER_vTaskSetTaskNumber( xTask, uxHandle ) +#endif + +#ifndef traceRETURN_vTaskSetTaskNumber + #define traceRETURN_vTaskSetTaskNumber() +#endif + +#ifndef traceENTER_eTaskConfirmSleepModeStatus + #define traceENTER_eTaskConfirmSleepModeStatus() +#endif + +#ifndef traceRETURN_eTaskConfirmSleepModeStatus + #define traceRETURN_eTaskConfirmSleepModeStatus( eReturn ) +#endif + +#ifndef traceENTER_vTaskSetThreadLocalStoragePointer + #define traceENTER_vTaskSetThreadLocalStoragePointer( xTaskToSet, xIndex, pvValue ) +#endif + +#ifndef traceRETURN_vTaskSetThreadLocalStoragePointer + #define traceRETURN_vTaskSetThreadLocalStoragePointer() +#endif + +#ifndef traceENTER_pvTaskGetThreadLocalStoragePointer + #define traceENTER_pvTaskGetThreadLocalStoragePointer( xTaskToQuery, xIndex ) +#endif + +#ifndef traceRETURN_pvTaskGetThreadLocalStoragePointer + #define traceRETURN_pvTaskGetThreadLocalStoragePointer( pvReturn ) +#endif + +#ifndef traceENTER_vTaskAllocateMPURegions + #define traceENTER_vTaskAllocateMPURegions( xTaskToModify, pxRegions ) +#endif + +#ifndef traceRETURN_vTaskAllocateMPURegions + #define traceRETURN_vTaskAllocateMPURegions() +#endif + +#ifndef traceENTER_vTaskGetInfo + #define traceENTER_vTaskGetInfo( xTask, pxTaskStatus, xGetFreeStackSpace, eState ) +#endif + +#ifndef traceRETURN_vTaskGetInfo + #define traceRETURN_vTaskGetInfo() +#endif + +#ifndef traceENTER_uxTaskGetStackHighWaterMark2 + #define traceENTER_uxTaskGetStackHighWaterMark2( xTask ) +#endif + +#ifndef traceRETURN_uxTaskGetStackHighWaterMark2 + #define traceRETURN_uxTaskGetStackHighWaterMark2( uxReturn ) +#endif + +#ifndef traceENTER_uxTaskGetStackHighWaterMark + #define traceENTER_uxTaskGetStackHighWaterMark( xTask ) +#endif + +#ifndef traceRETURN_uxTaskGetStackHighWaterMark + #define traceRETURN_uxTaskGetStackHighWaterMark( uxReturn ) +#endif + +#ifndef traceENTER_xTaskGetCurrentTaskHandle + #define traceENTER_xTaskGetCurrentTaskHandle() +#endif + +#ifndef traceRETURN_xTaskGetCurrentTaskHandle + #define traceRETURN_xTaskGetCurrentTaskHandle( xReturn ) +#endif + +#ifndef traceENTER_xTaskGetCurrentTaskHandleForCore + #define traceENTER_xTaskGetCurrentTaskHandleForCore( xCoreID ) +#endif + +#ifndef traceRETURN_xTaskGetCurrentTaskHandleForCore + #define traceRETURN_xTaskGetCurrentTaskHandleForCore( xReturn ) +#endif + +#ifndef traceENTER_xTaskGetSchedulerState + #define traceENTER_xTaskGetSchedulerState() +#endif + +#ifndef traceRETURN_xTaskGetSchedulerState + #define traceRETURN_xTaskGetSchedulerState( xReturn ) +#endif + +#ifndef traceENTER_xTaskPriorityInherit + #define traceENTER_xTaskPriorityInherit( pxMutexHolder ) +#endif + +#ifndef traceRETURN_xTaskPriorityInherit + #define traceRETURN_xTaskPriorityInherit( xReturn ) +#endif + +#ifndef traceENTER_xTaskPriorityDisinherit + #define traceENTER_xTaskPriorityDisinherit( pxMutexHolder ) +#endif + +#ifndef traceRETURN_xTaskPriorityDisinherit + #define traceRETURN_xTaskPriorityDisinherit( xReturn ) +#endif + +#ifndef traceENTER_vTaskPriorityDisinheritAfterTimeout + #define traceENTER_vTaskPriorityDisinheritAfterTimeout( pxMutexHolder, uxHighestPriorityWaitingTask ) +#endif + +#ifndef traceRETURN_vTaskPriorityDisinheritAfterTimeout + #define traceRETURN_vTaskPriorityDisinheritAfterTimeout() +#endif + +#ifndef traceENTER_vTaskYieldWithinAPI + #define traceENTER_vTaskYieldWithinAPI() +#endif + +#ifndef traceRETURN_vTaskYieldWithinAPI + #define traceRETURN_vTaskYieldWithinAPI() +#endif + +#ifndef traceENTER_vTaskEnterCritical + #define traceENTER_vTaskEnterCritical() +#endif + +#ifndef traceRETURN_vTaskEnterCritical + #define traceRETURN_vTaskEnterCritical() +#endif + +#ifndef traceENTER_vTaskEnterCriticalFromISR + #define traceENTER_vTaskEnterCriticalFromISR() +#endif + +#ifndef traceRETURN_vTaskEnterCriticalFromISR + #define traceRETURN_vTaskEnterCriticalFromISR( uxSavedInterruptStatus ) +#endif + +#ifndef traceENTER_vTaskExitCritical + #define traceENTER_vTaskExitCritical() +#endif + +#ifndef traceRETURN_vTaskExitCritical + #define traceRETURN_vTaskExitCritical() +#endif + +#ifndef traceENTER_vTaskExitCriticalFromISR + #define traceENTER_vTaskExitCriticalFromISR( uxSavedInterruptStatus ) +#endif + +#ifndef traceRETURN_vTaskExitCriticalFromISR + #define traceRETURN_vTaskExitCriticalFromISR() +#endif + +#ifndef traceENTER_vTaskListTasks + #define traceENTER_vTaskListTasks( pcWriteBuffer, uxBufferLength ) +#endif + +#ifndef traceRETURN_vTaskListTasks + #define traceRETURN_vTaskListTasks() +#endif + +#ifndef traceENTER_vTaskGetRunTimeStatistics + #define traceENTER_vTaskGetRunTimeStatistics( pcWriteBuffer, uxBufferLength ) +#endif + +#ifndef traceRETURN_vTaskGetRunTimeStatistics + #define traceRETURN_vTaskGetRunTimeStatistics() +#endif + +#ifndef traceENTER_uxTaskResetEventItemValue + #define traceENTER_uxTaskResetEventItemValue() +#endif + +#ifndef traceRETURN_uxTaskResetEventItemValue + #define traceRETURN_uxTaskResetEventItemValue( uxReturn ) +#endif + +#ifndef traceENTER_pvTaskIncrementMutexHeldCount + #define traceENTER_pvTaskIncrementMutexHeldCount() +#endif + +#ifndef traceRETURN_pvTaskIncrementMutexHeldCount + #define traceRETURN_pvTaskIncrementMutexHeldCount( pxTCB ) +#endif + +#ifndef traceENTER_ulTaskGenericNotifyTake + #define traceENTER_ulTaskGenericNotifyTake( uxIndexToWaitOn, xClearCountOnExit, xTicksToWait ) +#endif + +#ifndef traceRETURN_ulTaskGenericNotifyTake + #define traceRETURN_ulTaskGenericNotifyTake( ulReturn ) +#endif + +#ifndef traceENTER_xTaskGenericNotifyWait + #define traceENTER_xTaskGenericNotifyWait( uxIndexToWaitOn, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ) +#endif + +#ifndef traceRETURN_xTaskGenericNotifyWait + #define traceRETURN_xTaskGenericNotifyWait( xReturn ) +#endif + +#ifndef traceENTER_xTaskGenericNotify + #define traceENTER_xTaskGenericNotify( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue ) +#endif + +#ifndef traceRETURN_xTaskGenericNotify + #define traceRETURN_xTaskGenericNotify( xReturn ) +#endif + +#ifndef traceENTER_xTaskGenericNotifyFromISR + #define traceENTER_xTaskGenericNotifyFromISR( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_xTaskGenericNotifyFromISR + #define traceRETURN_xTaskGenericNotifyFromISR( xReturn ) +#endif + +#ifndef traceENTER_vTaskGenericNotifyGiveFromISR + #define traceENTER_vTaskGenericNotifyGiveFromISR( xTaskToNotify, uxIndexToNotify, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_vTaskGenericNotifyGiveFromISR + #define traceRETURN_vTaskGenericNotifyGiveFromISR() +#endif + +#ifndef traceENTER_xTaskGenericNotifyStateClear + #define traceENTER_xTaskGenericNotifyStateClear( xTask, uxIndexToClear ) +#endif + +#ifndef traceRETURN_xTaskGenericNotifyStateClear + #define traceRETURN_xTaskGenericNotifyStateClear( xReturn ) +#endif + +#ifndef traceENTER_ulTaskGenericNotifyValueClear + #define traceENTER_ulTaskGenericNotifyValueClear( xTask, uxIndexToClear, ulBitsToClear ) +#endif + +#ifndef traceRETURN_ulTaskGenericNotifyValueClear + #define traceRETURN_ulTaskGenericNotifyValueClear( ulReturn ) +#endif + +#ifndef traceENTER_ulTaskGetRunTimeCounter + #define traceENTER_ulTaskGetRunTimeCounter( xTask ) +#endif + +#ifndef traceRETURN_ulTaskGetRunTimeCounter + #define traceRETURN_ulTaskGetRunTimeCounter( ulRunTimeCounter ) +#endif + +#ifndef traceENTER_ulTaskGetRunTimePercent + #define traceENTER_ulTaskGetRunTimePercent( xTask ) +#endif + +#ifndef traceRETURN_ulTaskGetRunTimePercent + #define traceRETURN_ulTaskGetRunTimePercent( ulReturn ) +#endif + +#ifndef traceENTER_ulTaskGetIdleRunTimeCounter + #define traceENTER_ulTaskGetIdleRunTimeCounter() +#endif + +#ifndef traceRETURN_ulTaskGetIdleRunTimeCounter + #define traceRETURN_ulTaskGetIdleRunTimeCounter( ulReturn ) +#endif + +#ifndef traceENTER_ulTaskGetIdleRunTimePercent + #define traceENTER_ulTaskGetIdleRunTimePercent() +#endif + +#ifndef traceRETURN_ulTaskGetIdleRunTimePercent + #define traceRETURN_ulTaskGetIdleRunTimePercent( ulReturn ) +#endif + +#ifndef traceENTER_xTaskGetMPUSettings + #define traceENTER_xTaskGetMPUSettings( xTask ) +#endif + +#ifndef traceRETURN_xTaskGetMPUSettings + #define traceRETURN_xTaskGetMPUSettings( xMPUSettings ) +#endif + +#ifndef traceENTER_xStreamBufferGenericCreate + #define traceENTER_xStreamBufferGenericCreate( xBufferSizeBytes, xTriggerLevelBytes, xIsMessageBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback ) +#endif + +#ifndef traceRETURN_xStreamBufferGenericCreate + #define traceRETURN_xStreamBufferGenericCreate( pvAllocatedMemory ) +#endif + +#ifndef traceENTER_xStreamBufferGenericCreateStatic + #define traceENTER_xStreamBufferGenericCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, xIsMessageBuffer, pucStreamBufferStorageArea, pxStaticStreamBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback ) +#endif + +#ifndef traceRETURN_xStreamBufferGenericCreateStatic + #define traceRETURN_xStreamBufferGenericCreateStatic( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferGetStaticBuffers + #define traceENTER_xStreamBufferGetStaticBuffers( xStreamBuffer, ppucStreamBufferStorageArea, ppxStaticStreamBuffer ) +#endif + +#ifndef traceRETURN_xStreamBufferGetStaticBuffers + #define traceRETURN_xStreamBufferGetStaticBuffers( xReturn ) +#endif + +#ifndef traceENTER_vStreamBufferDelete + #define traceENTER_vStreamBufferDelete( xStreamBuffer ) +#endif + +#ifndef traceRETURN_vStreamBufferDelete + #define traceRETURN_vStreamBufferDelete() +#endif + +#ifndef traceENTER_xStreamBufferReset + #define traceENTER_xStreamBufferReset( xStreamBuffer ) +#endif + +#ifndef traceRETURN_xStreamBufferReset + #define traceRETURN_xStreamBufferReset( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferSetTriggerLevel + #define traceENTER_xStreamBufferSetTriggerLevel( xStreamBuffer, xTriggerLevel ) +#endif + +#ifndef traceRETURN_xStreamBufferSetTriggerLevel + #define traceRETURN_xStreamBufferSetTriggerLevel( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferSpacesAvailable + #define traceENTER_xStreamBufferSpacesAvailable( xStreamBuffer ) +#endif + +#ifndef traceRETURN_xStreamBufferSpacesAvailable + #define traceRETURN_xStreamBufferSpacesAvailable( xSpace ) +#endif + +#ifndef traceENTER_xStreamBufferBytesAvailable + #define traceENTER_xStreamBufferBytesAvailable( xStreamBuffer ) +#endif + +#ifndef traceRETURN_xStreamBufferBytesAvailable + #define traceRETURN_xStreamBufferBytesAvailable( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferSend + #define traceENTER_xStreamBufferSend( xStreamBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) +#endif + +#ifndef traceRETURN_xStreamBufferSend + #define traceRETURN_xStreamBufferSend( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferSendFromISR + #define traceENTER_xStreamBufferSendFromISR( xStreamBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_xStreamBufferSendFromISR + #define traceRETURN_xStreamBufferSendFromISR( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferReceive + #define traceENTER_xStreamBufferReceive( xStreamBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) +#endif + +#ifndef traceRETURN_xStreamBufferReceive + #define traceRETURN_xStreamBufferReceive( xReceivedLength ) +#endif + +#ifndef traceENTER_xStreamBufferNextMessageLengthBytes + #define traceENTER_xStreamBufferNextMessageLengthBytes( xStreamBuffer ) +#endif + +#ifndef traceRETURN_xStreamBufferNextMessageLengthBytes + #define traceRETURN_xStreamBufferNextMessageLengthBytes( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferReceiveFromISR + #define traceENTER_xStreamBufferReceiveFromISR( xStreamBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_xStreamBufferReceiveFromISR + #define traceRETURN_xStreamBufferReceiveFromISR( xReceivedLength ) +#endif + +#ifndef traceENTER_xStreamBufferIsEmpty + #define traceENTER_xStreamBufferIsEmpty( xStreamBuffer ) +#endif + +#ifndef traceRETURN_xStreamBufferIsEmpty + #define traceRETURN_xStreamBufferIsEmpty( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferIsFull + #define traceENTER_xStreamBufferIsFull( xStreamBuffer ) +#endif + +#ifndef traceRETURN_xStreamBufferIsFull + #define traceRETURN_xStreamBufferIsFull( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferSendCompletedFromISR + #define traceENTER_xStreamBufferSendCompletedFromISR( xStreamBuffer, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_xStreamBufferSendCompletedFromISR + #define traceRETURN_xStreamBufferSendCompletedFromISR( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferReceiveCompletedFromISR + #define traceENTER_xStreamBufferReceiveCompletedFromISR( xStreamBuffer, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_xStreamBufferReceiveCompletedFromISR + #define traceRETURN_xStreamBufferReceiveCompletedFromISR( xReturn ) +#endif + +#ifndef traceENTER_uxStreamBufferGetStreamBufferNumber + #define traceENTER_uxStreamBufferGetStreamBufferNumber( xStreamBuffer ) +#endif + +#ifndef traceRETURN_uxStreamBufferGetStreamBufferNumber + #define traceRETURN_uxStreamBufferGetStreamBufferNumber( uxStreamBufferNumber ) +#endif + +#ifndef traceENTER_vStreamBufferSetStreamBufferNumber + #define traceENTER_vStreamBufferSetStreamBufferNumber( xStreamBuffer, uxStreamBufferNumber ) +#endif + +#ifndef traceRETURN_vStreamBufferSetStreamBufferNumber + #define traceRETURN_vStreamBufferSetStreamBufferNumber() +#endif + +#ifndef traceENTER_ucStreamBufferGetStreamBufferType + #define traceENTER_ucStreamBufferGetStreamBufferType( xStreamBuffer ) +#endif + +#ifndef traceRETURN_ucStreamBufferGetStreamBufferType + #define traceRETURN_ucStreamBufferGetStreamBufferType( ucStreamBufferType ) +#endif + +#ifndef traceENTER_vListInitialise + #define traceENTER_vListInitialise( pxList ) +#endif + +#ifndef traceRETURN_vListInitialise + #define traceRETURN_vListInitialise() +#endif + +#ifndef traceENTER_vListInitialiseItem + #define traceENTER_vListInitialiseItem( pxItem ) +#endif + +#ifndef traceRETURN_vListInitialiseItem + #define traceRETURN_vListInitialiseItem() +#endif + +#ifndef traceENTER_vListInsertEnd + #define traceENTER_vListInsertEnd( pxList, pxNewListItem ) +#endif + +#ifndef traceRETURN_vListInsertEnd + #define traceRETURN_vListInsertEnd() +#endif + +#ifndef traceENTER_vListInsert + #define traceENTER_vListInsert( pxList, pxNewListItem ) +#endif + +#ifndef traceRETURN_vListInsert + #define traceRETURN_vListInsert() +#endif + +#ifndef traceENTER_uxListRemove + #define traceENTER_uxListRemove( pxItemToRemove ) +#endif + +#ifndef traceRETURN_uxListRemove + #define traceRETURN_uxListRemove( uxNumberOfItems ) +#endif + +#ifndef traceENTER_xCoRoutineCreate + #define traceENTER_xCoRoutineCreate( pxCoRoutineCode, uxPriority, uxIndex ) +#endif + +#ifndef traceRETURN_xCoRoutineCreate + #define traceRETURN_xCoRoutineCreate( xReturn ) +#endif + +#ifndef traceENTER_vCoRoutineAddToDelayedList + #define traceENTER_vCoRoutineAddToDelayedList( xTicksToDelay, pxEventList ) +#endif + +#ifndef traceRETURN_vCoRoutineAddToDelayedList + #define traceRETURN_vCoRoutineAddToDelayedList() +#endif + +#ifndef traceENTER_vCoRoutineSchedule + #define traceENTER_vCoRoutineSchedule() +#endif + +#ifndef traceRETURN_vCoRoutineSchedule + #define traceRETURN_vCoRoutineSchedule() +#endif + +#ifndef traceENTER_xCoRoutineRemoveFromEventList + #define traceENTER_xCoRoutineRemoveFromEventList( pxEventList ) +#endif + +#ifndef traceRETURN_xCoRoutineRemoveFromEventList + #define traceRETURN_xCoRoutineRemoveFromEventList( xReturn ) +#endif + #ifndef configGENERATE_RUN_TIME_STATS #define configGENERATE_RUN_TIME_STATS 0 #endif @@ -809,6 +2615,10 @@ #define portPRIVILEGE_BIT ( ( UBaseType_t ) 0x00 ) #endif +#ifndef portYIELD_WITHIN_API + #define portYIELD_WITHIN_API portYIELD +#endif + #ifndef portSUPPRESS_TICKS_AND_SLEEP #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) #endif @@ -893,6 +2703,10 @@ #define configAPPLICATION_ALLOCATED_HEAP 0 #endif +#ifndef configENABLE_HEAP_PROTECTOR + #define configENABLE_HEAP_PROTECTOR 0 +#endif + #ifndef configUSE_TASK_NOTIFICATIONS #define configUSE_TASK_NOTIFICATIONS 1 #endif @@ -909,6 +2723,12 @@ #define configUSE_POSIX_ERRNO 0 #endif +#ifndef configUSE_SB_COMPLETED_CALLBACK + +/* By default per-instance callbacks are not enabled for stream buffer or message buffer. */ + #define configUSE_SB_COMPLETED_CALLBACK 0 +#endif + #ifndef portTICK_TYPE_IS_ATOMIC #define portTICK_TYPE_IS_ATOMIC 0 #endif @@ -918,14 +2738,27 @@ #define configSUPPORT_STATIC_ALLOCATION 0 #endif +#ifndef configKERNEL_PROVIDED_STATIC_MEMORY + #define configKERNEL_PROVIDED_STATIC_MEMORY 0 +#endif + #ifndef configSUPPORT_DYNAMIC_ALLOCATION /* Defaults to 1 for backward compatibility. */ #define configSUPPORT_DYNAMIC_ALLOCATION 1 #endif -#ifndef configSTACK_ALLOCATION_FROM_SEPARATE_HEAP - /* Defaults to 0 for backward compatibility. */ - #define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 +#if ( ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION != 1 ) ) + #error configUSE_STATS_FORMATTING_FUNCTIONS cannot be used without dynamic allocation, but configSUPPORT_DYNAMIC_ALLOCATION is not set to 1. +#endif + +#if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) + #if ( ( configUSE_TRACE_FACILITY != 1 ) && ( configGENERATE_RUN_TIME_STATS != 1 ) ) + #error configUSE_STATS_FORMATTING_FUNCTIONS is 1 but the functions it enables are not used because neither configUSE_TRACE_FACILITY or configGENERATE_RUN_TIME_STATS are 1. Set configUSE_STATS_FORMATTING_FUNCTIONS to 0 in FreeRTOSConfig.h. + #endif +#endif + +#ifndef configSTATS_BUFFER_MAX_LENGTH + #define configSTATS_BUFFER_MAX_LENGTH 0xFFFF #endif #ifndef configSTACK_DEPTH_TYPE @@ -935,6 +2768,14 @@ #define configSTACK_DEPTH_TYPE uint16_t #endif +#ifndef configRUN_TIME_COUNTER_TYPE + +/* Defaults to uint32_t for backward compatibility, but can be overridden in + * FreeRTOSConfig.h if uint32_t is too restrictive. */ + + #define configRUN_TIME_COUNTER_TYPE uint32_t +#endif + #ifndef configMESSAGE_BUFFER_LENGTH_TYPE /* Defaults to size_t for backward compatibility, but can be overridden @@ -944,12 +2785,6 @@ #endif /* Sanity check the configuration. */ -#if ( configUSE_TICKLESS_IDLE != 0 ) - #if ( INCLUDE_vTaskSuspend != 1 ) - #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0 - #endif /* INCLUDE_vTaskSuspend */ -#endif /* configUSE_TICKLESS_IDLE */ - #if ( ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) ) #error configSUPPORT_STATIC_ALLOCATION and configSUPPORT_DYNAMIC_ALLOCATION cannot both be 0, but can both be 1. #endif @@ -958,18 +2793,26 @@ #error configUSE_MUTEXES must be set to 1 to use recursive mutexes #endif -#if( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configUSE_CORE_AFFINITY != 0 ) ) - #error configRUN_MULTIPLE_PRIORITIES must be set to 1 to use core exclusion -#endif - -#if( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configUSE_TASK_PREEMPTION_DISABLE != 0 ) ) +#if ( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configUSE_TASK_PREEMPTION_DISABLE != 0 ) ) #error configRUN_MULTIPLE_PRIORITIES must be set to 1 to use task preemption disable #endif -#if( ( configUSE_PREEMPTION == 0 ) && ( configUSE_TASK_PREEMPTION_DISABLE != 0 ) ) +#if ( ( configUSE_PREEMPTION == 0 ) && ( configUSE_TASK_PREEMPTION_DISABLE != 0 ) ) #error configUSE_PREEMPTION must be set to 1 to use task preemption disable #endif +#if ( ( configNUMBER_OF_CORES == 1 ) && ( configUSE_TASK_PREEMPTION_DISABLE != 0 ) ) + #error configUSE_TASK_PREEMPTION_DISABLE is not supported in single core FreeRTOS +#endif + +#if ( ( configNUMBER_OF_CORES == 1 ) && ( configUSE_CORE_AFFINITY != 0 ) ) + #error configUSE_CORE_AFFINITY is not supported in single core FreeRTOS +#endif + +#if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PORT_OPTIMISED_TASK_SELECTION != 0 ) ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION is not supported in SMP FreeRTOS +#endif + #ifndef configINITIAL_TICK_COUNT #define configINITIAL_TICK_COUNT 0 #endif @@ -990,7 +2833,7 @@ #define portTICK_TYPE_ENTER_CRITICAL() #define portTICK_TYPE_EXIT_CRITICAL() #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() 0 - #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) ( void ) x + #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) ( void ) ( x ) #endif /* if ( portTICK_TYPE_IS_ATOMIC == 0 ) */ /* Definitions to allow backward compatibility with FreeRTOS versions prior to @@ -1086,6 +2929,12 @@ #define configENABLE_FPU 1 #endif +/* Set configENABLE_MVE to 1 to enable MVE support and 0 to disable it. This is + * currently used in ARMv8M ports. */ +#ifndef configENABLE_MVE + #define configENABLE_MVE 0 +#endif + /* Set configENABLE_TRUSTZONE to 1 enable TrustZone support and 0 to disable it. * This is currently used in ARMv8M ports. */ #ifndef configENABLE_TRUSTZONE @@ -1098,6 +2947,16 @@ #define configRUN_FREERTOS_SECURE_ONLY 0 #endif +#ifndef configRUN_ADDITIONAL_TESTS + #define configRUN_ADDITIONAL_TESTS 0 +#endif + +/* The following config allows infinite loop control. For example, control the + * infinite loop in idle task function when performing unit tests. */ +#ifndef configCONTROL_INFINITE_LOOP + #define configCONTROL_INFINITE_LOOP() +#endif + /* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using * dynamically allocated RAM, in which case when any task is deleted it is known * that both the task's stack and TCB need to be freed. Sometimes the @@ -1167,16 +3026,20 @@ struct xSTATIC_LIST_ITEM }; typedef struct xSTATIC_LIST_ITEM StaticListItem_t; -/* See the comments above the struct xSTATIC_LIST_ITEM definition. */ -struct xSTATIC_MINI_LIST_ITEM -{ - #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 ) - TickType_t xDummy1; - #endif - TickType_t xDummy2; - void * pvDummy3[ 2 ]; -}; -typedef struct xSTATIC_MINI_LIST_ITEM StaticMiniListItem_t; +#if ( configUSE_MINI_LIST_ITEM == 1 ) + /* See the comments above the struct xSTATIC_LIST_ITEM definition. */ + struct xSTATIC_MINI_LIST_ITEM + { + #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 ) + TickType_t xDummy1; + #endif + TickType_t xDummy2; + void * pvDummy3[ 2 ]; + }; + typedef struct xSTATIC_MINI_LIST_ITEM StaticMiniListItem_t; +#else /* if ( configUSE_MINI_LIST_ITEM == 1 ) */ + typedef struct xSTATIC_LIST_ITEM StaticMiniListItem_t; +#endif /* if ( configUSE_MINI_LIST_ITEM == 1 ) */ /* See the comments above the struct xSTATIC_LIST_ITEM definition. */ typedef struct xSTATIC_LIST @@ -1211,16 +3074,19 @@ typedef struct xSTATIC_TCB #if ( portUSING_MPU_WRAPPERS == 1 ) xMPU_SETTINGS xDummy2; #endif - #if ( configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 ) - UBaseType_t uxDummy25; + #if ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) + UBaseType_t uxDummy26; #endif StaticListItem_t xDummy3[ 2 ]; UBaseType_t uxDummy5; void * pxDummy6; - BaseType_t xDummy23[ 2 ]; + #if ( configNUMBER_OF_CORES > 1 ) + BaseType_t xDummy23; + UBaseType_t uxDummy24; + #endif uint8_t ucDummy7[ configMAX_TASK_NAME_LEN ]; #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - BaseType_t xDummy24; + BaseType_t xDummy25; #endif #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) void * pxDummy8; @@ -1241,10 +3107,10 @@ typedef struct xSTATIC_TCB void * pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; #endif #if ( configGENERATE_RUN_TIME_STATS == 1 ) - uint32_t ulDummy16; + configRUN_TIME_COUNTER_TYPE ulDummy16; #endif - #if ( configUSE_NEWLIB_REENTRANT == 1 ) - struct _reent xDummy17; + #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) + configTLS_BLOCK_TYPE xDummy17; #endif #if ( configUSE_TASK_NOTIFICATIONS == 1 ) uint32_t ulDummy18[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; @@ -1382,6 +3248,9 @@ typedef struct xSTATIC_STREAM_BUFFER #if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxDummy4; #endif + #if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) + void * pvDummy5[ 2 ]; + #endif } StaticStreamBuffer_t; /* Message buffers are built on stream buffers. */ @@ -1393,29 +3262,4 @@ typedef StaticStreamBuffer_t StaticMessageBuffer_t; #endif /* *INDENT-ON* */ -/*----------------------------------------------------------- -* IDF Compatibility -*----------------------------------------------------------*/ - -#ifdef ESP_PLATFORM - - /* - * Include ESP-IDF API additions implicitly for compatibility reasons. - * - * ESP-IDF API additions were previously added directly to FreeRTOS headers - * (e.g., task.h, queue.h). These APIs have now been moved to - * idf_additions.h. - * - * To ensure there are no breaking changes, we include idf_additions.h - * implicitly here so that those API additions are still accessible. Given - * that FreeRTOS.h must be included first before calling any FreeRTOS API, - * any existing source code can continue using these relocated APIs without - * any additional header inclusions via this implicit inclusion. - * - * Todo: Deprecate this implicit inclusion by ESP-IDF v6.0 (IDF-8126) - */ - #include "freertos/idf_additions.h" - -#endif /* ESP_PLATFORM */ - #endif /* INC_FREERTOS_H */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/StackMacros.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/StackMacros.h index d616581750..9813ada43f 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/StackMacros.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/StackMacros.h @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -26,7 +32,7 @@ #ifndef _MSC_VER /* Visual Studio doesn't support #warning. */ - #warning The name of this file has changed to stack_macros.h. Please update your code accordingly. This source file (which has the original name) will be removed in future released. + #warning The name of this file has changed to stack_macros.h. Please update your code accordingly. This source file (which has the original name) will be removed in a future release. #endif #include "stack_macros.h" diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/atomic.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/atomic.h index 5146437ce7..5d0bee9678 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/atomic.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/atomic.h @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/croutine.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/croutine.h index 5caecd29a8..bab1f29a93 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/croutine.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/croutine.h @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -45,28 +51,28 @@ typedef void * CoRoutineHandle_t; /* Defines the prototype to which co-routine functions must conform. */ -typedef void (* crCOROUTINE_CODE)( CoRoutineHandle_t, - UBaseType_t ); +typedef void (* crCOROUTINE_CODE)( CoRoutineHandle_t xHandle, + UBaseType_t uxIndex ); typedef struct corCoRoutineControlBlock { crCOROUTINE_CODE pxCoRoutineFunction; - ListItem_t xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */ - ListItem_t xEventListItem; /*< List item used to place the CRCB in event lists. */ - UBaseType_t uxPriority; /*< The priority of the co-routine in relation to other co-routines. */ - UBaseType_t uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */ - uint16_t uxState; /*< Used internally by the co-routine implementation. */ + ListItem_t xGenericListItem; /**< List item used to place the CRCB in ready and blocked queues. */ + ListItem_t xEventListItem; /**< List item used to place the CRCB in event lists. */ + UBaseType_t uxPriority; /**< The priority of the co-routine in relation to other co-routines. */ + UBaseType_t uxIndex; /**< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */ + uint16_t uxState; /**< Used internally by the co-routine implementation. */ } CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */ /** * croutine. h - *
+ * @code{c}
  * BaseType_t xCoRoutineCreate(
  *                               crCOROUTINE_CODE pxCoRoutineCode,
  *                               UBaseType_t uxPriority,
  *                               UBaseType_t uxIndex
  *                             );
- * 
+ * @endcode * * Create a new co-routine and add it to the list of co-routines that are * ready to run. @@ -86,7 +92,7 @@ typedef struct corCoRoutineControlBlock * list, otherwise an error code defined with ProjDefs.h. * * Example usage: - *
+ * @code{c}
  * // Co-routine to be created.
  * void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
  * {
@@ -127,7 +133,7 @@ typedef struct corCoRoutineControlBlock
  *       xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
  *   }
  * }
- * 
+ * @endcode * \defgroup xCoRoutineCreate xCoRoutineCreate * \ingroup Tasks */ @@ -138,9 +144,9 @@ BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, /** * croutine. h - *
+ * @code{c}
  * void vCoRoutineSchedule( void );
- * 
+ * @endcode * * Run a co-routine. * @@ -154,7 +160,7 @@ BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, * hook). * * Example usage: - *
+ * @code{c}
  * // This idle task hook will schedule a co-routine each time it is called.
  * // The rest of the idle task will execute between co-routine calls.
  * void vApplicationIdleHook( void )
@@ -172,7 +178,7 @@ BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode,
  *      vCoRoutineSchedule();
  *  }
  * }
- * 
+ * @endcode * \defgroup vCoRoutineSchedule vCoRoutineSchedule * \ingroup Tasks */ @@ -180,14 +186,14 @@ void vCoRoutineSchedule( void ); /** * croutine. h - *
+ * @code{c}
  * crSTART( CoRoutineHandle_t xHandle );
- * 
+ * @endcode * * This macro MUST always be called at the start of a co-routine function. * * Example usage: - *
+ * @code{c}
  * // Co-routine to be created.
  * void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
  * {
@@ -205,7 +211,7 @@ void vCoRoutineSchedule( void );
  *   // Must end every co-routine with a call to crEND();
  *   crEND();
  * }
- * 
+ * @endcode * \defgroup crSTART crSTART * \ingroup Tasks */ @@ -215,14 +221,14 @@ void vCoRoutineSchedule( void ); /** * croutine. h - *
+ * @code{c}
  * crEND();
- * 
+ * @endcode * * This macro MUST always be called at the end of a co-routine function. * * Example usage: - *
+ * @code{c}
  * // Co-routine to be created.
  * void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
  * {
@@ -240,7 +246,7 @@ void vCoRoutineSchedule( void );
  *   // Must end every co-routine with a call to crEND();
  *   crEND();
  * }
- * 
+ * @endcode * \defgroup crSTART crSTART * \ingroup Tasks */ @@ -259,9 +265,9 @@ void vCoRoutineSchedule( void ); /** * croutine. h - *
+ * @code{c}
  * crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );
- * 
+ * @endcode * * Delay a co-routine for a fixed period of time. * @@ -278,7 +284,7 @@ void vCoRoutineSchedule( void ); * can be used to convert ticks to milliseconds. * * Example usage: - *
+ * @code{c}
  * // Co-routine to be created.
  * void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
  * {
@@ -301,19 +307,21 @@ void vCoRoutineSchedule( void );
  *   // Must end every co-routine with a call to crEND();
  *   crEND();
  * }
- * 
+ * @endcode * \defgroup crDELAY crDELAY * \ingroup Tasks */ -#define crDELAY( xHandle, xTicksToDelay ) \ - if( ( xTicksToDelay ) > 0 ) \ - { \ - vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \ - } \ - crSET_STATE0( ( xHandle ) ); +#define crDELAY( xHandle, xTicksToDelay ) \ + do { \ + if( ( xTicksToDelay ) > 0 ) \ + { \ + vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \ + } \ + crSET_STATE0( ( xHandle ) ); \ + } while( 0 ) /** - *
+ * @code{c}
  * crQUEUE_SEND(
  *                CoRoutineHandle_t xHandle,
  *                QueueHandle_t pxQueue,
@@ -321,7 +329,7 @@ void vCoRoutineSchedule( void );
  *                TickType_t xTicksToWait,
  *                BaseType_t *pxResult
  *           )
- * 
+ * @endcode * * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. @@ -361,7 +369,7 @@ void vCoRoutineSchedule( void ); * error defined within ProjDefs.h. * * Example usage: - *
+ * @code{c}
  * // Co-routine function that blocks for a fixed period then posts a number onto
  * // a queue.
  * static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
@@ -393,12 +401,12 @@ void vCoRoutineSchedule( void );
  *  // Co-routines must end with a call to crEND().
  *  crEND();
  * }
- * 
+ * @endcode * \defgroup crQUEUE_SEND crQUEUE_SEND * \ingroup Tasks */ #define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \ - { \ + do { \ *( pxResult ) = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), ( xTicksToWait ) ); \ if( *( pxResult ) == errQUEUE_BLOCKED ) \ { \ @@ -410,11 +418,11 @@ void vCoRoutineSchedule( void ); crSET_STATE1( ( xHandle ) ); \ *pxResult = pdPASS; \ } \ - } + } while( 0 ) /** * croutine. h - *
+ * @code{c}
  * crQUEUE_RECEIVE(
  *                   CoRoutineHandle_t xHandle,
  *                   QueueHandle_t pxQueue,
@@ -422,7 +430,7 @@ void vCoRoutineSchedule( void );
  *                   TickType_t xTicksToWait,
  *                   BaseType_t *pxResult
  *               )
- * 
+ * @endcode * * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. @@ -461,7 +469,7 @@ void vCoRoutineSchedule( void ); * an error code as defined within ProjDefs.h. * * Example usage: - *
+ * @code{c}
  * // A co-routine receives the number of an LED to flash from a queue.  It
  * // blocks on the queue until the number is received.
  * static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
@@ -487,12 +495,12 @@ void vCoRoutineSchedule( void );
  *
  *  crEND();
  * }
- * 
+ * @endcode * \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE * \ingroup Tasks */ #define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \ - { \ + do { \ *( pxResult ) = xQueueCRReceive( ( pxQueue ), ( pvBuffer ), ( xTicksToWait ) ); \ if( *( pxResult ) == errQUEUE_BLOCKED ) \ { \ @@ -504,17 +512,17 @@ void vCoRoutineSchedule( void ); crSET_STATE1( ( xHandle ) ); \ *( pxResult ) = pdPASS; \ } \ - } + } while( 0 ) /** * croutine. h - *
+ * @code{c}
  * crQUEUE_SEND_FROM_ISR(
  *                          QueueHandle_t pxQueue,
  *                          void *pvItemToQueue,
  *                          BaseType_t xCoRoutinePreviouslyWoken
  *                     )
- * 
+ * @endcode * * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() @@ -549,7 +557,7 @@ void vCoRoutineSchedule( void ); * the ISR. * * Example usage: - *
+ * @code{c}
  * // A co-routine that blocks on a queue waiting for characters to be received.
  * static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
  * {
@@ -598,7 +606,7 @@ void vCoRoutineSchedule( void );
  *       xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
  *   }
  * }
- * 
+ * @endcode * \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR * \ingroup Tasks */ @@ -608,13 +616,13 @@ void vCoRoutineSchedule( void ); /** * croutine. h - *
+ * @code{c}
  * crQUEUE_SEND_FROM_ISR(
  *                          QueueHandle_t pxQueue,
  *                          void *pvBuffer,
  *                          BaseType_t * pxCoRoutineWoken
  *                     )
- * 
+ * @endcode * * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() @@ -649,7 +657,7 @@ void vCoRoutineSchedule( void ); * pdFALSE. * * Example usage: - *
+ * @code{c}
  * // A co-routine that posts a character to a queue then blocks for a fixed
  * // period.  The character is incremented each time.
  * static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
@@ -714,7 +722,7 @@ void vCoRoutineSchedule( void );
  *       }
  *   }
  * }
- * 
+ * @endcode * \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR * \ingroup Tasks */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/deprecated_definitions.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/deprecated_definitions.h index dce847d236..baea900003 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/deprecated_definitions.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/deprecated_definitions.h @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/event_groups.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/event_groups.h index 48108a3da3..852bddd0dc 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/event_groups.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/event_groups.h @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -34,6 +40,26 @@ /* FreeRTOS includes. */ #include "timers.h" +/* The following bit fields convey control information in a task's event list + * item value. It is important they don't clash with the + * taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */ +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + #define eventCLEAR_EVENTS_ON_EXIT_BIT ( ( uint16_t ) 0x0100U ) + #define eventUNBLOCKED_DUE_TO_BIT_SET ( ( uint16_t ) 0x0200U ) + #define eventWAIT_FOR_ALL_BITS ( ( uint16_t ) 0x0400U ) + #define eventEVENT_BITS_CONTROL_BYTES ( ( uint16_t ) 0xff00U ) +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + #define eventCLEAR_EVENTS_ON_EXIT_BIT ( ( uint32_t ) 0x01000000UL ) + #define eventUNBLOCKED_DUE_TO_BIT_SET ( ( uint32_t ) 0x02000000UL ) + #define eventWAIT_FOR_ALL_BITS ( ( uint32_t ) 0x04000000UL ) + #define eventEVENT_BITS_CONTROL_BYTES ( ( uint32_t ) 0xff000000UL ) +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_64_BITS ) + #define eventCLEAR_EVENTS_ON_EXIT_BIT ( ( uint64_t ) 0x0100000000000000ULL ) + #define eventUNBLOCKED_DUE_TO_BIT_SET ( ( uint64_t ) 0x0200000000000000ULL ) + #define eventWAIT_FOR_ALL_BITS ( ( uint64_t ) 0x0400000000000000ULL ) + #define eventEVENT_BITS_CONTROL_BYTES ( ( uint64_t ) 0xff00000000000000ULL ) +#endif /* if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) */ + /* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { @@ -63,8 +89,6 @@ * be set and then tested atomically - as is the case where event groups are * used to create a synchronisation point between multiple tasks (a * 'rendezvous'). - * - * \defgroup EventGroup */ @@ -84,8 +108,8 @@ typedef struct EventGroupDef_t * EventGroupHandle_t; /* * The type that holds event bits always matches TickType_t - therefore the - * number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to 1, - * 32 bits if set to 0. + * number of bits it holds is set by configTICK_TYPE_WIDTH_IN_BITS (16 bits if set to 0, + * 32 bits if set to 1, 64 bits if set to 2. * * \defgroup EventBits_t EventBits_t * \ingroup EventGroup @@ -94,36 +118,37 @@ typedef TickType_t EventBits_t; /** * event_groups.h - *
+ * @code{c}
  * EventGroupHandle_t xEventGroupCreate( void );
- * 
+ * @endcode * * Create a new event group. * * Internally, within the FreeRTOS implementation, event groups use a [small] * block of memory, in which the event group's structure is stored. If an event - * groups is created using xEventGropuCreate() then the required memory is + * groups is created using xEventGroupCreate() then the required memory is * automatically dynamically allocated inside the xEventGroupCreate() function. * (see https://www.FreeRTOS.org/a00111.html). If an event group is created - * using xEventGropuCreateStatic() then the application writer must instead + * using xEventGroupCreateStatic() then the application writer must instead * provide the memory that will get used by the event group. * xEventGroupCreateStatic() therefore allows an event group to be created * without using any dynamic memory allocation. * * Although event groups are not related to ticks, for internal implementation * reasons the number of bits available for use in an event group is dependent - * on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If - * configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit - * 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has - * 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store - * event bits within an event group. + * on the configTICK_TYPE_WIDTH_IN_BITS setting in FreeRTOSConfig.h. If + * configTICK_TYPE_WIDTH_IN_BITS is 0 then each event group contains 8 usable bits (bit + * 0 to bit 7). If configTICK_TYPE_WIDTH_IN_BITS is set to 1 then each event group has + * 24 usable bits (bit 0 to bit 23). If configTICK_TYPE_WIDTH_IN_BITS is set to 2 then + * each event group has 56 usable bits (bit 0 to bit 53). The EventBits_t type + * is used to store event bits within an event group. * * @return If the event group was created then a handle to the event group is * returned. If there was insufficient FreeRTOS heap available to create the * event group then NULL is returned. See https://www.FreeRTOS.org/a00111.html * * Example usage: - *
+ * @code{c}
  *  // Declare a variable to hold the created event group.
  *  EventGroupHandle_t xCreatedEventGroup;
  *
@@ -140,7 +165,7 @@ typedef TickType_t               EventBits_t;
  *  {
  *      // The event group was created.
  *  }
- * 
+ * @endcode * \defgroup xEventGroupCreate xEventGroupCreate * \ingroup EventGroup */ @@ -150,29 +175,30 @@ typedef TickType_t EventBits_t; /** * event_groups.h - *
+ * @code{c}
  * EventGroupHandle_t xEventGroupCreateStatic( EventGroupHandle_t * pxEventGroupBuffer );
- * 
+ * @endcode * * Create a new event group. * * Internally, within the FreeRTOS implementation, event groups use a [small] * block of memory, in which the event group's structure is stored. If an event - * groups is created using xEventGropuCreate() then the required memory is + * groups is created using xEventGroupCreate() then the required memory is * automatically dynamically allocated inside the xEventGroupCreate() function. * (see https://www.FreeRTOS.org/a00111.html). If an event group is created - * using xEventGropuCreateStatic() then the application writer must instead + * using xEventGroupCreateStatic() then the application writer must instead * provide the memory that will get used by the event group. * xEventGroupCreateStatic() therefore allows an event group to be created * without using any dynamic memory allocation. * * Although event groups are not related to ticks, for internal implementation * reasons the number of bits available for use in an event group is dependent - * on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If - * configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit - * 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has - * 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store - * event bits within an event group. + * on the configTICK_TYPE_WIDTH_IN_BITS setting in FreeRTOSConfig.h. If + * configTICK_TYPE_WIDTH_IN_BITS is 0 then each event group contains 8 usable bits (bit + * 0 to bit 7). If configTICK_TYPE_WIDTH_IN_BITS is set to 1 then each event group has + * 24 usable bits (bit 0 to bit 23). If configTICK_TYPE_WIDTH_IN_BITS is set to 2 then + * each event group has 56 usable bits (bit 0 to bit 53). The EventBits_t type + * is used to store event bits within an event group. * * @param pxEventGroupBuffer pxEventGroupBuffer must point to a variable of type * StaticEventGroup_t, which will be then be used to hold the event group's data @@ -182,7 +208,7 @@ typedef TickType_t EventBits_t; * returned. If pxEventGroupBuffer was NULL then NULL is returned. * * Example usage: - *
+ * @code{c}
  *  // StaticEventGroup_t is a publicly accessible structure that has the same
  *  // size and alignment requirements as the real event group structure.  It is
  *  // provided as a mechanism for applications to know the size of the event
@@ -195,7 +221,7 @@ typedef TickType_t               EventBits_t;
  *
  *  // Create the event group without dynamically allocating any memory.
  *  xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
- * 
+ * @endcode */ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) PRIVILEGED_FUNCTION; @@ -203,13 +229,13 @@ typedef TickType_t EventBits_t; /** * event_groups.h - *
+ * @code{c}
  *  EventBits_t xEventGroupWaitBits(    EventGroupHandle_t xEventGroup,
  *                                      const EventBits_t uxBitsToWaitFor,
  *                                      const BaseType_t xClearOnExit,
  *                                      const BaseType_t xWaitForAllBits,
  *                                      const TickType_t xTicksToWait );
- * 
+ * @endcode * * [Potentially] block to wait for one or more bits to be set within a * previously created event group. @@ -241,7 +267,8 @@ typedef TickType_t EventBits_t; * * @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait * for one/all (depending on the xWaitForAllBits value) of the bits specified by - * uxBitsToWaitFor to become set. + * uxBitsToWaitFor to become set. A value of portMAX_DELAY can be used to block + * indefinitely (provided INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h). * * @return The value of the event group at the time either the bits being waited * for became set, or the block time expired. Test the return value to know @@ -253,9 +280,9 @@ typedef TickType_t EventBits_t; * pdTRUE. * * Example usage: - *
- #define BIT_0 ( 1 << 0 )
- #define BIT_4 ( 1 << 4 )
+ * @code{c}
+ * #define BIT_0 ( 1 << 0 )
+ * #define BIT_4 ( 1 << 4 )
  *
  * void aFunction( EventGroupHandle_t xEventGroup )
  * {
@@ -289,7 +316,7 @@ typedef TickType_t               EventBits_t;
  *          // without either BIT_0 or BIT_4 becoming set.
  *      }
  * }
- * 
+ * @endcode * \defgroup xEventGroupWaitBits xEventGroupWaitBits * \ingroup EventGroup */ @@ -301,9 +328,9 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, /** * event_groups.h - *
+ * @code{c}
  *  EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
- * 
+ * @endcode * * Clear bits within an event group. This function cannot be called from an * interrupt. @@ -317,9 +344,9 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, * @return The value of the event group before the specified bits were cleared. * * Example usage: - *
- #define BIT_0 ( 1 << 0 )
- #define BIT_4 ( 1 << 4 )
+ * @code{c}
+ * #define BIT_0 ( 1 << 0 )
+ * #define BIT_4 ( 1 << 4 )
  *
  * void aFunction( EventGroupHandle_t xEventGroup )
  * {
@@ -350,7 +377,7 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
  *          // Neither bit 0 nor bit 4 were set in the first place.
  *      }
  * }
- * 
+ * @endcode * \defgroup xEventGroupClearBits xEventGroupClearBits * \ingroup EventGroup */ @@ -359,9 +386,9 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, /** * event_groups.h - *
+ * @code{c}
  *  BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
- * 
+ * @endcode * * A version of xEventGroupClearBits() that can be called from an interrupt. * @@ -375,6 +402,12 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, * timer task to have the clear operation performed in the context of the timer * task. * + * @note If this function returns pdPASS then the timer task is ready to run + * and a portYIELD_FROM_ISR(pdTRUE) should be executed to perform the needed + * clear on the event group. This behavior is different from + * xEventGroupSetBitsFromISR because the parameter xHigherPriorityTaskWoken is + * not present. + * * @param xEventGroup The event group in which the bits are to be cleared. * * @param uxBitsToClear A bitwise value that indicates the bit or bits to clear. @@ -386,9 +419,9 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, * if the timer service queue was full. * * Example usage: - *
- #define BIT_0 ( 1 << 0 )
- #define BIT_4 ( 1 << 4 )
+ * @code{c}
+ * #define BIT_0 ( 1 << 0 )
+ * #define BIT_4 ( 1 << 4 )
  *
  * // An event group which it is assumed has already been created by a call to
  * // xEventGroupCreate().
@@ -404,9 +437,10 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
  *      if( xResult == pdPASS )
  *      {
  *          // The message was posted successfully.
+ *          portYIELD_FROM_ISR(pdTRUE);
  *      }
  * }
- * 
+ * @endcode * \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR * \ingroup EventGroup */ @@ -415,14 +449,14 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION; #else #define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) \ - xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ) + xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) ( xEventGroup ), ( uint32_t ) ( uxBitsToClear ), NULL ) #endif /** * event_groups.h - *
+ * @code{c}
  *  EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
- * 
+ * @endcode * * Set bits within an event group. * This function cannot be called from an interrupt. xEventGroupSetBitsFromISR() @@ -448,9 +482,9 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, * event group value before the call to xEventGroupSetBits() returns. * * Example usage: - *
- #define BIT_0 ( 1 << 0 )
- #define BIT_4 ( 1 << 4 )
+ * @code{c}
+ * #define BIT_0 ( 1 << 0 )
+ * #define BIT_4 ( 1 << 4 )
  *
  * void aFunction( EventGroupHandle_t xEventGroup )
  * {
@@ -486,7 +520,7 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
  *          // cleared as the task left the Blocked state.
  *      }
  * }
- * 
+ * @endcode * \defgroup xEventGroupSetBits xEventGroupSetBits * \ingroup EventGroup */ @@ -495,9 +529,9 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, /** * event_groups.h - *
+ * @code{c}
  *  BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
- * 
+ * @endcode * * A version of xEventGroupSetBits() that can be called from an interrupt. * @@ -530,9 +564,9 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, * if the timer service queue was full. * * Example usage: - *
- #define BIT_0 ( 1 << 0 )
- #define BIT_4 ( 1 << 4 )
+ * @code{c}
+ * #define BIT_0 ( 1 << 0 )
+ * #define BIT_4 ( 1 << 4 )
  *
  * // An event group which it is assumed has already been created by a call to
  * // xEventGroupCreate().
@@ -561,7 +595,7 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
  *          portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
  *      }
  * }
- * 
+ * @endcode * \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR * \ingroup EventGroup */ @@ -571,17 +605,17 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; #else #define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) \ - xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ) + xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) ( xEventGroup ), ( uint32_t ) ( uxBitsToSet ), ( pxHigherPriorityTaskWoken ) ) #endif /** * event_groups.h - *
+ * @code{c}
  *  EventBits_t xEventGroupSync(    EventGroupHandle_t xEventGroup,
  *                                  const EventBits_t uxBitsToSet,
  *                                  const EventBits_t uxBitsToWaitFor,
  *                                  TickType_t xTicksToWait );
- * 
+ * @endcode * * Atomically set bits within an event group, then wait for a combination of * bits to be set within the same event group. This functionality is typically @@ -620,13 +654,13 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, * automatically cleared. * * Example usage: - *
+ * @code{c}
  * // Bits used by the three tasks.
- #define TASK_0_BIT     ( 1 << 0 )
- #define TASK_1_BIT     ( 1 << 1 )
- #define TASK_2_BIT     ( 1 << 2 )
+ * #define TASK_0_BIT     ( 1 << 0 )
+ * #define TASK_1_BIT     ( 1 << 1 )
+ * #define TASK_2_BIT     ( 1 << 2 )
  *
- #define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )
+ * #define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )
  *
  * // Use an event group to synchronise three tasks.  It is assumed this event
  * // group has already been created elsewhere.
@@ -694,7 +728,7 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
  *  }
  * }
  *
- * 
+ * @endcode * \defgroup xEventGroupSync xEventGroupSync * \ingroup EventGroup */ @@ -706,9 +740,9 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, /** * event_groups.h - *
+ * @code{c}
  *  EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
- * 
+ * @endcode * * Returns the current value of the bits in an event group. This function * cannot be used from an interrupt. @@ -720,13 +754,13 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, * \defgroup xEventGroupGetBits xEventGroupGetBits * \ingroup EventGroup */ -#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 ) +#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( ( xEventGroup ), 0 ) /** * event_groups.h - *
+ * @code{c}
  *  EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
- * 
+ * @endcode * * A version of xEventGroupGetBits() that can be called from an ISR. * @@ -741,9 +775,9 @@ EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEG /** * event_groups.h - *
+ * @code{c}
  *  void xEventGroupDelete( EventGroupHandle_t xEventGroup );
- * 
+ * @endcode * * Delete an event group that was previously created by a call to * xEventGroupCreate(). Tasks that are blocked on the event group will be @@ -777,9 +811,9 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION; /* For internal use only. */ void vEventGroupSetBitsCallback( void * pvEventGroup, - const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION; + uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION; void vEventGroupClearBitsCallback( void * pvEventGroup, - const uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION; + uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION; #if ( configUSE_TRACE_FACILITY == 1 ) diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/list.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/list.h index 332f3f413c..026fce1d46 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/list.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/list.h @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -31,7 +37,7 @@ * * list_ts can only store pointers to list_item_ts. Each ListItem_t contains a * numeric value (xItemValue). Most of the time the lists are sorted in - * descending item value order. + * ascending item value order. * * Lists are created already containing one list item. The value of this * item is the maximum possible that can be stored, it is therefore always at @@ -141,35 +147,39 @@ struct xLIST; struct xLIST_ITEM { - listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ - configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */ - struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */ - struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */ - void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ - struct xLIST * configLIST_VOLATILE pxContainer; /*< Pointer to the list in which this list item is placed (if any). */ - listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + configLIST_VOLATILE TickType_t xItemValue; /**< The value being listed. In most cases this is used to sort the list in ascending order. */ + struct xLIST_ITEM * configLIST_VOLATILE pxNext; /**< Pointer to the next ListItem_t in the list. */ + struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /**< Pointer to the previous ListItem_t in the list. */ + void * pvOwner; /**< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ + struct xLIST * configLIST_VOLATILE pxContainer; /**< Pointer to the list in which this list item is placed (if any). */ + listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ }; -typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */ +typedef struct xLIST_ITEM ListItem_t; -struct xMINI_LIST_ITEM -{ - listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ - configLIST_VOLATILE TickType_t xItemValue; - struct xLIST_ITEM * configLIST_VOLATILE pxNext; - struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; -}; -typedef struct xMINI_LIST_ITEM MiniListItem_t; +#if ( configUSE_MINI_LIST_ITEM == 1 ) + struct xMINI_LIST_ITEM + { + listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + configLIST_VOLATILE TickType_t xItemValue; + struct xLIST_ITEM * configLIST_VOLATILE pxNext; + struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; + }; + typedef struct xMINI_LIST_ITEM MiniListItem_t; +#else + typedef struct xLIST_ITEM MiniListItem_t; +#endif /* * Definition of the type of queue used by the scheduler. */ typedef struct xLIST { - listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + listFIRST_LIST_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ volatile UBaseType_t uxNumberOfItems; - ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */ - MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ - listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + ListItem_t * configLIST_VOLATILE pxIndex; /**< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */ + MiniListItem_t xListEnd; /**< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ + listSECOND_LIST_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ } List_t; /* @@ -192,7 +202,7 @@ typedef struct xLIST /* * Access macro to set the value of the list item. In most cases the value is - * used to sort the list in descending order. + * used to sort the list in ascending order. * * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE * \ingroup LinkedList @@ -277,18 +287,98 @@ typedef struct xLIST * \ingroup LinkedList */ #define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ - { \ + do { \ List_t * const pxConstList = ( pxList ); \ /* Increment the index to the next item and return the item, ensuring */ \ /* we don't return the marker used at the end of the list. */ \ ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \ { \ - ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ + ( pxConstList )->pxIndex = ( pxConstList )->xListEnd.pxNext; \ } \ ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \ - } + } while( 0 ) +/* + * Version of uxListRemove() that does not return a value. Provided as a slight + * optimisation for xTaskIncrementTick() by being inline. + * + * Remove an item from a list. The list item has a pointer to the list that + * it is in, so only the list item need be passed into the function. + * + * @param uxListRemove The item to be removed. The item will remove itself from + * the list pointed to by it's pxContainer parameter. + * + * @return The number of items that remain in the list after the list item has + * been removed. + * + * \page listREMOVE_ITEM listREMOVE_ITEM + * \ingroup LinkedList + */ +#define listREMOVE_ITEM( pxItemToRemove ) \ + do { \ + /* The list item knows which list it is in. Obtain the list from the list \ + * item. */ \ + List_t * const pxList = ( pxItemToRemove )->pxContainer; \ + \ + ( pxItemToRemove )->pxNext->pxPrevious = ( pxItemToRemove )->pxPrevious; \ + ( pxItemToRemove )->pxPrevious->pxNext = ( pxItemToRemove )->pxNext; \ + /* Make sure the index is left pointing to a valid item. */ \ + if( pxList->pxIndex == ( pxItemToRemove ) ) \ + { \ + pxList->pxIndex = ( pxItemToRemove )->pxPrevious; \ + } \ + \ + ( pxItemToRemove )->pxContainer = NULL; \ + ( pxList->uxNumberOfItems )--; \ + } while( 0 ) + +/* + * Inline version of vListInsertEnd() to provide slight optimisation for + * xTaskIncrementTick(). + * + * Insert a list item into a list. The item will be inserted in a position + * such that it will be the last item within the list returned by multiple + * calls to listGET_OWNER_OF_NEXT_ENTRY. + * + * The list member pxIndex is used to walk through a list. Calling + * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list. + * Placing an item in a list using vListInsertEnd effectively places the item + * in the list position pointed to by pxIndex. This means that every other + * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before + * the pxIndex parameter again points to the item being inserted. + * + * @param pxList The list into which the item is to be inserted. + * + * @param pxNewListItem The list item to be inserted into the list. + * + * \page listINSERT_END listINSERT_END + * \ingroup LinkedList + */ +#define listINSERT_END( pxList, pxNewListItem ) \ + do { \ + ListItem_t * const pxIndex = ( pxList )->pxIndex; \ + \ + /* Only effective when configASSERT() is also defined, these tests may catch \ + * the list data structures being overwritten in memory. They will not catch \ + * data errors caused by incorrect configuration or use of FreeRTOS. */ \ + listTEST_LIST_INTEGRITY( ( pxList ) ); \ + listTEST_LIST_ITEM_INTEGRITY( ( pxNewListItem ) ); \ + \ + /* Insert a new list item into ( pxList ), but rather than sort the list, \ + * makes the new list item the last item to be removed by a call to \ + * listGET_OWNER_OF_NEXT_ENTRY(). */ \ + ( pxNewListItem )->pxNext = pxIndex; \ + ( pxNewListItem )->pxPrevious = pxIndex->pxPrevious; \ + \ + pxIndex->pxPrevious->pxNext = ( pxNewListItem ); \ + pxIndex->pxPrevious = ( pxNewListItem ); \ + \ + /* Remember which list the item is in. */ \ + ( pxNewListItem )->pxContainer = ( pxList ); \ + \ + ( ( pxList )->uxNumberOfItems )++; \ + } while( 0 ) /* * Access function to obtain the owner of the first entry in a list. Lists @@ -359,7 +449,7 @@ void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION; /* * Insert a list item into a list. The item will be inserted into the list in - * a position determined by its item value (descending item value order). + * a position determined by its item value (ascending item value order). * * @param pxList The list into which the item is to be inserted. * diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/message_buffer.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/message_buffer.h index aa05f233cb..f11639c6c8 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/message_buffer.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/message_buffer.h @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -78,18 +84,19 @@ * Type by which message buffers are referenced. For example, a call to * xMessageBufferCreate() returns an MessageBufferHandle_t variable that can * then be used as a parameter to xMessageBufferSend(), xMessageBufferReceive(), - * etc. + * etc. Message buffer is essentially built as a stream buffer hence its handle + * is also set to same type as a stream buffer handle. */ -typedef void * MessageBufferHandle_t; +typedef StreamBufferHandle_t MessageBufferHandle_t; /*-----------------------------------------------------------*/ /** * message_buffer.h * - *
+ * @code{c}
  * MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes );
- * 
+ * @endcode * * Creates a new message buffer using dynamically allocated memory. See * xMessageBufferCreateStatic() for a version that uses statically allocated @@ -105,6 +112,18 @@ typedef void * MessageBufferHandle_t; * 32-bit architecture, so on most 32-bit architectures a 10 byte message will * take up 14 bytes of message buffer space. * + * @param pxSendCompletedCallback Callback invoked when a send operation to the + * message buffer is complete. If the parameter is NULL or xMessageBufferCreate() + * is called without the parameter, then it will use the default implementation + * provided by sbSEND_COMPLETED macro. To enable the callback, + * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h. + * + * @param pxReceiveCompletedCallback Callback invoked when a receive operation from + * the message buffer is complete. If the parameter is NULL or xMessageBufferCreate() + * is called without the parameter, it will use the default implementation provided + * by sbRECEIVE_COMPLETED macro. To enable the callback, + * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h. + * * @return If NULL is returned, then the message buffer cannot be created * because there is insufficient heap memory available for FreeRTOS to allocate * the message buffer data structures and storage area. A non-NULL value being @@ -113,7 +132,7 @@ typedef void * MessageBufferHandle_t; * buffer. * * Example use: - *
+ * @code{c}
  *
  * void vAFunction( void )
  * {
@@ -123,7 +142,7 @@ typedef void * MessageBufferHandle_t;
  *  // Create a message buffer that can hold 100 bytes.  The memory used to hold
  *  // both the message buffer structure and the messages themselves is allocated
  *  // dynamically.  Each message added to the buffer consumes an additional 4
- *  // bytes which are used to hold the lengh of the message.
+ *  // bytes which are used to hold the length of the message.
  *  xMessageBuffer = xMessageBufferCreate( xMessageBufferSizeBytes );
  *
  *  if( xMessageBuffer == NULL )
@@ -136,21 +155,26 @@ typedef void * MessageBufferHandle_t;
  *      // The message buffer was created successfully and can now be used.
  *  }
  *
- * 
+ * @endcode * \defgroup xMessageBufferCreate xMessageBufferCreate * \ingroup MessageBufferManagement */ #define xMessageBufferCreate( xBufferSizeBytes ) \ - ( MessageBufferHandle_t ) xStreamBufferGenericCreate( xBufferSizeBytes, ( size_t ) 0, pdTRUE ) + xStreamBufferGenericCreate( ( xBufferSizeBytes ), ( size_t ) 0, pdTRUE, NULL, NULL ) + +#if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) + #define xMessageBufferCreateWithCallback( xBufferSizeBytes, pxSendCompletedCallback, pxReceiveCompletedCallback ) \ + xStreamBufferGenericCreate( ( xBufferSizeBytes ), ( size_t ) 0, pdTRUE, ( pxSendCompletedCallback ), ( pxReceiveCompletedCallback ) ) +#endif /** * message_buffer.h * - *
+ * @code{c}
  * MessageBufferHandle_t xMessageBufferCreateStatic( size_t xBufferSizeBytes,
  *                                                uint8_t *pucMessageBufferStorageArea,
  *                                                StaticMessageBuffer_t *pxStaticMessageBuffer );
- * 
+ * @endcode * Creates a new message buffer using statically allocated memory. See * xMessageBufferCreate() for a version that uses dynamically allocated memory. * @@ -163,19 +187,29 @@ typedef void * MessageBufferHandle_t; * stored in the message buffer is actually (xBufferSizeBytes - 1). * * @param pucMessageBufferStorageArea Must point to a uint8_t array that is at - * least xBufferSizeBytes + 1 big. This is the array to which messages are + * least xBufferSizeBytes big. This is the array to which messages are * copied when they are written to the message buffer. * * @param pxStaticMessageBuffer Must point to a variable of type * StaticMessageBuffer_t, which will be used to hold the message buffer's data * structure. * + * @param pxSendCompletedCallback Callback invoked when a new message is sent to the message buffer. + * If the parameter is NULL or xMessageBufferCreate() is called without the parameter, then it will use the default + * implementation provided by sbSEND_COMPLETED macro. To enable the callback, + * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h. + * + * @param pxReceiveCompletedCallback Callback invoked when a message is read from a + * message buffer. If the parameter is NULL or xMessageBufferCreate() is called without the parameter, it will + * use the default implementation provided by sbRECEIVE_COMPLETED macro. To enable the callback, + * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h. + * * @return If the message buffer is created successfully then a handle to the * created message buffer is returned. If either pucMessageBufferStorageArea or * pxStaticmessageBuffer are NULL then NULL is returned. * * Example use: - *
+ * @code{c}
  *
  * // Used to dimension the array used to hold the messages.  The available space
  * // will actually be one less than this, so 999.
@@ -192,8 +226,8 @@ typedef void * MessageBufferHandle_t;
  * {
  * MessageBufferHandle_t xMessageBuffer;
  *
- *  xMessageBuffer = xMessageBufferCreateStatic( sizeof( ucBufferStorage ),
- *                                               ucBufferStorage,
+ *  xMessageBuffer = xMessageBufferCreateStatic( sizeof( ucStorageBuffer ),
+ *                                               ucStorageBuffer,
  *                                               &xMessageBufferStruct );
  *
  *  // As neither the pucMessageBufferStorageArea or pxStaticMessageBuffer
@@ -203,12 +237,17 @@ typedef void * MessageBufferHandle_t;
  *  // Other code that uses the message buffer can go here.
  * }
  *
- * 
+ * @endcode * \defgroup xMessageBufferCreateStatic xMessageBufferCreateStatic * \ingroup MessageBufferManagement */ #define xMessageBufferCreateStatic( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer ) \ - ( MessageBufferHandle_t ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, 0, pdTRUE, pucMessageBufferStorageArea, pxStaticMessageBuffer ) + xStreamBufferGenericCreateStatic( ( xBufferSizeBytes ), 0, pdTRUE, ( pucMessageBufferStorageArea ), ( pxStaticMessageBuffer ), NULL, NULL ) + +#if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) + #define xMessageBufferCreateStaticWithCallback( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback ) \ + xStreamBufferGenericCreateStatic( ( xBufferSizeBytes ), 0, pdTRUE, ( pucMessageBufferStorageArea ), ( pxStaticMessageBuffer ), ( pxSendCompletedCallback ), ( pxReceiveCompletedCallback ) ) +#endif /** * message_buffer.h @@ -244,12 +283,12 @@ typedef void * MessageBufferHandle_t; /** * message_buffer.h * - *
+ * @code{c}
  * size_t xMessageBufferSend( MessageBufferHandle_t xMessageBuffer,
  *                         const void *pvTxData,
  *                         size_t xDataLengthBytes,
  *                         TickType_t xTicksToWait );
- * 
+ * @endcode * * Sends a discrete message to the message buffer. The message can be any * length that fits within the buffer's free space, and is copied into the @@ -306,7 +345,7 @@ typedef void * MessageBufferHandle_t; * time out then xDataLengthBytes is returned. * * Example use: - *
+ * @code{c}
  * void vAFunction( MessageBufferHandle_t xMessageBuffer )
  * {
  * size_t xBytesSent;
@@ -334,22 +373,22 @@ typedef void * MessageBufferHandle_t;
  *      // not enough free space in the buffer.
  *  }
  * }
- * 
+ * @endcode * \defgroup xMessageBufferSend xMessageBufferSend * \ingroup MessageBufferManagement */ #define xMessageBufferSend( xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) \ - xStreamBufferSend( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) + xStreamBufferSend( ( xMessageBuffer ), ( pvTxData ), ( xDataLengthBytes ), ( xTicksToWait ) ) /** * message_buffer.h * - *
+ * @code{c}
  * size_t xMessageBufferSendFromISR( MessageBufferHandle_t xMessageBuffer,
  *                                const void *pvTxData,
  *                                size_t xDataLengthBytes,
  *                                BaseType_t *pxHigherPriorityTaskWoken );
- * 
+ * @endcode * * Interrupt safe version of the API function that sends a discrete message to * the message buffer. The message can be any length that fits within the @@ -407,7 +446,7 @@ typedef void * MessageBufferHandle_t; * then 0 is returned, otherwise xDataLengthBytes is returned. * * Example use: - *
+ * @code{c}
  * // A message buffer that has already been created.
  * MessageBufferHandle_t xMessageBuffer;
  *
@@ -439,22 +478,22 @@ typedef void * MessageBufferHandle_t;
  *  // documentation for the port in use for port specific instructions.
  *  portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
  * }
- * 
+ * @endcode * \defgroup xMessageBufferSendFromISR xMessageBufferSendFromISR * \ingroup MessageBufferManagement */ #define xMessageBufferSendFromISR( xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) \ - xStreamBufferSendFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) + xStreamBufferSendFromISR( ( xMessageBuffer ), ( pvTxData ), ( xDataLengthBytes ), ( pxHigherPriorityTaskWoken ) ) /** * message_buffer.h * - *
+ * @code{c}
  * size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer,
  *                            void *pvRxData,
  *                            size_t xBufferLengthBytes,
  *                            TickType_t xTicksToWait );
- * 
+ * @endcode * * Receives a discrete message from a message buffer. Messages can be of * variable length and are copied out of the buffer. @@ -507,7 +546,7 @@ typedef void * MessageBufferHandle_t; * zero is returned. * * Example use: - *
+ * @code{c}
  * void vAFunction( MessageBuffer_t xMessageBuffer )
  * {
  * uint8_t ucRxData[ 20 ];
@@ -528,23 +567,23 @@ typedef void * MessageBufferHandle_t;
  *      // the message here....
  *  }
  * }
- * 
+ * @endcode * \defgroup xMessageBufferReceive xMessageBufferReceive * \ingroup MessageBufferManagement */ #define xMessageBufferReceive( xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) \ - xStreamBufferReceive( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) + xStreamBufferReceive( ( xMessageBuffer ), ( pvRxData ), ( xBufferLengthBytes ), ( xTicksToWait ) ) /** * message_buffer.h * - *
+ * @code{c}
  * size_t xMessageBufferReceiveFromISR( MessageBufferHandle_t xMessageBuffer,
  *                                   void *pvRxData,
  *                                   size_t xBufferLengthBytes,
  *                                   BaseType_t *pxHigherPriorityTaskWoken );
- * 
+ * @endcode * * An interrupt safe version of the API function that receives a discrete * message from a message buffer. Messages can be of variable length and are @@ -598,7 +637,7 @@ typedef void * MessageBufferHandle_t; * any. * * Example use: - *
+ * @code{c}
  * // A message buffer that has already been created.
  * MessageBuffer_t xMessageBuffer;
  *
@@ -630,19 +669,19 @@ typedef void * MessageBufferHandle_t;
  *  // documentation for the port in use for port specific instructions.
  *  portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
  * }
- * 
+ * @endcode * \defgroup xMessageBufferReceiveFromISR xMessageBufferReceiveFromISR * \ingroup MessageBufferManagement */ #define xMessageBufferReceiveFromISR( xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) \ - xStreamBufferReceiveFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) + xStreamBufferReceiveFromISR( ( xMessageBuffer ), ( pvRxData ), ( xBufferLengthBytes ), ( pxHigherPriorityTaskWoken ) ) /** * message_buffer.h * - *
+ * @code{c}
  * void vMessageBufferDelete( MessageBufferHandle_t xMessageBuffer );
- * 
+ * @endcode * * Deletes a message buffer that was previously created using a call to * xMessageBufferCreate() or xMessageBufferCreateStatic(). If the message @@ -656,13 +695,13 @@ typedef void * MessageBufferHandle_t; * */ #define vMessageBufferDelete( xMessageBuffer ) \ - vStreamBufferDelete( ( StreamBufferHandle_t ) xMessageBuffer ) + vStreamBufferDelete( xMessageBuffer ) /** * message_buffer.h - *
+ * @code{c}
  * BaseType_t xMessageBufferIsFull( MessageBufferHandle_t xMessageBuffer );
- * 
+ * @endcode * * Tests to see if a message buffer is full. A message buffer is full if it * cannot accept any more messages, of any size, until space is made available @@ -674,13 +713,13 @@ typedef void * MessageBufferHandle_t; * pdTRUE is returned. Otherwise pdFALSE is returned. */ #define xMessageBufferIsFull( xMessageBuffer ) \ - xStreamBufferIsFull( ( StreamBufferHandle_t ) xMessageBuffer ) + xStreamBufferIsFull( xMessageBuffer ) /** * message_buffer.h - *
+ * @code{c}
  * BaseType_t xMessageBufferIsEmpty( MessageBufferHandle_t xMessageBuffer );
- * 
+ * @endcode * * Tests to see if a message buffer is empty (does not contain any messages). * @@ -691,13 +730,13 @@ typedef void * MessageBufferHandle_t; * */ #define xMessageBufferIsEmpty( xMessageBuffer ) \ - xStreamBufferIsEmpty( ( StreamBufferHandle_t ) xMessageBuffer ) + xStreamBufferIsEmpty( xMessageBuffer ) /** * message_buffer.h - *
+ * @code{c}
  * BaseType_t xMessageBufferReset( MessageBufferHandle_t xMessageBuffer );
- * 
+ * @endcode * * Resets a message buffer to its initial empty state, discarding any message it * contained. @@ -715,14 +754,14 @@ typedef void * MessageBufferHandle_t; * \ingroup MessageBufferManagement */ #define xMessageBufferReset( xMessageBuffer ) \ - xStreamBufferReset( ( StreamBufferHandle_t ) xMessageBuffer ) + xStreamBufferReset( xMessageBuffer ) /** * message_buffer.h - *
+ * @code{c}
  * size_t xMessageBufferSpaceAvailable( MessageBufferHandle_t xMessageBuffer );
- * 
+ * @endcode * Returns the number of bytes of free space in the message buffer. * * @param xMessageBuffer The handle of the message buffer being queried. @@ -738,15 +777,15 @@ typedef void * MessageBufferHandle_t; * \ingroup MessageBufferManagement */ #define xMessageBufferSpaceAvailable( xMessageBuffer ) \ - xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer ) + xStreamBufferSpacesAvailable( xMessageBuffer ) #define xMessageBufferSpacesAvailable( xMessageBuffer ) \ - xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer ) /* Corrects typo in original macro name. */ + xStreamBufferSpacesAvailable( xMessageBuffer ) /* Corrects typo in original macro name. */ /** * message_buffer.h - *
+ * @code{c}
  * size_t xMessageBufferNextLengthBytes( MessageBufferHandle_t xMessageBuffer );
- * 
+ * @endcode * Returns the length (in bytes) of the next message in a message buffer. * Useful if xMessageBufferReceive() returned 0 because the size of the buffer * passed into xMessageBufferReceive() was too small to hold the next message. @@ -760,14 +799,14 @@ typedef void * MessageBufferHandle_t; * \ingroup MessageBufferManagement */ #define xMessageBufferNextLengthBytes( xMessageBuffer ) \ - xStreamBufferNextMessageLengthBytes( ( StreamBufferHandle_t ) xMessageBuffer ) PRIVILEGED_FUNCTION; + xStreamBufferNextMessageLengthBytes( xMessageBuffer ) PRIVILEGED_FUNCTION; /** * message_buffer.h * - *
- * BaseType_t xMessageBufferSendCompletedFromISR( MessageBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
- * 
+ * @code{c} + * BaseType_t xMessageBufferSendCompletedFromISR( MessageBufferHandle_t xMessageBuffer, BaseType_t *pxHigherPriorityTaskWoken ); + * @endcode * * For advanced users only. * @@ -782,7 +821,7 @@ typedef void * MessageBufferHandle_t; * See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for * additional information. * - * @param xStreamBuffer The handle of the stream buffer to which data was + * @param xMessageBuffer The handle of the stream buffer to which data was * written. * * @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be @@ -800,14 +839,14 @@ typedef void * MessageBufferHandle_t; * \ingroup StreamBufferManagement */ #define xMessageBufferSendCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) \ - xStreamBufferSendCompletedFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pxHigherPriorityTaskWoken ) + xStreamBufferSendCompletedFromISR( ( xMessageBuffer ), ( pxHigherPriorityTaskWoken ) ) /** * message_buffer.h * - *
- * BaseType_t xMessageBufferReceiveCompletedFromISR( MessageBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
- * 
+ * @code{c} + * BaseType_t xMessageBufferReceiveCompletedFromISR( MessageBufferHandle_t xMessageBuffer, BaseType_t *pxHigherPriorityTaskWoken ); + * @endcode * * For advanced users only. * @@ -823,7 +862,7 @@ typedef void * MessageBufferHandle_t; * See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for * additional information. * - * @param xStreamBuffer The handle of the stream buffer from which data was + * @param xMessageBuffer The handle of the stream buffer from which data was * read. * * @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be @@ -841,7 +880,7 @@ typedef void * MessageBufferHandle_t; * \ingroup StreamBufferManagement */ #define xMessageBufferReceiveCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) \ - xStreamBufferReceiveCompletedFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pxHigherPriorityTaskWoken ) + xStreamBufferReceiveCompletedFromISR( ( xMessageBuffer ), ( pxHigherPriorityTaskWoken ) ) /* *INDENT-OFF* */ #if defined( __cplusplus ) diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/mpu_prototypes.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/mpu_prototypes.h index 57cc0857c3..c954d5ce18 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/mpu_prototypes.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/mpu_prototypes.h @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -36,24 +42,46 @@ #ifndef MPU_PROTOTYPES_H #define MPU_PROTOTYPES_H -/* MPU versions of tasks.h API functions. */ -BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode, - const char * const pcName, - const uint16_t usStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - TaskHandle_t * const pxCreatedTask ) FREERTOS_SYSTEM_CALL; -TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode, - const char * const pcName, - const uint32_t ulStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - StackType_t * const puxStackBuffer, - StaticTask_t * const pxTaskBuffer ) FREERTOS_SYSTEM_CALL; -void MPU_vTaskDelete( TaskHandle_t xTaskToDelete ) FREERTOS_SYSTEM_CALL; +typedef struct xTaskGenericNotifyParams +{ + TaskHandle_t xTaskToNotify; + UBaseType_t uxIndexToNotify; + uint32_t ulValue; + eNotifyAction eAction; + uint32_t * pulPreviousNotificationValue; +} xTaskGenericNotifyParams_t; + +typedef struct xTaskGenericNotifyWaitParams +{ + UBaseType_t uxIndexToWaitOn; + uint32_t ulBitsToClearOnEntry; + uint32_t ulBitsToClearOnExit; + uint32_t * pulNotificationValue; + TickType_t xTicksToWait; +} xTaskGenericNotifyWaitParams_t; + +typedef struct xTimerGenericCommandFromTaskParams +{ + TimerHandle_t xTimer; + BaseType_t xCommandID; + TickType_t xOptionalValue; + BaseType_t * pxHigherPriorityTaskWoken; + TickType_t xTicksToWait; +} xTimerGenericCommandFromTaskParams_t; + +typedef struct xEventGroupWaitBitsParams +{ + EventGroupHandle_t xEventGroup; + EventBits_t uxBitsToWaitFor; + BaseType_t xClearOnExit; + BaseType_t xWaitForAllBits; + TickType_t xTicksToWait; +} xEventGroupWaitBitsParams_t; + +/* MPU versions of task.h API functions. */ void MPU_vTaskDelay( const TickType_t xTicksToDelay ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, - const TickType_t xTimeIncrement ) FREERTOS_SYSTEM_CALL; + const TickType_t xTimeIncrement ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; UBaseType_t MPU_uxTaskPriorityGet( const TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; eTaskState MPU_eTaskGetState( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; @@ -61,17 +89,10 @@ void MPU_vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t * pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState ) FREERTOS_SYSTEM_CALL; -void MPU_vTaskPrioritySet( TaskHandle_t xTask, - UBaseType_t uxNewPriority ) FREERTOS_SYSTEM_CALL; void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend ) FREERTOS_SYSTEM_CALL; void MPU_vTaskResume( TaskHandle_t xTaskToResume ) FREERTOS_SYSTEM_CALL; -void MPU_vTaskStartScheduler( void ) FREERTOS_SYSTEM_CALL; -void MPU_vTaskSuspendAll( void ) FREERTOS_SYSTEM_CALL; -BaseType_t MPU_xTaskResumeAll( void ) FREERTOS_SYSTEM_CALL; TickType_t MPU_xTaskGetTickCount( void ) FREERTOS_SYSTEM_CALL; UBaseType_t MPU_uxTaskGetNumberOfTasks( void ) FREERTOS_SYSTEM_CALL; -char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ) FREERTOS_SYSTEM_CALL; -TaskHandle_t MPU_xTaskGetHandle( const char * pcNameToQuery ) FREERTOS_SYSTEM_CALL; UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; configSTACK_DEPTH_TYPE MPU_uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask, @@ -82,25 +103,26 @@ void MPU_vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, void * pvValue ) FREERTOS_SYSTEM_CALL; void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ) FREERTOS_SYSTEM_CALL; -BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, - void * pvParameter ) FREERTOS_SYSTEM_CALL; TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ) FREERTOS_SYSTEM_CALL; UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, - uint32_t * const pulTotalRunTime ) FREERTOS_SYSTEM_CALL; -uint32_t MPU_ulTaskGetIdleRunTimeCounter( void ) FREERTOS_SYSTEM_CALL; -void MPU_vTaskList( char * pcWriteBuffer ) FREERTOS_SYSTEM_CALL; -void MPU_vTaskGetRunTimeStats( char * pcWriteBuffer ) FREERTOS_SYSTEM_CALL; + configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) FREERTOS_SYSTEM_CALL; +configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetRunTimeCounter( const TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; +configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetRunTimePercent( const TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; +configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimeCounter( void ) FREERTOS_SYSTEM_CALL; +configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimePercent( void ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t * pulPreviousNotificationValue ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskGenericNotifyEntry( const xTaskGenericNotifyParams_t * pxParams ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t * pulNotificationValue, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskGenericNotifyWaitEntry( const xTaskGenericNotifyWaitParams_t * pxParams ) FREERTOS_SYSTEM_CALL; uint32_t MPU_ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; @@ -109,14 +131,58 @@ BaseType_t MPU_xTaskGenericNotifyStateClear( TaskHandle_t xTask, uint32_t MPU_ulTaskGenericNotifyValueClear( TaskHandle_t xTask, UBaseType_t uxIndexToClear, uint32_t ulBitsToClear ) FREERTOS_SYSTEM_CALL; -BaseType_t MPU_xTaskIncrementTick( void ) FREERTOS_SYSTEM_CALL; -TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) FREERTOS_SYSTEM_CALL; void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) FREERTOS_SYSTEM_CALL; -void MPU_vTaskMissedYield( void ) FREERTOS_SYSTEM_CALL; +TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xTaskGetSchedulerState( void ) FREERTOS_SYSTEM_CALL; -BaseType_t MPU_xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) FREERTOS_SYSTEM_CALL; + +/* Privileged only wrappers for Task APIs. These are needed so that + * the application can use opaque handles maintained in mpu_wrappers.c + * with all the APIs. */ +BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint16_t usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION; +TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + StackType_t * const puxStackBuffer, + StaticTask_t * const pxTaskBuffer ) PRIVILEGED_FUNCTION; +void MPU_vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; +void MPU_vTaskPrioritySet( TaskHandle_t xTask, + UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION; +TaskHandle_t MPU_xTaskGetHandle( const char * pcNameToQuery ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, + void * pvParameter ) PRIVILEGED_FUNCTION; +char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, + TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, + TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; +void MPU_vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, + const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xTaskGetStaticBuffers( TaskHandle_t xTask, + StackType_t ** ppuxStackBuffer, + StaticTask_t ** ppxTaskBuffer ) PRIVILEGED_FUNCTION; +UBaseType_t MPU_uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; +UBaseType_t MPU_uxTaskBasePriorityGet( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; +UBaseType_t MPU_uxTaskBasePriorityGetFromISR( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; +TaskHookFunction_t MPU_xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + uint32_t ulValue, + eNotifyAction eAction, + uint32_t * pulPreviousNotificationValue, + BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +void MPU_vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; /* MPU versions of queue.h API functions. */ BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, @@ -133,15 +199,6 @@ BaseType_t MPU_xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; -void MPU_vQueueDelete( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; -QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL; -QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType, - StaticQueue_t * pxStaticQueue ) FREERTOS_SYSTEM_CALL; -QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, - const UBaseType_t uxInitialCount ) FREERTOS_SYSTEM_CALL; -QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, - const UBaseType_t uxInitialCount, - StaticQueue_t * pxStaticQueue ) FREERTOS_SYSTEM_CALL; TaskHandle_t MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; @@ -150,70 +207,109 @@ void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, const char * pcName ) FREERTOS_SYSTEM_CALL; void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; const char * MPU_pcQueueGetName( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; -QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength, - const UBaseType_t uxItemSize, - const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL; -QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, - const UBaseType_t uxItemSize, - uint8_t * pucQueueStorage, - StaticQueue_t * pxStaticQueue, - const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL; -QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL; -BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, - QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL; QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; -BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue, - BaseType_t xNewQueue ) FREERTOS_SYSTEM_CALL; void MPU_vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) FREERTOS_SYSTEM_CALL; UBaseType_t MPU_uxQueueGetQueueNumber( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; uint8_t MPU_ucQueueGetQueueType( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; +/* Privileged only wrappers for Queue APIs. These are needed so that + * the application can use opaque handles maintained in mpu_wrappers.c + * with all the APIs. */ +void MPU_vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; +QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType, + StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION; +QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, + const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION; +QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, + const UBaseType_t uxInitialCount, + StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION; +QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength, + const UBaseType_t uxItemSize, + const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; +QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, + const UBaseType_t uxItemSize, + uint8_t * pucQueueStorage, + StaticQueue_t * pxStaticQueue, + const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; +QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, + QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue, + BaseType_t xNewQueue ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xQueueGenericGetStaticBuffers( QueueHandle_t xQueue, + uint8_t ** ppucQueueStorage, + StaticQueue_t ** ppxStaticQueue ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xQueueGenericSendFromISR( QueueHandle_t xQueue, + const void * const pvItemToQueue, + BaseType_t * const pxHigherPriorityTaskWoken, + const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xQueueGiveFromISR( QueueHandle_t xQueue, + BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xQueuePeekFromISR( QueueHandle_t xQueue, + void * const pvBuffer ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xQueueReceiveFromISR( QueueHandle_t xQueue, + void * const pvBuffer, + BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +UBaseType_t MPU_uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +TaskHandle_t MPU_xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION; +QueueSetMemberHandle_t MPU_xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; + /* MPU versions of timers.h API functions. */ -TimerHandle_t MPU_xTimerCreate( const char * const pcTimerName, - const TickType_t xTimerPeriodInTicks, - const UBaseType_t uxAutoReload, - void * const pvTimerID, - TimerCallbackFunction_t pxCallbackFunction ) FREERTOS_SYSTEM_CALL; -TimerHandle_t MPU_xTimerCreateStatic( const char * const pcTimerName, - const TickType_t xTimerPeriodInTicks, - const UBaseType_t uxAutoReload, - void * const pvTimerID, - TimerCallbackFunction_t pxCallbackFunction, - StaticTimer_t * pxTimerBuffer ) FREERTOS_SYSTEM_CALL; void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; void MPU_vTimerSetTimerID( TimerHandle_t xTimer, void * pvNewID ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void ) FREERTOS_SYSTEM_CALL; -BaseType_t MPU_xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, - void * pvParameter1, - uint32_t ulParameter2, - TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTimerGenericCommandFromTask( TimerHandle_t xTimer, + const BaseType_t xCommandID, + const TickType_t xOptionalValue, + BaseType_t * const pxHigherPriorityTaskWoken, + const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTimerGenericCommandFromTaskEntry( const xTimerGenericCommandFromTaskParams_t * pxParams ) FREERTOS_SYSTEM_CALL; const char * MPU_pcTimerGetName( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; void MPU_vTimerSetReloadMode( TimerHandle_t xTimer, - const UBaseType_t uxAutoReload ) FREERTOS_SYSTEM_CALL; + const BaseType_t uxAutoReload ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTimerGetReloadMode( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; UBaseType_t MPU_uxTimerGetReloadMode( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; -BaseType_t MPU_xTimerCreateTimerTask( void ) FREERTOS_SYSTEM_CALL; -BaseType_t MPU_xTimerGenericCommand( TimerHandle_t xTimer, - const BaseType_t xCommandID, - const TickType_t xOptionalValue, - BaseType_t * const pxHigherPriorityTaskWoken, - const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; + +/* Privileged only wrappers for Timer APIs. These are needed so that + * the application can use opaque handles maintained in mpu_wrappers.c + * with all the APIs. */ +TimerHandle_t MPU_xTimerCreate( const char * const pcTimerName, + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, + void * const pvTimerID, + TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION; +TimerHandle_t MPU_xTimerCreateStatic( const char * const pcTimerName, + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, + void * const pvTimerID, + TimerCallbackFunction_t pxCallbackFunction, + StaticTimer_t * pxTimerBuffer ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xTimerGetStaticBuffer( TimerHandle_t xTimer, + StaticTimer_t ** ppxTimerBuffer ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xTimerGenericCommandFromISR( TimerHandle_t xTimer, + const BaseType_t xCommandID, + const TickType_t xOptionalValue, + BaseType_t * const pxHigherPriorityTaskWoken, + const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /* MPU versions of event_group.h API functions. */ -EventGroupHandle_t MPU_xEventGroupCreate( void ) FREERTOS_SYSTEM_CALL; -EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) FREERTOS_SYSTEM_CALL; EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +EventBits_t MPU_xEventGroupWaitBitsEntry( const xEventGroupWaitBitsParams_t * pxParams ) FREERTOS_SYSTEM_CALL; EventBits_t MPU_xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) FREERTOS_SYSTEM_CALL; EventBits_t MPU_xEventGroupSetBits( EventGroupHandle_t xEventGroup, @@ -222,8 +318,26 @@ EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; -void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup ) FREERTOS_SYSTEM_CALL; -UBaseType_t MPU_uxEventGroupGetNumber( void * xEventGroup ) FREERTOS_SYSTEM_CALL; +#if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t MPU_uxEventGroupGetNumber( void * xEventGroup ) FREERTOS_SYSTEM_CALL; + void MPU_vEventGroupSetNumber( void * xEventGroup, + UBaseType_t uxEventGroupNumber ) FREERTOS_SYSTEM_CALL; +#endif /* ( configUSE_TRACE_FACILITY == 1 )*/ + +/* Privileged only wrappers for Event Group APIs. These are needed so that + * the application can use opaque handles maintained in mpu_wrappers.c + * with all the APIs. */ +EventGroupHandle_t MPU_xEventGroupCreate( void ) PRIVILEGED_FUNCTION; +EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) PRIVILEGED_FUNCTION; +void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup, + StaticEventGroup_t ** ppxEventGroupBuffer ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToSet, + BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +EventBits_t MPU_xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION; /* MPU versions of message/stream_buffer.h API functions. */ size_t MPU_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, @@ -234,24 +348,45 @@ size_t MPU_xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, void * pvRxData, size_t xBufferLengthBytes, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; -size_t MPU_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; -void MPU_vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; -BaseType_t MPU_xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; size_t MPU_xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; size_t MPU_xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel ) FREERTOS_SYSTEM_CALL; +size_t MPU_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; + +/* Privileged only wrappers for Stream Buffer APIs. These are needed so that + * the application can use opaque handles maintained in mpu_wrappers.c + * with all the APIs. */ StreamBufferHandle_t MPU_xStreamBufferGenericCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes, - BaseType_t xIsMessageBuffer ) FREERTOS_SYSTEM_CALL; + BaseType_t xIsMessageBuffer, + StreamBufferCallbackFunction_t pxSendCompletedCallback, + StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION; StreamBufferHandle_t MPU_xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes, size_t xTriggerLevelBytes, BaseType_t xIsMessageBuffer, uint8_t * const pucStreamBufferStorageArea, - StaticStreamBuffer_t * const pxStaticStreamBuffer ) FREERTOS_SYSTEM_CALL; - - + StaticStreamBuffer_t * const pxStaticStreamBuffer, + StreamBufferCallbackFunction_t pxSendCompletedCallback, + StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION; +void MPU_vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xStreamBufferGetStaticBuffers( StreamBufferHandle_t xStreamBuffers, + uint8_t * ppucStreamBufferStorageArea, + StaticStreamBuffer_t * ppxStaticStreamBuffer ) PRIVILEGED_FUNCTION; +size_t MPU_xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, + const void * pvTxData, + size_t xDataLengthBytes, + BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +size_t MPU_xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, + void * pvRxData, + size_t xBufferLengthBytes, + BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, + BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +BaseType_t MPU_xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, + BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; #endif /* MPU_PROTOTYPES_H */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/mpu_syscall_numbers.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/mpu_syscall_numbers.h new file mode 100644 index 0000000000..6fad5f11e6 --- /dev/null +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/mpu_syscall_numbers.h @@ -0,0 +1,109 @@ +/* + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef MPU_SYSCALL_NUMBERS_H +#define MPU_SYSCALL_NUMBERS_H + +/* Numbers assigned to various system calls. */ +#define SYSTEM_CALL_xTaskGenericNotify 0 +#define SYSTEM_CALL_xTaskGenericNotifyWait 1 +#define SYSTEM_CALL_xTimerGenericCommandFromTask 2 +#define SYSTEM_CALL_xEventGroupWaitBits 3 +#define SYSTEM_CALL_xTaskDelayUntil 4 +#define SYSTEM_CALL_xTaskAbortDelay 5 +#define SYSTEM_CALL_vTaskDelay 6 +#define SYSTEM_CALL_uxTaskPriorityGet 7 +#define SYSTEM_CALL_eTaskGetState 8 +#define SYSTEM_CALL_vTaskGetInfo 9 +#define SYSTEM_CALL_xTaskGetIdleTaskHandle 10 +#define SYSTEM_CALL_vTaskSuspend 11 +#define SYSTEM_CALL_vTaskResume 12 +#define SYSTEM_CALL_xTaskGetTickCount 13 +#define SYSTEM_CALL_uxTaskGetNumberOfTasks 14 +#define SYSTEM_CALL_ulTaskGetRunTimeCounter 15 +#define SYSTEM_CALL_ulTaskGetRunTimePercent 16 +#define SYSTEM_CALL_ulTaskGetIdleRunTimePercent 17 +#define SYSTEM_CALL_ulTaskGetIdleRunTimeCounter 18 +#define SYSTEM_CALL_vTaskSetApplicationTaskTag 19 +#define SYSTEM_CALL_xTaskGetApplicationTaskTag 20 +#define SYSTEM_CALL_vTaskSetThreadLocalStoragePointer 21 +#define SYSTEM_CALL_pvTaskGetThreadLocalStoragePointer 22 +#define SYSTEM_CALL_uxTaskGetSystemState 23 +#define SYSTEM_CALL_uxTaskGetStackHighWaterMark 24 +#define SYSTEM_CALL_uxTaskGetStackHighWaterMark2 25 +#define SYSTEM_CALL_xTaskGetCurrentTaskHandle 26 +#define SYSTEM_CALL_xTaskGetSchedulerState 27 +#define SYSTEM_CALL_vTaskSetTimeOutState 28 +#define SYSTEM_CALL_xTaskCheckForTimeOut 29 +#define SYSTEM_CALL_ulTaskGenericNotifyTake 30 +#define SYSTEM_CALL_xTaskGenericNotifyStateClear 31 +#define SYSTEM_CALL_ulTaskGenericNotifyValueClear 32 +#define SYSTEM_CALL_xQueueGenericSend 33 +#define SYSTEM_CALL_uxQueueMessagesWaiting 34 +#define SYSTEM_CALL_uxQueueSpacesAvailable 35 +#define SYSTEM_CALL_xQueueReceive 36 +#define SYSTEM_CALL_xQueuePeek 37 +#define SYSTEM_CALL_xQueueSemaphoreTake 38 +#define SYSTEM_CALL_xQueueGetMutexHolder 39 +#define SYSTEM_CALL_xQueueTakeMutexRecursive 40 +#define SYSTEM_CALL_xQueueGiveMutexRecursive 41 +#define SYSTEM_CALL_xQueueSelectFromSet 42 +#define SYSTEM_CALL_xQueueAddToSet 43 +#define SYSTEM_CALL_vQueueAddToRegistry 44 +#define SYSTEM_CALL_vQueueUnregisterQueue 45 +#define SYSTEM_CALL_pcQueueGetName 46 +#define SYSTEM_CALL_pvTimerGetTimerID 47 +#define SYSTEM_CALL_vTimerSetTimerID 48 +#define SYSTEM_CALL_xTimerIsTimerActive 49 +#define SYSTEM_CALL_xTimerGetTimerDaemonTaskHandle 50 +#define SYSTEM_CALL_pcTimerGetName 51 +#define SYSTEM_CALL_vTimerSetReloadMode 52 +#define SYSTEM_CALL_xTimerGetReloadMode 53 +#define SYSTEM_CALL_uxTimerGetReloadMode 54 +#define SYSTEM_CALL_xTimerGetPeriod 55 +#define SYSTEM_CALL_xTimerGetExpiryTime 56 +#define SYSTEM_CALL_xEventGroupClearBits 57 +#define SYSTEM_CALL_xEventGroupSetBits 58 +#define SYSTEM_CALL_xEventGroupSync 59 +#define SYSTEM_CALL_uxEventGroupGetNumber 60 +#define SYSTEM_CALL_vEventGroupSetNumber 61 +#define SYSTEM_CALL_xStreamBufferSend 62 +#define SYSTEM_CALL_xStreamBufferReceive 63 +#define SYSTEM_CALL_xStreamBufferIsFull 64 +#define SYSTEM_CALL_xStreamBufferIsEmpty 65 +#define SYSTEM_CALL_xStreamBufferSpacesAvailable 66 +#define SYSTEM_CALL_xStreamBufferBytesAvailable 67 +#define SYSTEM_CALL_xStreamBufferSetTriggerLevel 68 +#define SYSTEM_CALL_xStreamBufferNextMessageLengthBytes 69 +#define NUM_SYSTEM_CALLS 70 /* Total number of system calls. */ + +#endif /* MPU_SYSCALL_NUMBERS_H */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/mpu_wrappers.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/mpu_wrappers.h index d04ce9b8cf..bbf4e70e1e 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/mpu_wrappers.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/mpu_wrappers.h @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -29,7 +35,7 @@ /* This file redefines API functions to be called through a wrapper macro, but * only for ports that are using the MPU. */ -#ifdef portUSING_MPU_WRAPPERS +#if ( portUSING_MPU_WRAPPERS == 1 ) /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is * included from queue.c or task.c to prevent it from having an effect within @@ -44,117 +50,188 @@ * privileges. */ -/* Map standard tasks.h API functions to the MPU equivalents. */ - #define xTaskCreate MPU_xTaskCreate - #define xTaskCreateStatic MPU_xTaskCreateStatic - #define vTaskDelete MPU_vTaskDelete - #define vTaskDelay MPU_vTaskDelay - #define xTaskDelayUntil MPU_xTaskDelayUntil - #define xTaskAbortDelay MPU_xTaskAbortDelay - #define uxTaskPriorityGet MPU_uxTaskPriorityGet - #define eTaskGetState MPU_eTaskGetState - #define vTaskGetInfo MPU_vTaskGetInfo - #define vTaskPrioritySet MPU_vTaskPrioritySet - #define vTaskSuspend MPU_vTaskSuspend - #define vTaskResume MPU_vTaskResume - #define vTaskSuspendAll MPU_vTaskSuspendAll - #define xTaskResumeAll MPU_xTaskResumeAll - #define xTaskGetTickCount MPU_xTaskGetTickCount - #define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks - #define pcTaskGetName MPU_pcTaskGetName - #define xTaskGetHandle MPU_xTaskGetHandle - #define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark - #define uxTaskGetStackHighWaterMark2 MPU_uxTaskGetStackHighWaterMark2 - #define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag - #define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag - #define vTaskSetThreadLocalStoragePointer MPU_vTaskSetThreadLocalStoragePointer - #define pvTaskGetThreadLocalStoragePointer MPU_pvTaskGetThreadLocalStoragePointer - #define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook - #define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle - #define uxTaskGetSystemState MPU_uxTaskGetSystemState - #define vTaskList MPU_vTaskList - #define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats - #define ulTaskGetIdleRunTimeCounter MPU_ulTaskGetIdleRunTimeCounter - #define xTaskGenericNotify MPU_xTaskGenericNotify - #define xTaskGenericNotifyWait MPU_xTaskGenericNotifyWait - #define ulTaskGenericNotifyTake MPU_ulTaskGenericNotifyTake - #define xTaskGenericNotifyStateClear MPU_xTaskGenericNotifyStateClear - #define ulTaskGenericNotifyValueClear MPU_ulTaskGenericNotifyValueClear - #define xTaskCatchUpTicks MPU_xTaskCatchUpTicks +/* Map standard task.h API functions to the MPU equivalents. */ + #define vTaskDelay MPU_vTaskDelay + #define xTaskDelayUntil MPU_xTaskDelayUntil + #define xTaskAbortDelay MPU_xTaskAbortDelay + #define uxTaskPriorityGet MPU_uxTaskPriorityGet + #define eTaskGetState MPU_eTaskGetState + #define vTaskGetInfo MPU_vTaskGetInfo + #define vTaskSuspend MPU_vTaskSuspend + #define vTaskResume MPU_vTaskResume + #define xTaskGetTickCount MPU_xTaskGetTickCount + #define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks + #define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark + #define uxTaskGetStackHighWaterMark2 MPU_uxTaskGetStackHighWaterMark2 + #define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag + #define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag + #define vTaskSetThreadLocalStoragePointer MPU_vTaskSetThreadLocalStoragePointer + #define pvTaskGetThreadLocalStoragePointer MPU_pvTaskGetThreadLocalStoragePointer + #define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle + #define uxTaskGetSystemState MPU_uxTaskGetSystemState + #define ulTaskGetIdleRunTimeCounter MPU_ulTaskGetIdleRunTimeCounter + #define ulTaskGetIdleRunTimePercent MPU_ulTaskGetIdleRunTimePercent + #define xTaskGenericNotify MPU_xTaskGenericNotify + #define xTaskGenericNotifyWait MPU_xTaskGenericNotifyWait + #define ulTaskGenericNotifyTake MPU_ulTaskGenericNotifyTake + #define xTaskGenericNotifyStateClear MPU_xTaskGenericNotifyStateClear + #define ulTaskGenericNotifyValueClear MPU_ulTaskGenericNotifyValueClear + #define vTaskSetTimeOutState MPU_vTaskSetTimeOutState + #define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut + #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle + #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState - #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle - #define vTaskSetTimeOutState MPU_vTaskSetTimeOutState - #define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut - #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState + #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) + #define ulTaskGetRunTimeCounter MPU_ulTaskGetRunTimeCounter + #define ulTaskGetRunTimePercent MPU_ulTaskGetRunTimePercent + #endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */ + +/* Privileged only wrappers for Task APIs. These are needed so that + * the application can use opaque handles maintained in mpu_wrappers.c + * with all the APIs. */ + #define xTaskCreate MPU_xTaskCreate + #define xTaskCreateStatic MPU_xTaskCreateStatic + #define vTaskDelete MPU_vTaskDelete + #define vTaskPrioritySet MPU_vTaskPrioritySet + #define xTaskGetHandle MPU_xTaskGetHandle + #define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook + + #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) + #define pcTaskGetName MPU_pcTaskGetName + #define xTaskCreateRestricted MPU_xTaskCreateRestricted + #define xTaskCreateRestrictedStatic MPU_xTaskCreateRestrictedStatic + #define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions + #define xTaskGetStaticBuffers MPU_xTaskGetStaticBuffers + #define uxTaskPriorityGetFromISR MPU_uxTaskPriorityGetFromISR + #define uxTaskBasePriorityGet MPU_uxTaskBasePriorityGet + #define uxTaskBasePriorityGetFromISR MPU_uxTaskBasePriorityGetFromISR + #define xTaskResumeFromISR MPU_xTaskResumeFromISR + #define xTaskGetApplicationTaskTagFromISR MPU_xTaskGetApplicationTaskTagFromISR + #define xTaskGenericNotifyFromISR MPU_xTaskGenericNotifyFromISR + #define vTaskGenericNotifyGiveFromISR MPU_vTaskGenericNotifyGiveFromISR + #endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */ /* Map standard queue.h API functions to the MPU equivalents. */ - #define xQueueGenericSend MPU_xQueueGenericSend - #define xQueueReceive MPU_xQueueReceive - #define xQueuePeek MPU_xQueuePeek - #define xQueueSemaphoreTake MPU_xQueueSemaphoreTake - #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting - #define uxQueueSpacesAvailable MPU_uxQueueSpacesAvailable + #define xQueueGenericSend MPU_xQueueGenericSend + #define xQueueReceive MPU_xQueueReceive + #define xQueuePeek MPU_xQueuePeek + #define xQueueSemaphoreTake MPU_xQueueSemaphoreTake + #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting + #define uxQueueSpacesAvailable MPU_uxQueueSpacesAvailable + #define xQueueGetMutexHolder MPU_xQueueGetMutexHolder + #define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive + #define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive + #define xQueueAddToSet MPU_xQueueAddToSet + #define xQueueSelectFromSet MPU_xQueueSelectFromSet + + #if ( configQUEUE_REGISTRY_SIZE > 0 ) + #define vQueueAddToRegistry MPU_vQueueAddToRegistry + #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue + #define pcQueueGetName MPU_pcQueueGetName + #endif /* #if ( configQUEUE_REGISTRY_SIZE > 0 ) */ + +/* Privileged only wrappers for Queue APIs. These are needed so that + * the application can use opaque handles maintained in mpu_wrappers.c + * with all the APIs. */ #define vQueueDelete MPU_vQueueDelete #define xQueueCreateMutex MPU_xQueueCreateMutex #define xQueueCreateMutexStatic MPU_xQueueCreateMutexStatic #define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore #define xQueueCreateCountingSemaphoreStatic MPU_xQueueCreateCountingSemaphoreStatic - #define xQueueGetMutexHolder MPU_xQueueGetMutexHolder - #define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive - #define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive #define xQueueGenericCreate MPU_xQueueGenericCreate #define xQueueGenericCreateStatic MPU_xQueueGenericCreateStatic - #define xQueueCreateSet MPU_xQueueCreateSet - #define xQueueAddToSet MPU_xQueueAddToSet - #define xQueueRemoveFromSet MPU_xQueueRemoveFromSet - #define xQueueSelectFromSet MPU_xQueueSelectFromSet #define xQueueGenericReset MPU_xQueueGenericReset + #define xQueueCreateSet MPU_xQueueCreateSet + #define xQueueRemoveFromSet MPU_xQueueRemoveFromSet - #if ( configQUEUE_REGISTRY_SIZE > 0 ) - #define vQueueAddToRegistry MPU_vQueueAddToRegistry - #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue - #define pcQueueGetName MPU_pcQueueGetName - #endif + #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) + #define xQueueGenericGetStaticBuffers MPU_xQueueGenericGetStaticBuffers + #define xQueueGenericSendFromISR MPU_xQueueGenericSendFromISR + #define xQueueGiveFromISR MPU_xQueueGiveFromISR + #define xQueuePeekFromISR MPU_xQueuePeekFromISR + #define xQueueReceiveFromISR MPU_xQueueReceiveFromISR + #define xQueueIsQueueEmptyFromISR MPU_xQueueIsQueueEmptyFromISR + #define xQueueIsQueueFullFromISR MPU_xQueueIsQueueFullFromISR + #define uxQueueMessagesWaitingFromISR MPU_uxQueueMessagesWaitingFromISR + #define xQueueGetMutexHolderFromISR MPU_xQueueGetMutexHolderFromISR + #define xQueueSelectFromSetFromISR MPU_xQueueSelectFromSetFromISR + #endif /* if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */ /* Map standard timer.h API functions to the MPU equivalents. */ - #define xTimerCreate MPU_xTimerCreate - #define xTimerCreateStatic MPU_xTimerCreateStatic - #define pvTimerGetTimerID MPU_pvTimerGetTimerID - #define vTimerSetTimerID MPU_vTimerSetTimerID - #define xTimerIsTimerActive MPU_xTimerIsTimerActive - #define xTimerGetTimerDaemonTaskHandle MPU_xTimerGetTimerDaemonTaskHandle - #define xTimerPendFunctionCall MPU_xTimerPendFunctionCall - #define pcTimerGetName MPU_pcTimerGetName - #define vTimerSetReloadMode MPU_vTimerSetReloadMode - #define uxTimerGetReloadMode MPU_uxTimerGetReloadMode - #define xTimerGetPeriod MPU_xTimerGetPeriod - #define xTimerGetExpiryTime MPU_xTimerGetExpiryTime - #define xTimerGenericCommand MPU_xTimerGenericCommand + #define pvTimerGetTimerID MPU_pvTimerGetTimerID + #define vTimerSetTimerID MPU_vTimerSetTimerID + #define xTimerIsTimerActive MPU_xTimerIsTimerActive + #define xTimerGetTimerDaemonTaskHandle MPU_xTimerGetTimerDaemonTaskHandle + #define xTimerGenericCommandFromTask MPU_xTimerGenericCommandFromTask + #define pcTimerGetName MPU_pcTimerGetName + #define vTimerSetReloadMode MPU_vTimerSetReloadMode + #define uxTimerGetReloadMode MPU_uxTimerGetReloadMode + #define xTimerGetPeriod MPU_xTimerGetPeriod + #define xTimerGetExpiryTime MPU_xTimerGetExpiryTime + +/* Privileged only wrappers for Timer APIs. These are needed so that + * the application can use opaque handles maintained in mpu_wrappers.c + * with all the APIs. */ + #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) + #define xTimerGetReloadMode MPU_xTimerGetReloadMode + #define xTimerCreate MPU_xTimerCreate + #define xTimerCreateStatic MPU_xTimerCreateStatic + #define xTimerGetStaticBuffer MPU_xTimerGetStaticBuffer + #define xTimerGenericCommandFromISR MPU_xTimerGenericCommandFromISR + #endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */ /* Map standard event_group.h API functions to the MPU equivalents. */ - #define xEventGroupCreate MPU_xEventGroupCreate - #define xEventGroupCreateStatic MPU_xEventGroupCreateStatic - #define xEventGroupWaitBits MPU_xEventGroupWaitBits - #define xEventGroupClearBits MPU_xEventGroupClearBits - #define xEventGroupSetBits MPU_xEventGroupSetBits - #define xEventGroupSync MPU_xEventGroupSync - #define vEventGroupDelete MPU_vEventGroupDelete + #define xEventGroupWaitBits MPU_xEventGroupWaitBits + #define xEventGroupClearBits MPU_xEventGroupClearBits + #define xEventGroupSetBits MPU_xEventGroupSetBits + #define xEventGroupSync MPU_xEventGroupSync + + #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) + #define uxEventGroupGetNumber MPU_uxEventGroupGetNumber + #define vEventGroupSetNumber MPU_vEventGroupSetNumber + #endif /* #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) */ + +/* Privileged only wrappers for Event Group APIs. These are needed so that + * the application can use opaque handles maintained in mpu_wrappers.c + * with all the APIs. */ + #define xEventGroupCreate MPU_xEventGroupCreate + #define xEventGroupCreateStatic MPU_xEventGroupCreateStatic + #define vEventGroupDelete MPU_vEventGroupDelete + + #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) + #define xEventGroupGetStaticBuffer MPU_xEventGroupGetStaticBuffer + #define xEventGroupClearBitsFromISR MPU_xEventGroupClearBitsFromISR + #define xEventGroupSetBitsFromISR MPU_xEventGroupSetBitsFromISR + #define xEventGroupGetBitsFromISR MPU_xEventGroupGetBitsFromISR + #endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */ /* Map standard message/stream_buffer.h API functions to the MPU * equivalents. */ #define xStreamBufferSend MPU_xStreamBufferSend #define xStreamBufferReceive MPU_xStreamBufferReceive - #define xStreamBufferNextMessageLengthBytes MPU_xStreamBufferNextMessageLengthBytes - #define vStreamBufferDelete MPU_vStreamBufferDelete #define xStreamBufferIsFull MPU_xStreamBufferIsFull #define xStreamBufferIsEmpty MPU_xStreamBufferIsEmpty - #define xStreamBufferReset MPU_xStreamBufferReset #define xStreamBufferSpacesAvailable MPU_xStreamBufferSpacesAvailable #define xStreamBufferBytesAvailable MPU_xStreamBufferBytesAvailable #define xStreamBufferSetTriggerLevel MPU_xStreamBufferSetTriggerLevel - #define xStreamBufferGenericCreate MPU_xStreamBufferGenericCreate - #define xStreamBufferGenericCreateStatic MPU_xStreamBufferGenericCreateStatic + #define xStreamBufferNextMessageLengthBytes MPU_xStreamBufferNextMessageLengthBytes +/* Privileged only wrappers for Stream Buffer APIs. These are needed so that + * the application can use opaque handles maintained in mpu_wrappers.c + * with all the APIs. */ + + #define xStreamBufferGenericCreate MPU_xStreamBufferGenericCreate + #define xStreamBufferGenericCreateStatic MPU_xStreamBufferGenericCreateStatic + #define vStreamBufferDelete MPU_vStreamBufferDelete + #define xStreamBufferReset MPU_xStreamBufferReset + + #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) + #define xStreamBufferGetStaticBuffers MPU_xStreamBufferGetStaticBuffers + #define xStreamBufferSendFromISR MPU_xStreamBufferSendFromISR + #define xStreamBufferReceiveFromISR MPU_xStreamBufferReceiveFromISR + #define xStreamBufferSendCompletedFromISR MPU_xStreamBufferSendCompletedFromISR + #define xStreamBufferReceiveCompletedFromISR MPU_xStreamBufferReceiveCompletedFromISR + #endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */ /* Remove the privileged function macro, but keep the PRIVILEGED_DATA * macro so applications can place data in privileged access sections @@ -163,6 +240,35 @@ #define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) ) #define FREERTOS_SYSTEM_CALL + + #if ( ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) ) + + #define vGrantAccessToTask( xTask, xTaskToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xTaskToGrantAccess ) ) + #define vRevokeAccessToTask( xTask, xTaskToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xTaskToRevokeAccess ) ) + + #define vGrantAccessToSemaphore( xTask, xSemaphoreToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xSemaphoreToGrantAccess ) ) + #define vRevokeAccessToSemaphore( xTask, xSemaphoreToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xSemaphoreToRevokeAccess ) ) + + #define vGrantAccessToQueue( xTask, xQueueToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xQueueToGrantAccess ) ) + #define vRevokeAccessToQueue( xTask, xQueueToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xQueueToRevokeAccess ) ) + + #define vGrantAccessToQueueSet( xTask, xQueueSetToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xQueueSetToGrantAccess ) ) + #define vRevokeAccessToQueueSet( xTask, xQueueSetToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xQueueSetToRevokeAccess ) ) + + #define vGrantAccessToEventGroup( xTask, xEventGroupToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xEventGroupToGrantAccess ) ) + #define vRevokeAccessToEventGroup( xTask, xEventGroupToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xEventGroupToRevokeAccess ) ) + + #define vGrantAccessToStreamBuffer( xTask, xStreamBufferToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xStreamBufferToGrantAccess ) ) + #define vRevokeAccessToStreamBuffer( xTask, xStreamBufferToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xStreamBufferToRevokeAccess ) ) + + #define vGrantAccessToMessageBuffer( xTask, xMessageBufferToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xMessageBufferToGrantAccess ) ) + #define vRevokeAccessToMessageBuffer( xTask, xMessageBufferToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xMessageBufferToRevokeAccess ) ) + + #define vGrantAccessToTimer( xTask, xTimerToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xTimerToGrantAccess ) ) + #define vRevokeAccessToTimer( xTask, xTimerToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xTimerToRevokeAccess ) ) + + #endif /* #if ( ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) ) */ + #else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ /* Ensure API functions go in the privileged execution section. */ @@ -177,7 +283,6 @@ #define PRIVILEGED_FUNCTION #define PRIVILEGED_DATA #define FREERTOS_SYSTEM_CALL - #define portUSING_MPU_WRAPPERS 0 #endif /* portUSING_MPU_WRAPPERS */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/newlib-freertos.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/newlib-freertos.h new file mode 100644 index 0000000000..20e234d06d --- /dev/null +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/newlib-freertos.h @@ -0,0 +1,66 @@ +/* + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef INC_NEWLIB_FREERTOS_H +#define INC_NEWLIB_FREERTOS_H + +/* Note Newlib support has been included by popular demand, but is not + * used by the FreeRTOS maintainers themselves. FreeRTOS is not + * responsible for resulting newlib operation. User must be familiar with + * newlib and must provide system-wide implementations of the necessary + * stubs. Be warned that (at the time of writing) the current newlib design + * implements a system-wide malloc() that must be provided with locks. + * + * See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html + * for additional information. */ + +#include + +#define configUSE_C_RUNTIME_TLS_SUPPORT 1 + +#ifndef configTLS_BLOCK_TYPE + #define configTLS_BLOCK_TYPE struct _reent +#endif + +#ifndef configINIT_TLS_BLOCK + #define configINIT_TLS_BLOCK( xTLSBlock, pxTopOfStack ) _REENT_INIT_PTR( &( xTLSBlock ) ) +#endif + +#ifndef configSET_TLS_BLOCK + #define configSET_TLS_BLOCK( xTLSBlock ) ( _impure_ptr = &( xTLSBlock ) ) +#endif + +#ifndef configDEINIT_TLS_BLOCK + #define configDEINIT_TLS_BLOCK( xTLSBlock ) _reclaim_reent( &( xTLSBlock ) ) +#endif + +#endif /* INC_NEWLIB_FREERTOS_H */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/picolibc-freertos.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/picolibc-freertos.h new file mode 100644 index 0000000000..b61a90deef --- /dev/null +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/picolibc-freertos.h @@ -0,0 +1,95 @@ +/* + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef INC_PICOLIBC_FREERTOS_H +#define INC_PICOLIBC_FREERTOS_H + +/* Use picolibc TLS support to allocate space for __thread variables, + * initialize them at thread creation and set the TLS context at + * thread switch time. + * + * See the picolibc TLS docs: + * https://github.com/picolibc/picolibc/blob/main/doc/tls.md + * for additional information. */ + +#include + +#define configUSE_C_RUNTIME_TLS_SUPPORT 1 + +#define configTLS_BLOCK_TYPE void * + +#define picolibcTLS_SIZE ( ( portPOINTER_SIZE_TYPE ) _tls_size() ) +#define picolibcSTACK_ALIGNMENT_MASK ( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) + +#if __PICOLIBC_MAJOR__ > 1 || __PICOLIBC_MINOR__ >= 8 + +/* Picolibc 1.8 and newer have explicit alignment values provided + * by the _tls_align() inline */ + #define picolibcTLS_ALIGNMENT_MASK ( ( portPOINTER_SIZE_TYPE ) ( _tls_align() - 1 ) ) +#else + +/* For older Picolibc versions, use the general port alignment value */ + #define picolibcTLS_ALIGNMENT_MASK ( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) +#endif + +/* Allocate thread local storage block off the end of the + * stack. The picolibcTLS_SIZE macro returns the size (in + * bytes) of the total TLS area used by the application. + * Calculate the top of stack address. */ +#if ( portSTACK_GROWTH < 0 ) + + #define configINIT_TLS_BLOCK( xTLSBlock, pxTopOfStack ) \ + do { \ + xTLSBlock = ( void * ) ( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) - \ + picolibcTLS_SIZE ) & \ + ~picolibcTLS_ALIGNMENT_MASK ); \ + pxTopOfStack = ( StackType_t * ) ( ( ( ( portPOINTER_SIZE_TYPE ) xTLSBlock ) - 1 ) & \ + ~picolibcSTACK_ALIGNMENT_MASK ); \ + _init_tls( xTLSBlock ); \ + } while( 0 ) +#else /* portSTACK_GROWTH */ + #define configINIT_TLS_BLOCK( xTLSBlock, pxTopOfStack ) \ + do { \ + xTLSBlock = ( void * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack + \ + picolibcTLS_ALIGNMENT_MASK ) & ~picolibcTLS_ALIGNMENT_MASK ); \ + pxTopOfStack = ( StackType_t * ) ( ( ( ( ( portPOINTER_SIZE_TYPE ) xTLSBlock ) + \ + picolibcTLS_SIZE ) + picolibcSTACK_ALIGNMENT_MASK ) & \ + ~picolibcSTACK_ALIGNMENT_MASK ); \ + _init_tls( xTLSBlock ); \ + } while( 0 ) +#endif /* portSTACK_GROWTH */ + +#define configSET_TLS_BLOCK( xTLSBlock ) _set_tls( xTLSBlock ) + +#define configDEINIT_TLS_BLOCK( xTLSBlock ) + +#endif /* INC_PICOLIBC_FREERTOS_H */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/portable.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/portable.h index 6a3564547d..87f1234627 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/portable.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/portable.h @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -53,30 +59,22 @@ #if portBYTE_ALIGNMENT == 32 #define portBYTE_ALIGNMENT_MASK ( 0x001f ) -#endif - -#if portBYTE_ALIGNMENT == 16 +#elif portBYTE_ALIGNMENT == 16 #define portBYTE_ALIGNMENT_MASK ( 0x000f ) -#endif - -#if portBYTE_ALIGNMENT == 8 +#elif portBYTE_ALIGNMENT == 8 #define portBYTE_ALIGNMENT_MASK ( 0x0007 ) -#endif - -#if portBYTE_ALIGNMENT == 4 +#elif portBYTE_ALIGNMENT == 4 #define portBYTE_ALIGNMENT_MASK ( 0x0003 ) -#endif - -#if portBYTE_ALIGNMENT == 2 +#elif portBYTE_ALIGNMENT == 2 #define portBYTE_ALIGNMENT_MASK ( 0x0001 ) -#endif - -#if portBYTE_ALIGNMENT == 1 +#elif portBYTE_ALIGNMENT == 1 #define portBYTE_ALIGNMENT_MASK ( 0x0000 ) -#endif - -#ifndef portBYTE_ALIGNMENT_MASK +#else /* if portBYTE_ALIGNMENT == 32 */ #error "Invalid portBYTE_ALIGNMENT definition" +#endif /* if portBYTE_ALIGNMENT == 32 */ + +#ifndef portUSING_MPU_WRAPPERS + #define portUSING_MPU_WRAPPERS 0 #endif #ifndef portNUM_CONFIGURABLE_REGIONS @@ -91,6 +89,11 @@ #define portARCH_NAME NULL #endif +#ifndef configSTACK_ALLOCATION_FROM_SEPARATE_HEAP + /* Defaults to 0 for backward compatibility. */ + #define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 +#endif + /* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { @@ -111,13 +114,15 @@ StackType_t * pxEndOfStack, TaskFunction_t pxCode, void * pvParameters, - BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION; + BaseType_t xRunPrivileged, + xMPU_SETTINGS * xMPUSettings ) PRIVILEGED_FUNCTION; #else StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void * pvParameters, - BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION; - #endif + BaseType_t xRunPrivileged, + xMPU_SETTINGS * xMPUSettings ) PRIVILEGED_FUNCTION; + #endif /* if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) */ #else /* if ( portUSING_MPU_WRAPPERS == 1 ) */ #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -142,13 +147,13 @@ typedef struct HeapRegion /* Used to pass information about the heap out of vPortGetHeapStats(). */ typedef struct xHeapStats { - size_t xAvailableHeapSpaceInBytes; /* The total heap size currently available - this is the sum of all the free blocks, not the largest block that can be allocated. */ - size_t xSizeOfLargestFreeBlockInBytes; /* The maximum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */ - size_t xSizeOfSmallestFreeBlockInBytes; /* The minimum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */ - size_t xNumberOfFreeBlocks; /* The number of free memory blocks within the heap at the time vPortGetHeapStats() is called. */ - size_t xMinimumEverFreeBytesRemaining; /* The minimum amount of total free memory (sum of all free blocks) there has been in the heap since the system booted. */ - size_t xNumberOfSuccessfulAllocations; /* The number of calls to pvPortMalloc() that have returned a valid memory block. */ - size_t xNumberOfSuccessfulFrees; /* The number of calls to vPortFree() that has successfully freed a block of memory. */ + size_t xAvailableHeapSpaceInBytes; /* The total heap size currently available - this is the sum of all the free blocks, not the largest block that can be allocated. */ + size_t xSizeOfLargestFreeBlockInBytes; /* The maximum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */ + size_t xSizeOfSmallestFreeBlockInBytes; /* The minimum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */ + size_t xNumberOfFreeBlocks; /* The number of free memory blocks within the heap at the time vPortGetHeapStats() is called. */ + size_t xMinimumEverFreeBytesRemaining; /* The minimum amount of total free memory (sum of all free blocks) there has been in the heap since the system booted. */ + size_t xNumberOfSuccessfulAllocations; /* The number of calls to pvPortMalloc() that have returned a valid memory block. */ + size_t xNumberOfSuccessfulFrees; /* The number of calls to vPortFree() that has successfully freed a block of memory. */ } HeapStats_t; /* @@ -174,17 +179,32 @@ void vPortGetHeapStats( HeapStats_t * pxHeapStats ); * Map to the memory management routines required for the port. */ void * pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION; +void * pvPortCalloc( size_t xNum, + size_t xSize ) PRIVILEGED_FUNCTION; void vPortFree( void * pv ) PRIVILEGED_FUNCTION; void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION; size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION; size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION; -#if( configSTACK_ALLOCATION_FROM_SEPARATE_HEAP == 1 ) - void *pvPortMallocStack( size_t xSize ) PRIVILEGED_FUNCTION; - void vPortFreeStack( void *pv ) PRIVILEGED_FUNCTION; +#if ( configSTACK_ALLOCATION_FROM_SEPARATE_HEAP == 1 ) + void * pvPortMallocStack( size_t xSize ) PRIVILEGED_FUNCTION; + void vPortFreeStack( void * pv ) PRIVILEGED_FUNCTION; #else - #define pvPortMallocStack pvPortMalloc - #define vPortFreeStack vPortFree + #define pvPortMallocStack pvPortMalloc + #define vPortFreeStack vPortFree +#endif + +#if ( configUSE_MALLOC_FAILED_HOOK == 1 ) + +/** + * task.h + * @code{c} + * void vApplicationMallocFailedHook( void ) + * @endcode + * + * This hook function is called when allocation failed. + */ + void vApplicationMallocFailedHook( void ); #endif /* @@ -215,6 +235,37 @@ void vPortEndScheduler( void ) PRIVILEGED_FUNCTION; uint32_t ulStackDepth ) PRIVILEGED_FUNCTION; #endif +/** + * @brief Checks if the calling task is authorized to access the given buffer. + * + * @param pvBuffer The buffer which the calling task wants to access. + * @param ulBufferLength The length of the pvBuffer. + * @param ulAccessRequested The permissions that the calling task wants. + * + * @return pdTRUE if the calling task is authorized to access the buffer, + * pdFALSE otherwise. + */ +#if ( portUSING_MPU_WRAPPERS == 1 ) + BaseType_t xPortIsAuthorizedToAccessBuffer( const void * pvBuffer, + uint32_t ulBufferLength, + uint32_t ulAccessRequested ) PRIVILEGED_FUNCTION; +#endif + +/** + * @brief Checks if the calling task is authorized to access the given kernel object. + * + * @param lInternalIndexOfKernelObject The index of the kernel object in the kernel + * object handle pool. + * + * @return pdTRUE if the calling task is authorized to access the kernel object, + * pdFALSE otherwise. + */ +#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) + + BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject ) PRIVILEGED_FUNCTION; + +#endif + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/projdefs.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/projdefs.h index 2f443e6402..24a257e1c8 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/projdefs.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/projdefs.h @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -31,17 +37,28 @@ * Defines the prototype to which task functions must conform. Defined in this * file to ensure the type is known before portable.h is included. */ -typedef void (* TaskFunction_t)( void * ); +typedef void (* TaskFunction_t)( void * arg ); /* Converts a time in milliseconds to a time in ticks. This macro can be * overridden by a macro of the same name defined in FreeRTOSConfig.h in case the * definition here is not suitable for your application. */ #ifndef pdMS_TO_TICKS - #define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000U ) ) + #define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( uint64_t ) ( xTimeInMs ) * ( uint64_t ) configTICK_RATE_HZ ) / ( uint64_t ) 1000U ) ) +#endif + +/* Converts a time in ticks to a time in milliseconds. This macro can be + * overridden by a macro of the same name defined in FreeRTOSConfig.h in case the + * definition here is not suitable for your application. */ +#ifndef pdTICKS_TO_MS + #define pdTICKS_TO_MS( xTimeInTicks ) ( ( TickType_t ) ( ( ( uint64_t ) ( xTimeInTicks ) * ( uint64_t ) 1000U ) / ( uint64_t ) configTICK_RATE_HZ ) ) #endif #define pdFALSE ( ( BaseType_t ) 0 ) #define pdTRUE ( ( BaseType_t ) 1 ) +#define pdFALSE_SIGNED ( ( BaseType_t ) 0 ) +#define pdTRUE_SIGNED ( ( BaseType_t ) 1 ) +#define pdFALSE_UNSIGNED ( ( UBaseType_t ) 0 ) +#define pdTRUE_UNSIGNED ( ( UBaseType_t ) 1 ) #define pdPASS ( pdTRUE ) #define pdFAIL ( pdFALSE ) @@ -58,10 +75,14 @@ typedef void (* TaskFunction_t)( void * ); #define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0 #endif -#if ( configUSE_16_BIT_TICKS == 1 ) +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) #define pdINTEGRITY_CHECK_VALUE 0x5a5a -#else +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) #define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_64_BITS ) + #define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5a5a5a5a5aULL +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. #endif /* The following errno values are used by FreeRTOS+ components, not FreeRTOS @@ -94,6 +115,7 @@ typedef void (* TaskFunction_t)( void * ); #define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */ #define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */ #define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define pdFREERTOS_ERRNO_EAFNOSUPPORT 97 /* Address family not supported by protocol */ #define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */ #define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */ #define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */ @@ -117,16 +139,4 @@ typedef void (* TaskFunction_t)( void * ); #define pdBIG_ENDIAN pdFREERTOS_BIG_ENDIAN -/* ------------------------------------------------ IDF Compatibility -------------------------------------------------- - * - * ------------------------------------------------------------------------------------------------------------------ */ - -#ifdef ESP_PLATFORM - -#ifndef pdTICKS_TO_MS - #define pdTICKS_TO_MS( xTicks ) ( ( TickType_t ) ( ( uint64_t ) ( xTicks ) * 1000 / configTICK_RATE_HZ ) ) -#endif - -#endif // ESP_PLATFORM - #endif /* PROJDEFS_H */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/queue.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/queue.h index 446f73493f..79d9e9e6ba 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/queue.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/queue.h @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -77,12 +83,12 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; /** * queue. h - *
+ * @code{c}
  * QueueHandle_t xQueueCreate(
  *                            UBaseType_t uxQueueLength,
  *                            UBaseType_t uxItemSize
  *                        );
- * 
+ * @endcode * * Creates a new queue instance, and returns a handle by which the new queue * can be referenced. @@ -111,7 +117,7 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * returned. * * Example usage: - *
+ * @code{c}
  * struct AMessage
  * {
  *  char ucMessageID;
@@ -139,7 +145,7 @@ typedef struct QueueDefinition   * QueueSetMemberHandle_t;
  *
  *  // ... Rest of task code.
  * }
- * 
+ * @endcode * \defgroup xQueueCreate xQueueCreate * \ingroup QueueManagement */ @@ -149,14 +155,14 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; /** * queue. h - *
+ * @code{c}
  * QueueHandle_t xQueueCreateStatic(
  *                            UBaseType_t uxQueueLength,
  *                            UBaseType_t uxItemSize,
- *                            uint8_t *pucQueueStorageBuffer,
+ *                            uint8_t *pucQueueStorage,
  *                            StaticQueue_t *pxQueueBuffer
  *                        );
- * 
+ * @endcode * * Creates a new queue instance, and returns a handle by which the new queue * can be referenced. @@ -180,11 +186,11 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * that will be copied for each posted item. Each item on the queue must be * the same size. * - * @param pucQueueStorageBuffer If uxItemSize is not zero then - * pucQueueStorageBuffer must point to a uint8_t array that is at least large + * @param pucQueueStorage If uxItemSize is not zero then + * pucQueueStorage must point to a uint8_t array that is at least large * enough to hold the maximum number of items that can be in the queue at any * one time - which is ( uxQueueLength * uxItemsSize ) bytes. If uxItemSize is - * zero then pucQueueStorageBuffer can be NULL. + * zero then pucQueueStorage can be NULL. * * @param pxQueueBuffer Must point to a variable of type StaticQueue_t, which * will be used to hold the queue's data structure. @@ -193,7 +199,7 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * returned. If pxQueueBuffer is NULL then NULL is returned. * * Example usage: - *
+ * @code{c}
  * struct AMessage
  * {
  *  char ucMessageID;
@@ -212,7 +218,7 @@ typedef struct QueueDefinition   * QueueSetMemberHandle_t;
  *
  * void vATask( void *pvParameters )
  * {
- * QueueHandle_t xQueue1;
+ *  QueueHandle_t xQueue1;
  *
  *  // Create a queue capable of containing 10 uint32_t values.
  *  xQueue1 = xQueueCreate( QUEUE_LENGTH, // The number of items the queue can hold.
@@ -225,7 +231,7 @@ typedef struct QueueDefinition   * QueueSetMemberHandle_t;
  *
  *  // ... Rest of task code.
  * }
- * 
+ * @endcode * \defgroup xQueueCreateStatic xQueueCreateStatic * \ingroup QueueManagement */ @@ -264,13 +270,13 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; /** * queue. h - *
- * BaseType_t xQueueSendToToFront(
+ * @code{c}
+ * BaseType_t xQueueSendToFront(
  *                                 QueueHandle_t    xQueue,
  *                                 const void       *pvItemToQueue,
  *                                 TickType_t       xTicksToWait
  *                             );
- * 
+ * @endcode * * Post an item to the front of a queue. The item is queued by copy, not by * reference. This function must not be called from an interrupt service @@ -293,7 +299,7 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. * * Example usage: - *
+ * @code{c}
  * struct AMessage
  * {
  *  char ucMessageID;
@@ -336,7 +342,7 @@ typedef struct QueueDefinition   * QueueSetMemberHandle_t;
  *
  *  // ... Rest of task code.
  * }
- * 
+ * @endcode * \defgroup xQueueSend xQueueSend * \ingroup QueueManagement */ @@ -345,13 +351,13 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; /** * queue. h - *
+ * @code{c}
  * BaseType_t xQueueSendToBack(
  *                                 QueueHandle_t    xQueue,
  *                                 const void       *pvItemToQueue,
  *                                 TickType_t       xTicksToWait
  *                             );
- * 
+ * @endcode * * This is a macro that calls xQueueGenericSend(). * @@ -376,7 +382,7 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. * * Example usage: - *
+ * @code{c}
  * struct AMessage
  * {
  *  char ucMessageID;
@@ -419,7 +425,7 @@ typedef struct QueueDefinition   * QueueSetMemberHandle_t;
  *
  *  // ... Rest of task code.
  * }
- * 
+ * @endcode * \defgroup xQueueSend xQueueSend * \ingroup QueueManagement */ @@ -428,13 +434,13 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; /** * queue. h - *
+ * @code{c}
  * BaseType_t xQueueSend(
  *                            QueueHandle_t xQueue,
  *                            const void * pvItemToQueue,
  *                            TickType_t xTicksToWait
  *                       );
- * 
+ * @endcode * * This is a macro that calls xQueueGenericSend(). It is included for * backward compatibility with versions of FreeRTOS.org that did not @@ -461,7 +467,7 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. * * Example usage: - *
+ * @code{c}
  * struct AMessage
  * {
  *  char ucMessageID;
@@ -504,7 +510,7 @@ typedef struct QueueDefinition   * QueueSetMemberHandle_t;
  *
  *  // ... Rest of task code.
  * }
- * 
+ * @endcode * \defgroup xQueueSend xQueueSend * \ingroup QueueManagement */ @@ -513,12 +519,12 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; /** * queue. h - *
+ * @code{c}
  * BaseType_t xQueueOverwrite(
  *                            QueueHandle_t xQueue,
  *                            const void * pvItemToQueue
  *                       );
- * 
+ * @endcode * * Only for use with queues that have a length of one - so the queue is either * empty or full. @@ -542,7 +548,7 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * to the queue even when the queue is already full. * * Example usage: - *
+ * @code{c}
  *
  * void vFunction( void *pvParameters )
  * {
@@ -588,7 +594,7 @@ typedef struct QueueDefinition   * QueueSetMemberHandle_t;
  *
  *  // ...
  * }
- * 
+ * @endcode * \defgroup xQueueOverwrite xQueueOverwrite * \ingroup QueueManagement */ @@ -598,14 +604,14 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; /** * queue. h - *
+ * @code{c}
  * BaseType_t xQueueGenericSend(
  *                                  QueueHandle_t xQueue,
  *                                  const void * pvItemToQueue,
  *                                  TickType_t xTicksToWait
  *                                  BaseType_t xCopyPosition
  *                              );
- * 
+ * @endcode * * It is preferred that the macros xQueueSend(), xQueueSendToFront() and * xQueueSendToBack() are used in place of calling this function directly. @@ -634,7 +640,7 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. * * Example usage: - *
+ * @code{c}
  * struct AMessage
  * {
  *  char ucMessageID;
@@ -677,7 +683,7 @@ typedef struct QueueDefinition   * QueueSetMemberHandle_t;
  *
  *  // ... Rest of task code.
  * }
- * 
+ * @endcode * \defgroup xQueueSend xQueueSend * \ingroup QueueManagement */ @@ -688,13 +694,13 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, /** * queue. h - *
+ * @code{c}
  * BaseType_t xQueuePeek(
  *                           QueueHandle_t xQueue,
  *                           void * const pvBuffer,
  *                           TickType_t xTicksToWait
  *                       );
- * 
+ * @endcode * * Receive an item from a queue without removing the item from the queue. * The item is received by copy so a buffer of adequate size must be @@ -725,7 +731,7 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, * otherwise pdFALSE. * * Example usage: - *
+ * @code{c}
  * struct AMessage
  * {
  *  char ucMessageID;
@@ -775,7 +781,7 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
  *
  *  // ... Rest of task code.
  * }
- * 
+ * @endcode * \defgroup xQueuePeek xQueuePeek * \ingroup QueueManagement */ @@ -785,12 +791,12 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, /** * queue. h - *
+ * @code{c}
  * BaseType_t xQueuePeekFromISR(
  *                                  QueueHandle_t xQueue,
  *                                  void *pvBuffer,
  *                              );
- * 
+ * @endcode * * A version of xQueuePeek() that can be called from an interrupt service * routine (ISR). @@ -820,13 +826,13 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, /** * queue. h - *
+ * @code{c}
  * BaseType_t xQueueReceive(
  *                               QueueHandle_t xQueue,
  *                               void *pvBuffer,
  *                               TickType_t xTicksToWait
  *                          );
- * 
+ * @endcode * * Receive an item from a queue. The item is received by copy so a buffer of * adequate size must be provided. The number of bytes copied into the buffer @@ -854,7 +860,7 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, * otherwise pdFALSE. * * Example usage: - *
+ * @code{c}
  * struct AMessage
  * {
  *  char ucMessageID;
@@ -904,7 +910,7 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue,
  *
  *  // ... Rest of task code.
  * }
- * 
+ * @endcode * \defgroup xQueueReceive xQueueReceive * \ingroup QueueManagement */ @@ -914,9 +920,9 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, /** * queue. h - *
+ * @code{c}
  * UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue );
- * 
+ * @endcode * * Return the number of messages stored in a queue. * @@ -931,9 +937,9 @@ UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) PRIVILEGED_FUNC /** * queue. h - *
+ * @code{c}
  * UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );
- * 
+ * @endcode * * Return the number of free spaces available in a queue. This is equal to the * number of items that can be sent to the queue before the queue becomes full @@ -950,9 +956,9 @@ UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) PRIVILEGED_FUNC /** * queue. h - *
+ * @code{c}
  * void vQueueDelete( QueueHandle_t xQueue );
- * 
+ * @endcode * * Delete a queue - freeing all the memory allocated for storing of items * placed on the queue. @@ -966,13 +972,13 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** * queue. h - *
+ * @code{c}
  * BaseType_t xQueueSendToFrontFromISR(
  *                                       QueueHandle_t xQueue,
  *                                       const void *pvItemToQueue,
  *                                       BaseType_t *pxHigherPriorityTaskWoken
  *                                    );
- * 
+ * @endcode * * This is a macro that calls xQueueGenericSendFromISR(). * @@ -993,7 +999,7 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; * @param pxHigherPriorityTaskWoken xQueueSendToFrontFromISR() will set * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task * to unblock, and the unblocked task has a priority higher than the currently - * running task. If xQueueSendToFromFromISR() sets this value to pdTRUE then + * running task. If xQueueSendToFrontFromISR() sets this value to pdTRUE then * a context switch should be requested before the interrupt is exited. * * @return pdTRUE if the data was successfully sent to the queue, otherwise @@ -1001,11 +1007,11 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; * * Example usage for buffered IO (where the ISR can obtain more than one value * per call): - *
+ * @code{c}
  * void vBufferISR( void )
  * {
  * char cIn;
- * BaseType_t xHigherPrioritTaskWoken;
+ * BaseType_t xHigherPriorityTaskWoken;
  *
  *  // We have not woken a task at the start of the ISR.
  *  xHigherPriorityTaskWoken = pdFALSE;
@@ -1027,7 +1033,7 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
  *      taskYIELD ();
  *  }
  * }
- * 
+ * @endcode * * \defgroup xQueueSendFromISR xQueueSendFromISR * \ingroup QueueManagement @@ -1038,13 +1044,13 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** * queue. h - *
+ * @code{c}
  * BaseType_t xQueueSendToBackFromISR(
  *                                       QueueHandle_t xQueue,
  *                                       const void *pvItemToQueue,
  *                                       BaseType_t *pxHigherPriorityTaskWoken
  *                                    );
- * 
+ * @endcode * * This is a macro that calls xQueueGenericSendFromISR(). * @@ -1073,7 +1079,7 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; * * Example usage for buffered IO (where the ISR can obtain more than one value * per call): - *
+ * @code{c}
  * void vBufferISR( void )
  * {
  * char cIn;
@@ -1099,7 +1105,7 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
  *      taskYIELD ();
  *  }
  * }
- * 
+ * @endcode * * \defgroup xQueueSendFromISR xQueueSendFromISR * \ingroup QueueManagement @@ -1109,13 +1115,13 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** * queue. h - *
+ * @code{c}
  * BaseType_t xQueueOverwriteFromISR(
  *                            QueueHandle_t xQueue,
  *                            const void * pvItemToQueue,
  *                            BaseType_t *pxHigherPriorityTaskWoken
  *                       );
- * 
+ * @endcode * * A version of xQueueOverwrite() that can be used in an interrupt service * routine (ISR). @@ -1146,7 +1152,7 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; * the queue is already full. * * Example usage: - *
+ * @code{c}
  *
  * QueueHandle_t xQueue;
  *
@@ -1183,12 +1189,15 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
  *  {
  *      // Writing to the queue caused a task to unblock and the unblocked task
  *      // has a priority higher than or equal to the priority of the currently
- *      // executing task (the task this interrupt interrupted).  Perform a context
+ *      // executing task (the task this interrupt interrupted). Perform a context
  *      // switch so this interrupt returns directly to the unblocked task.
- *      portYIELD_FROM_ISR(); // or portEND_SWITCHING_ISR() depending on the port.
+ *      // The macro used is port specific and will be either
+ *      // portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to the documentation
+ *      // page for the port being used.
+ *      portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
  *  }
  * }
- * 
+ * @endcode * \defgroup xQueueOverwriteFromISR xQueueOverwriteFromISR * \ingroup QueueManagement */ @@ -1197,13 +1206,13 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** * queue. h - *
+ * @code{c}
  * BaseType_t xQueueSendFromISR(
  *                                   QueueHandle_t xQueue,
  *                                   const void *pvItemToQueue,
  *                                   BaseType_t *pxHigherPriorityTaskWoken
  *                              );
- * 
+ * @endcode * * This is a macro that calls xQueueGenericSendFromISR(). It is included * for backward compatibility with versions of FreeRTOS.org that did not @@ -1235,7 +1244,7 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; * * Example usage for buffered IO (where the ISR can obtain more than one value * per call): - *
+ * @code{c}
  * void vBufferISR( void )
  * {
  * char cIn;
@@ -1258,11 +1267,14 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
  *  // Now the buffer is empty we can switch context if necessary.
  *  if( xHigherPriorityTaskWoken )
  *  {
- *      // Actual macro used here is port specific.
- *      portYIELD_FROM_ISR ();
+ *       // As xHigherPriorityTaskWoken is now set to pdTRUE then a context
+ *       // switch should be requested. The macro used is port specific and
+ *       // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
+ *       // refer to the documentation page for the port being used.
+ *       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
  *  }
  * }
- * 
+ * @endcode * * \defgroup xQueueSendFromISR xQueueSendFromISR * \ingroup QueueManagement @@ -1272,14 +1284,14 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** * queue. h - *
+ * @code{c}
  * BaseType_t xQueueGenericSendFromISR(
  *                                         QueueHandle_t    xQueue,
  *                                         const    void    *pvItemToQueue,
  *                                         BaseType_t  *pxHigherPriorityTaskWoken,
  *                                         BaseType_t  xCopyPosition
  *                                     );
- * 
+ * @endcode * * It is preferred that the macros xQueueSendFromISR(), * xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place @@ -1315,7 +1327,7 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; * * Example usage for buffered IO (where the ISR can obtain more than one value * per call): - *
+ * @code{c}
  * void vBufferISR( void )
  * {
  * char cIn;
@@ -1335,14 +1347,17 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
  *
  *  } while( portINPUT_BYTE( BUFFER_COUNT ) );
  *
- *  // Now the buffer is empty we can switch context if necessary.  Note that the
- *  // name of the yield function required is port specific.
+ *  // Now the buffer is empty we can switch context if necessary.
  *  if( xHigherPriorityTaskWokenByPost )
  *  {
- *      portYIELD_FROM_ISR();
+ *       // As xHigherPriorityTaskWokenByPost is now set to pdTRUE then a context
+ *       // switch should be requested. The macro used is port specific and
+ *       // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
+ *       // refer to the documentation page for the port being used.
+ *       portYIELD_FROM_ISR( xHigherPriorityTaskWokenByPost );
  *  }
  * }
- * 
+ * @endcode * * \defgroup xQueueSendFromISR xQueueSendFromISR * \ingroup QueueManagement @@ -1356,13 +1371,13 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, /** * queue. h - *
+ * @code{c}
  * BaseType_t xQueueReceiveFromISR(
  *                                     QueueHandle_t    xQueue,
  *                                     void             *pvBuffer,
  *                                     BaseType_t       *pxTaskWoken
  *                                 );
- * 
+ * @endcode * * Receive an item from a queue. It is safe to use this function from within an * interrupt service routine. @@ -1373,16 +1388,16 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, * @param pvBuffer Pointer to the buffer into which the received item will * be copied. * - * @param pxTaskWoken A task may be blocked waiting for space to become - * available on the queue. If xQueueReceiveFromISR causes such a task to - * unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will + * @param pxHigherPriorityTaskWoken A task may be blocked waiting for space to + * become available on the queue. If xQueueReceiveFromISR causes such a task + * to unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will * remain unchanged. * * @return pdTRUE if an item was successfully received from the queue, * otherwise pdFALSE. * * Example usage: - *
+ * @code{c}
  *
  * QueueHandle_t xQueue;
  *
@@ -1427,17 +1442,17 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue,
  *      vOutputCharacter( cRxedChar );
  *
  *      // If removing the character from the queue woke the task that was
- *      // posting onto the queue cTaskWokenByReceive will have been set to
+ *      // posting onto the queue xTaskWokenByReceive will have been set to
  *      // pdTRUE.  No matter how many times this loop iterates only one
  *      // task will be woken.
  *  }
  *
- *  if( cTaskWokenByPost != ( char ) pdFALSE;
+ *  if( xTaskWokenByReceive != ( char ) pdFALSE;
  *  {
  *      taskYIELD ();
  *  }
  * }
- * 
+ * @endcode * \defgroup xQueueReceiveFromISR xQueueReceiveFromISR * \ingroup QueueManagement */ @@ -1447,12 +1462,14 @@ BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, /* * Utilities to query queues that are safe to use from an ISR. These utilities - * should be used only from witin an ISR, or within a critical section. + * should be used only from within an ISR, or within a critical section. */ BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +#if ( configUSE_CO_ROUTINES == 1 ) + /* * The functions defined above are for passing data to and from tasks. The * functions below are the equivalents for passing data to and from @@ -1462,18 +1479,20 @@ UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) PRIVILEG * should not be called directly from application code. Instead use the macro * wrappers defined within croutine.h. */ -BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, - const void * pvItemToQueue, - BaseType_t xCoRoutinePreviouslyWoken ); -BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, - void * pvBuffer, - BaseType_t * pxTaskWoken ); -BaseType_t xQueueCRSend( QueueHandle_t xQueue, - const void * pvItemToQueue, - TickType_t xTicksToWait ); -BaseType_t xQueueCRReceive( QueueHandle_t xQueue, - void * pvBuffer, - TickType_t xTicksToWait ); + BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, + const void * pvItemToQueue, + BaseType_t xCoRoutinePreviouslyWoken ); + BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, + void * pvBuffer, + BaseType_t * pxTaskWoken ); + BaseType_t xQueueCRSend( QueueHandle_t xQueue, + const void * pvItemToQueue, + TickType_t xTicksToWait ); + BaseType_t xQueueCRReceive( QueueHandle_t xQueue, + void * pvBuffer, + TickType_t xTicksToWait ); + +#endif /* if ( configUSE_CO_ROUTINES == 1 ) */ /* * For internal use only. Use xSemaphoreCreateMutex(), @@ -1481,17 +1500,30 @@ BaseType_t xQueueCRReceive( QueueHandle_t xQueue, * these functions directly. */ QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; -QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, - StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION; -QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, - const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION; -QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, - const UBaseType_t uxInitialCount, - StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION; + +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, + StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION; +#endif + +#if ( configUSE_COUNTING_SEMAPHORES == 1 ) + QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, + const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION; +#endif + +#if ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, + const UBaseType_t uxInitialCount, + StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION; +#endif + BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; -TaskHandle_t xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION; -TaskHandle_t xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION; + +#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) + TaskHandle_t xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION; + TaskHandle_t xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION; +#endif /* * For internal use only. Use xSemaphoreTakeMutexRecursive() or @@ -1505,7 +1537,7 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION; * Reset a queue back to its original empty state. The return value is now * obsolete and is always set to pdPASS. */ -#define xQueueReset( xQueue ) xQueueGenericReset( xQueue, pdFALSE ) +#define xQueueReset( xQueue ) xQueueGenericReset( ( xQueue ), pdFALSE ) /* * The registry is provided as a means for kernel aware debuggers to @@ -1517,21 +1549,25 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION; * configQUEUE_REGISTRY_SIZE defines the maximum number of handles the * registry can hold. configQUEUE_REGISTRY_SIZE must be greater than 0 * within FreeRTOSConfig.h for the registry to be available. Its value - * does not effect the number of queues, semaphores and mutexes that can be + * does not affect the number of queues, semaphores and mutexes that can be * created - just the number that the registry can hold. * + * If vQueueAddToRegistry is called more than once with the same xQueue + * parameter, the registry will store the pcQueueName parameter from the + * most recent call to vQueueAddToRegistry. + * * @param xQueue The handle of the queue being added to the registry. This * is the handle returned by a call to xQueueCreate(). Semaphore and mutex * handles can also be passed in here. * - * @param pcName The name to be associated with the handle. This is the + * @param pcQueueName The name to be associated with the handle. This is the * name that the kernel aware debugger will display. The queue registry only * stores a pointer to the string - so the string must be persistent (global or * preferably in ROM/Flash), not on the stack. */ #if ( configQUEUE_REGISTRY_SIZE > 0 ) void vQueueAddToRegistry( QueueHandle_t xQueue, - const char * pcQueueName ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const char * pcQueueName ) PRIVILEGED_FUNCTION; #endif /* @@ -1560,7 +1596,7 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION; * returned. */ #if ( configQUEUE_REGISTRY_SIZE > 0 ) - const char * pcQueueGetName( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const char * pcQueueGetName( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; #endif /* @@ -1647,7 +1683,9 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION; * @return If the queue set is created successfully then a handle to the created * queue set is returned. Otherwise NULL is returned. */ -QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) PRIVILEGED_FUNCTION; +#if ( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) PRIVILEGED_FUNCTION; +#endif /* * Adds a queue or semaphore to a queue set that was previously created by a @@ -1671,8 +1709,10 @@ QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) PRIVILE * queue set because it is already a member of a different queue set then pdFAIL * is returned. */ -BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, - QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; +#if ( configUSE_QUEUE_SETS == 1 ) + BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, + QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; +#endif /* * Removes a queue or semaphore from a queue set. A queue or semaphore can only @@ -1691,8 +1731,10 @@ BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, * then pdPASS is returned. If the queue was not in the queue set, or the * queue (or semaphore) was not empty, then pdFAIL is returned. */ -BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, - QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; +#if ( configUSE_QUEUE_SETS == 1 ) + BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, + QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; +#endif /* * xQueueSelectFromSet() selects from the members of a queue set a queue or @@ -1728,13 +1770,17 @@ BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, * in the queue set that is available, or NULL if no such queue or semaphore * exists before before the specified block time expires. */ -QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, - const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +#if ( configUSE_QUEUE_SETS == 1 ) + QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, + const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +#endif /* * A version of xQueueSelectFromSet() that can be used from an ISR. */ -QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; +#if ( configUSE_QUEUE_SETS == 1 ) + QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; +#endif /* Not public API functions. */ void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, @@ -1742,11 +1788,22 @@ void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION; BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) PRIVILEGED_FUNCTION; -void vQueueSetQueueNumber( QueueHandle_t xQueue, - UBaseType_t uxQueueNumber ) PRIVILEGED_FUNCTION; -UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; -uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +#if ( configUSE_TRACE_FACILITY == 1 ) + void vQueueSetQueueNumber( QueueHandle_t xQueue, + UBaseType_t uxQueueNumber ) PRIVILEGED_FUNCTION; +#endif + +#if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +#endif + +#if ( configUSE_TRACE_FACILITY == 1 ) + uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +#endif + +UBaseType_t uxQueueGetQueueItemSize( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +UBaseType_t uxQueueGetQueueLength( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /* *INDENT-OFF* */ #ifdef __cplusplus diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/semphr.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/semphr.h index d72bf45b1b..03a1cf6264 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/semphr.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/semphr.h @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -42,9 +48,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * semphr. h - *
+ * @code{c}
  * vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore );
- * 
+ * @endcode * * In many usage scenarios it is faster and more memory efficient to use a * direct to task notification in place of a binary semaphore! @@ -72,7 +78,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * @param xSemaphore Handle to the created semaphore. Should be of type SemaphoreHandle_t. * * Example usage: - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphore = NULL;
  *
  * void vATask( void * pvParameters )
@@ -87,26 +93,26 @@ typedef QueueHandle_t SemaphoreHandle_t;
  *      // The semaphore can now be used.
  *  }
  * }
- * 
+ * @endcode * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary * \ingroup Semaphores */ #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #define vSemaphoreCreateBinary( xSemaphore ) \ - { \ + do { \ ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ if( ( xSemaphore ) != NULL ) \ { \ ( void ) xSemaphoreGive( ( xSemaphore ) ); \ } \ - } + } while( 0 ) #endif /** * semphr. h - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphoreCreateBinary( void );
- * 
+ * @endcode * * Creates a new binary semaphore instance, and returns a handle by which the * new semaphore can be referenced. @@ -142,7 +148,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * hold the semaphore's data structures could not be allocated. * * Example usage: - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphore = NULL;
  *
  * void vATask( void * pvParameters )
@@ -157,7 +163,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
  *      // The semaphore can now be used.
  *  }
  * }
- * 
+ * @endcode * \defgroup xSemaphoreCreateBinary xSemaphoreCreateBinary * \ingroup Semaphores */ @@ -167,9 +173,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * semphr. h - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer );
- * 
+ * @endcode * * Creates a new binary semaphore instance, and returns a handle by which the * new semaphore can be referenced. @@ -202,7 +208,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * returned. If pxSemaphoreBuffer is NULL then NULL is returned. * * Example usage: - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphore = NULL;
  * StaticSemaphore_t xSemaphoreBuffer;
  *
@@ -218,22 +224,22 @@ typedef QueueHandle_t SemaphoreHandle_t;
  *
  *  // Rest of task code goes here.
  * }
- * 
+ * @endcode * \defgroup xSemaphoreCreateBinaryStatic xSemaphoreCreateBinaryStatic * \ingroup Semaphores */ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) - #define xSemaphoreCreateBinaryStatic( pxStaticSemaphore ) xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticSemaphore, queueQUEUE_TYPE_BINARY_SEMAPHORE ) + #define xSemaphoreCreateBinaryStatic( pxStaticSemaphore ) xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, ( pxStaticSemaphore ), queueQUEUE_TYPE_BINARY_SEMAPHORE ) #endif /* configSUPPORT_STATIC_ALLOCATION */ /** * semphr. h - *
+ * @code{c}
  * xSemaphoreTake(
  *                   SemaphoreHandle_t xSemaphore,
  *                   TickType_t xBlockTime
  *               );
- * 
+ * @endcode * * Macro to obtain a semaphore. The semaphore must have previously been * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or @@ -252,7 +258,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * if xBlockTime expired without the semaphore becoming available. * * Example usage: - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphore = NULL;
  *
  * // A task that creates a semaphore.
@@ -289,7 +295,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
  *      }
  *  }
  * }
- * 
+ * @endcode * \defgroup xSemaphoreTake xSemaphoreTake * \ingroup Semaphores */ @@ -297,12 +303,12 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * semphr. h - *
+ * @code{c}
  * xSemaphoreTakeRecursive(
  *                          SemaphoreHandle_t xMutex,
  *                          TickType_t xBlockTime
  *                        );
- * 
+ * @endcode * * Macro to recursively obtain, or 'take', a mutex type semaphore. * The mutex must have previously been created using a call to @@ -333,7 +339,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * expired without the semaphore becoming available. * * Example usage: - *
+ * @code{c}
  * SemaphoreHandle_t xMutex = NULL;
  *
  * // A task that creates a mutex.
@@ -384,7 +390,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
  *      }
  *  }
  * }
- * 
+ * @endcode * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive * \ingroup Semaphores */ @@ -394,9 +400,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * semphr. h - *
+ * @code{c}
  * xSemaphoreGive( SemaphoreHandle_t xSemaphore );
- * 
+ * @endcode * * Macro to release a semaphore. The semaphore must have previously been * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or @@ -417,7 +423,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * semaphore was not first obtained correctly. * * Example usage: - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphore = NULL;
  *
  * void vATask( void * pvParameters )
@@ -451,7 +457,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
  *      }
  *  }
  * }
- * 
+ * @endcode * \defgroup xSemaphoreGive xSemaphoreGive * \ingroup Semaphores */ @@ -459,9 +465,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * semphr. h - *
+ * @code{c}
  * xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex );
- * 
+ * @endcode * * Macro to recursively release, or 'give', a mutex type semaphore. * The mutex must have previously been created using a call to @@ -485,7 +491,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * @return pdTRUE if the semaphore was given. * * Example usage: - *
+ * @code{c}
  * SemaphoreHandle_t xMutex = NULL;
  *
  * // A task that creates a mutex.
@@ -537,7 +543,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
  *      }
  *  }
  * }
- * 
+ * @endcode * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive * \ingroup Semaphores */ @@ -547,12 +553,12 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * semphr. h - *
+ * @code{c}
  * xSemaphoreGiveFromISR(
  *                        SemaphoreHandle_t xSemaphore,
  *                        BaseType_t *pxHigherPriorityTaskWoken
  *                    );
- * 
+ * @endcode * * Macro to release a semaphore. The semaphore must have previously been * created with a call to xSemaphoreCreateBinary() or xSemaphoreCreateCounting(). @@ -574,7 +580,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL. * * Example usage: - *
+ * @code{c}
  \#define LONG_TIME 0xffff
  \#define TICKS_TO_WAIT 10
  * SemaphoreHandle_t xSemaphore = NULL;
@@ -631,7 +637,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
  *      // to find the syntax required.
  *  }
  * }
- * 
+ * @endcode * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR * \ingroup Semaphores */ @@ -639,12 +645,12 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * semphr. h - *
+ * @code{c}
  * xSemaphoreTakeFromISR(
  *                        SemaphoreHandle_t xSemaphore,
  *                        BaseType_t *pxHigherPriorityTaskWoken
  *                    );
- * 
+ * @endcode * * Macro to take a semaphore from an ISR. The semaphore must have * previously been created with a call to xSemaphoreCreateBinary() or @@ -674,9 +680,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * semphr. h - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphoreCreateMutex( void );
- * 
+ * @endcode * * Creates a new mutex type semaphore instance, and returns a handle by which * the new mutex can be referenced. @@ -710,7 +716,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * data structures then NULL is returned. * * Example usage: - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphore;
  *
  * void vATask( void * pvParameters )
@@ -725,19 +731,19 @@ typedef QueueHandle_t SemaphoreHandle_t;
  *      // The semaphore can now be used.
  *  }
  * }
- * 
+ * @endcode * \defgroup xSemaphoreCreateMutex xSemaphoreCreateMutex * \ingroup Semaphores */ -#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) +#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_MUTEXES == 1 ) ) #define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ) #endif /** * semphr. h - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer );
- * 
+ * @endcode * * Creates a new mutex type semaphore instance, and returns a handle by which * the new mutex can be referenced. @@ -774,7 +780,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * mutex is returned. If pxMutexBuffer was NULL then NULL is returned. * * Example usage: - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphore;
  * StaticSemaphore_t xMutexBuffer;
  *
@@ -788,25 +794,25 @@ typedef QueueHandle_t SemaphoreHandle_t;
  *  // As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
  *  // so there is no need to check it.
  * }
- * 
+ * @endcode * \defgroup xSemaphoreCreateMutexStatic xSemaphoreCreateMutexStatic * \ingroup Semaphores */ -#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) +#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_MUTEXES == 1 ) ) #define xSemaphoreCreateMutexStatic( pxMutexBuffer ) xQueueCreateMutexStatic( queueQUEUE_TYPE_MUTEX, ( pxMutexBuffer ) ) -#endif /* configSUPPORT_STATIC_ALLOCATION */ +#endif /** * semphr. h - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void );
- * 
+ * @endcode * * Creates a new recursive mutex type semaphore instance, and returns a handle * by which the new recursive mutex can be referenced. * - * Internally, within the FreeRTOS implementation, recursive mutexs use a block + * Internally, within the FreeRTOS implementation, recursive mutexes use a block * of memory, in which the mutex structure is stored. If a recursive mutex is * created using xSemaphoreCreateRecursiveMutex() then the required memory is * automatically dynamically allocated inside the @@ -843,7 +849,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * SemaphoreHandle_t. * * Example usage: - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphore;
  *
  * void vATask( void * pvParameters )
@@ -858,7 +864,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
  *      // The semaphore can now be used.
  *  }
  * }
- * 
+ * @endcode * \defgroup xSemaphoreCreateRecursiveMutex xSemaphoreCreateRecursiveMutex * \ingroup Semaphores */ @@ -868,14 +874,14 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * semphr. h - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic( StaticSemaphore_t *pxMutexBuffer );
- * 
+ * @endcode * * Creates a new recursive mutex type semaphore instance, and returns a handle * by which the new recursive mutex can be referenced. * - * Internally, within the FreeRTOS implementation, recursive mutexs use a block + * Internally, within the FreeRTOS implementation, recursive mutexes use a block * of memory, in which the mutex structure is stored. If a recursive mutex is * created using xSemaphoreCreateRecursiveMutex() then the required memory is * automatically dynamically allocated inside the @@ -917,7 +923,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * returned. * * Example usage: - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphore;
  * StaticSemaphore_t xMutexBuffer;
  *
@@ -933,19 +939,19 @@ typedef QueueHandle_t SemaphoreHandle_t;
  *  // As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
  *  // so there is no need to check it.
  * }
- * 
+ * @endcode * \defgroup xSemaphoreCreateRecursiveMutexStatic xSemaphoreCreateRecursiveMutexStatic * \ingroup Semaphores */ #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) ) - #define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutexStatic( queueQUEUE_TYPE_RECURSIVE_MUTEX, pxStaticSemaphore ) + #define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutexStatic( queueQUEUE_TYPE_RECURSIVE_MUTEX, ( pxStaticSemaphore ) ) #endif /* configSUPPORT_STATIC_ALLOCATION */ /** * semphr. h - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount );
- * 
+ * @endcode * * Creates a new counting semaphore instance, and returns a handle by which the * new counting semaphore can be referenced. @@ -997,7 +1003,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * created. * * Example usage: - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphore;
  *
  * void vATask( void * pvParameters )
@@ -1015,7 +1021,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
  *      // The semaphore can now be used.
  *  }
  * }
- * 
+ * @endcode * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting * \ingroup Semaphores */ @@ -1025,9 +1031,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * semphr. h - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer );
- * 
+ * @endcode * * Creates a new counting semaphore instance, and returns a handle by which the * new counting semaphore can be referenced. @@ -1083,7 +1089,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * then NULL is returned. * * Example usage: - *
+ * @code{c}
  * SemaphoreHandle_t xSemaphore;
  * StaticSemaphore_t xSemaphoreBuffer;
  *
@@ -1102,7 +1108,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
  *  // No memory allocation was attempted so xSemaphore cannot be NULL, so there
  *  // is no need to check its value.
  * }
- * 
+ * @endcode * \defgroup xSemaphoreCreateCountingStatic xSemaphoreCreateCountingStatic * \ingroup Semaphores */ @@ -1112,9 +1118,9 @@ typedef QueueHandle_t SemaphoreHandle_t; /** * semphr. h - *
+ * @code{c}
  * void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );
- * 
+ * @endcode * * Delete a semaphore. This function must be used with care. For example, * do not delete a mutex type semaphore if the mutex is held by a task. @@ -1124,13 +1130,13 @@ typedef QueueHandle_t SemaphoreHandle_t; * \defgroup vSemaphoreDelete vSemaphoreDelete * \ingroup Semaphores */ -#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) ) +#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) ) /** * semphr.h - *
+ * @code{c}
  * TaskHandle_t xSemaphoreGetMutexHolder( SemaphoreHandle_t xMutex );
- * 
+ * @endcode * * If xMutex is indeed a mutex type semaphore, return the current mutex holder. * If xMutex is not a mutex type semaphore, or the mutex is available (not held @@ -1141,26 +1147,30 @@ typedef QueueHandle_t SemaphoreHandle_t; * the holder may change between the function exiting and the returned value * being tested. */ -#define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) ) +#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) + #define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) ) +#endif /** * semphr.h - *
+ * @code{c}
  * TaskHandle_t xSemaphoreGetMutexHolderFromISR( SemaphoreHandle_t xMutex );
- * 
+ * @endcode * * If xMutex is indeed a mutex type semaphore, return the current mutex holder. * If xMutex is not a mutex type semaphore, or the mutex is available (not held * by a task), return NULL. * */ -#define xSemaphoreGetMutexHolderFromISR( xSemaphore ) xQueueGetMutexHolderFromISR( ( xSemaphore ) ) +#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) + #define xSemaphoreGetMutexHolderFromISR( xSemaphore ) xQueueGetMutexHolderFromISR( ( xSemaphore ) ) +#endif /** * semphr.h - *
+ * @code{c}
  * UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore );
- * 
+ * @endcode * * If the semaphore is a counting semaphore then uxSemaphoreGetCount() returns * its current count value. If the semaphore is a binary semaphore then @@ -1168,12 +1178,27 @@ typedef QueueHandle_t SemaphoreHandle_t; * semaphore is not available. * */ -#define uxSemaphoreGetCount( xSemaphore ) uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) ) +#define uxSemaphoreGetCount( xSemaphore ) uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) ) /** * semphr.h * @code{c} - * BaseType_t xSemaphoreGetStaticBuffer( SemaphoreHandle_t xSemaphore ); + * UBaseType_t uxSemaphoreGetCountFromISR( SemaphoreHandle_t xSemaphore ); + * @endcode + * + * If the semaphore is a counting semaphore then uxSemaphoreGetCountFromISR() returns + * its current count value. If the semaphore is a binary semaphore then + * uxSemaphoreGetCountFromISR() returns 1 if the semaphore is available, and 0 if the + * semaphore is not available. + * + */ +#define uxSemaphoreGetCountFromISR( xSemaphore ) uxQueueMessagesWaitingFromISR( ( QueueHandle_t ) ( xSemaphore ) ) + +/** + * semphr.h + * @code{c} + * BaseType_t xSemaphoreGetStaticBuffer( SemaphoreHandle_t xSemaphore, + * StaticSemaphore_t ** ppxSemaphoreBuffer ); * @endcode * * Retrieve pointer to a statically created binary semaphore, counting semaphore, diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/stack_macros.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/stack_macros.h index a80613712e..9999606ca7 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/stack_macros.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/stack_macros.h @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -48,20 +54,21 @@ * use on the stack. */ #ifndef portSTACK_LIMIT_PADDING - #define portSTACK_LIMIT_PADDING 0 + #define portSTACK_LIMIT_PADDING 0 #endif #if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) ) /* Only the current stack state is to be checked. */ - #define taskCHECK_FOR_STACK_OVERFLOW() \ - { \ - /* Is the currently saved stack pointer within the stack limit? */ \ - if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack + portSTACK_LIMIT_PADDING ) \ - { \ - vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ - } \ - } + #define taskCHECK_FOR_STACK_OVERFLOW() \ + do { \ + /* Is the currently saved stack pointer within the stack limit? */ \ + if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack + portSTACK_LIMIT_PADDING ) \ + { \ + char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \ + } \ + } while( 0 ) #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ /*-----------------------------------------------------------*/ @@ -69,34 +76,36 @@ #if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) ) /* Only the current stack state is to be checked. */ - #define taskCHECK_FOR_STACK_OVERFLOW() \ - { \ - \ - /* Is the currently saved stack pointer within the stack limit? */ \ - if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) \ - { \ - vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ - } \ - } + #define taskCHECK_FOR_STACK_OVERFLOW() \ + do { \ + \ + /* Is the currently saved stack pointer within the stack limit? */ \ + if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) \ + { \ + char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \ + } \ + } while( 0 ) #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ /*-----------------------------------------------------------*/ #if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) - #define taskCHECK_FOR_STACK_OVERFLOW() \ - { \ - const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \ - const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5; \ - \ - if( ( pulStack[ 0 ] != ulCheckValue ) || \ - ( pulStack[ 1 ] != ulCheckValue ) || \ - ( pulStack[ 2 ] != ulCheckValue ) || \ - ( pulStack[ 3 ] != ulCheckValue ) ) \ - { \ - vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ - } \ - } + #define taskCHECK_FOR_STACK_OVERFLOW() \ + do { \ + const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \ + const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5U; \ + \ + if( ( pulStack[ 0 ] != ulCheckValue ) || \ + ( pulStack[ 1 ] != ulCheckValue ) || \ + ( pulStack[ 2 ] != ulCheckValue ) || \ + ( pulStack[ 3 ] != ulCheckValue ) ) \ + { \ + char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \ + } \ + } while( 0 ) #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ /*-----------------------------------------------------------*/ @@ -104,7 +113,7 @@ #if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) #define taskCHECK_FOR_STACK_OVERFLOW() \ - { \ + do { \ int8_t * pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \ static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ @@ -118,9 +127,10 @@ /* Has the extremity of the task stack ever been written over? */ \ if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ { \ - vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \ } \ - } + } while( 0 ) #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ /*-----------------------------------------------------------*/ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/stdint.readme b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/stdint.readme deleted file mode 100644 index bcfe1edbcd..0000000000 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/stdint.readme +++ /dev/null @@ -1,52 +0,0 @@ -/* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * https://www.FreeRTOS.org - * https://github.com/FreeRTOS - * - */ - -#ifndef FREERTOS_STDINT -#define FREERTOS_STDINT - -/******************************************************************************* - * THIS IS NOT A FULL stdint.h IMPLEMENTATION - It only contains the definitions - * necessary to build the FreeRTOS code. It is provided to allow FreeRTOS to be - * built using compilers that do not provide their own stdint.h definition. - * - * To use this file: - * - * 1) Copy this file into the directory that contains your FreeRTOSConfig.h - * header file, as that directory will already be in the compiler's include - * path. - * - * 2) Rename the copied file stdint.h. - * - */ - -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef short int16_t; -typedef unsigned short uint16_t; -typedef long int32_t; -typedef unsigned long uint32_t; - -#endif /* FREERTOS_STDINT */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/stream_buffer.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/stream_buffer.h index 00f9d0585e..00c97ecf93 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/stream_buffer.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/stream_buffer.h @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -69,13 +75,19 @@ struct StreamBufferDef_t; typedef struct StreamBufferDef_t * StreamBufferHandle_t; +/** + * Type used as a stream buffer's optional callback. + */ +typedef void (* StreamBufferCallbackFunction_t)( StreamBufferHandle_t xStreamBuffer, + BaseType_t xIsInsideISR, + BaseType_t * const pxHigherPriorityTaskWoken ); /** - * message_buffer.h + * stream_buffer.h * - *
+ * @code{c}
  * StreamBufferHandle_t xStreamBufferCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes );
- * 
+ * @endcode * * Creates a new stream buffer using dynamically allocated memory. See * xStreamBufferCreateStatic() for a version that uses statically allocated @@ -101,6 +113,16 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t; * trigger level of 1 being used. It is not valid to specify a trigger level * that is greater than the buffer size. * + * @param pxSendCompletedCallback Callback invoked when number of bytes at least equal to + * trigger level is sent to the stream buffer. If the parameter is NULL, it will use the default + * implementation provided by sbSEND_COMPLETED macro. To enable the callback, + * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h. + * + * @param pxReceiveCompletedCallback Callback invoked when more than zero bytes are read from a + * stream buffer. If the parameter is NULL, it will use the default + * implementation provided by sbRECEIVE_COMPLETED macro. To enable the callback, + * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h. + * * @return If NULL is returned, then the stream buffer cannot be created * because there is insufficient heap memory available for FreeRTOS to allocate * the stream buffer data structures and storage area. A non-NULL value being @@ -109,7 +131,7 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t; * buffer. * * Example use: - *
+ * @code{c}
  *
  * void vAFunction( void )
  * {
@@ -131,21 +153,28 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t;
  *      // The stream buffer was created successfully and can now be used.
  *  }
  * }
- * 
+ * @endcode * \defgroup xStreamBufferCreate xStreamBufferCreate * \ingroup StreamBufferManagement */ -#define xStreamBufferCreate( xBufferSizeBytes, xTriggerLevelBytes ) xStreamBufferGenericCreate( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE ) + +#define xStreamBufferCreate( xBufferSizeBytes, xTriggerLevelBytes ) \ + xStreamBufferGenericCreate( ( xBufferSizeBytes ), ( xTriggerLevelBytes ), pdFALSE, NULL, NULL ) + +#if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) + #define xStreamBufferCreateWithCallback( xBufferSizeBytes, xTriggerLevelBytes, pxSendCompletedCallback, pxReceiveCompletedCallback ) \ + xStreamBufferGenericCreate( ( xBufferSizeBytes ), ( xTriggerLevelBytes ), pdFALSE, ( pxSendCompletedCallback ), ( pxReceiveCompletedCallback ) ) +#endif /** * stream_buffer.h * - *
+ * @code{c}
  * StreamBufferHandle_t xStreamBufferCreateStatic( size_t xBufferSizeBytes,
  *                                              size_t xTriggerLevelBytes,
  *                                              uint8_t *pucStreamBufferStorageArea,
  *                                              StaticStreamBuffer_t *pxStaticStreamBuffer );
- * 
+ * @endcode * Creates a new stream buffer using statically allocated memory. See * xStreamBufferCreate() for a version that uses dynamically allocated memory. * @@ -170,19 +199,29 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t; * that is greater than the buffer size. * * @param pucStreamBufferStorageArea Must point to a uint8_t array that is at - * least xBufferSizeBytes + 1 big. This is the array to which streams are + * least xBufferSizeBytes big. This is the array to which streams are * copied when they are written to the stream buffer. * * @param pxStaticStreamBuffer Must point to a variable of type * StaticStreamBuffer_t, which will be used to hold the stream buffer's data * structure. * + * @param pxSendCompletedCallback Callback invoked when number of bytes at least equal to + * trigger level is sent to the stream buffer. If the parameter is NULL, it will use the default + * implementation provided by sbSEND_COMPLETED macro. To enable the callback, + * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h. + * + * @param pxReceiveCompletedCallback Callback invoked when more than zero bytes are read from a + * stream buffer. If the parameter is NULL, it will use the default + * implementation provided by sbRECEIVE_COMPLETED macro. To enable the callback, + * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h. + * * @return If the stream buffer is created successfully then a handle to the * created stream buffer is returned. If either pucStreamBufferStorageArea or * pxStaticstreamBuffer are NULL then NULL is returned. * * Example use: - *
+ * @code{c}
  *
  * // Used to dimension the array used to hold the streams.  The available space
  * // will actually be one less than this, so 999.
@@ -200,9 +239,9 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t;
  * StreamBufferHandle_t xStreamBuffer;
  * const size_t xTriggerLevel = 1;
  *
- *  xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucBufferStorage ),
+ *  xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucStorageBuffer ),
  *                                             xTriggerLevel,
- *                                             ucBufferStorage,
+ *                                             ucStorageBuffer,
  *                                             &xStreamBufferStruct );
  *
  *  // As neither the pucStreamBufferStorageArea or pxStaticStreamBuffer
@@ -212,12 +251,18 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t;
  *  // Other code that uses the stream buffer can go here.
  * }
  *
- * 
+ * @endcode * \defgroup xStreamBufferCreateStatic xStreamBufferCreateStatic * \ingroup StreamBufferManagement */ + #define xStreamBufferCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer ) \ - xStreamBufferGenericCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE, pucStreamBufferStorageArea, pxStaticStreamBuffer ) + xStreamBufferGenericCreateStatic( ( xBufferSizeBytes ), ( xTriggerLevelBytes ), pdFALSE, ( pucStreamBufferStorageArea ), ( pxStaticStreamBuffer ), NULL, NULL ) + +#if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) + #define xStreamBufferCreateStaticWithCallback( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback ) \ + xStreamBufferGenericCreateStatic( ( xBufferSizeBytes ), ( xTriggerLevelBytes ), pdFALSE, ( pucStreamBufferStorageArea ), ( pxStaticStreamBuffer ), ( pxSendCompletedCallback ), ( pxReceiveCompletedCallback ) ) +#endif /** * stream_buffer.h @@ -254,12 +299,12 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t; /** * stream_buffer.h * - *
+ * @code{c}
  * size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
  *                        const void *pvTxData,
  *                        size_t xDataLengthBytes,
  *                        TickType_t xTicksToWait );
- * 
+ * @endcode * * Sends bytes to a stream buffer. The bytes are copied into the stream buffer. * @@ -309,7 +354,7 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t; * write as many bytes as possible. * * Example use: - *
+ * @code{c}
  * void vAFunction( StreamBufferHandle_t xStreamBuffer )
  * {
  * size_t xBytesSent;
@@ -339,7 +384,7 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t;
  *      // were sent.  Could try again to send the remaining bytes.
  *  }
  * }
- * 
+ * @endcode * \defgroup xStreamBufferSend xStreamBufferSend * \ingroup StreamBufferManagement */ @@ -351,12 +396,12 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, /** * stream_buffer.h * - *
+ * @code{c}
  * size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
  *                               const void *pvTxData,
  *                               size_t xDataLengthBytes,
  *                               BaseType_t *pxHigherPriorityTaskWoken );
- * 
+ * @endcode * * Interrupt safe version of the API function that sends a stream of bytes to * the stream buffer. @@ -408,7 +453,7 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, * space for all the bytes to be written. * * Example use: - *
+ * @code{c}
  * // A stream buffer that has already been created.
  * StreamBufferHandle_t xStreamBuffer;
  *
@@ -435,12 +480,12 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
  *  // priority of the currently executing task was unblocked and a context
  *  // switch should be performed to ensure the ISR returns to the unblocked
  *  // task.  In most FreeRTOS ports this is done by simply passing
- *  // xHigherPriorityTaskWoken into taskYIELD_FROM_ISR(), which will test the
+ *  // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the
  *  // variables value, and perform the context switch if necessary.  Check the
  *  // documentation for the port in use for port specific instructions.
- *  taskYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+ *  portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
  * }
- * 
+ * @endcode * \defgroup xStreamBufferSendFromISR xStreamBufferSendFromISR * \ingroup StreamBufferManagement */ @@ -452,12 +497,12 @@ size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, /** * stream_buffer.h * - *
+ * @code{c}
  * size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
  *                           void *pvRxData,
  *                           size_t xBufferLengthBytes,
  *                           TickType_t xTicksToWait );
- * 
+ * @endcode * * Receives bytes from a stream buffer. * @@ -507,7 +552,7 @@ size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, * out before xBufferLengthBytes were available. * * Example use: - *
+ * @code{c}
  * void vAFunction( StreamBuffer_t xStreamBuffer )
  * {
  * uint8_t ucRxData[ 20 ];
@@ -525,11 +570,11 @@ size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
  *
  *  if( xReceivedBytes > 0 )
  *  {
- *      // A ucRxData contains another xRecievedBytes bytes of data, which can
+ *      // A ucRxData contains another xReceivedBytes bytes of data, which can
  *      // be processed here....
  *  }
  * }
- * 
+ * @endcode * \defgroup xStreamBufferReceive xStreamBufferReceive * \ingroup StreamBufferManagement */ @@ -541,12 +586,12 @@ size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, /** * stream_buffer.h * - *
+ * @code{c}
  * size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
  *                                  void *pvRxData,
  *                                  size_t xBufferLengthBytes,
  *                                  BaseType_t *pxHigherPriorityTaskWoken );
- * 
+ * @endcode * * An interrupt safe version of the API function that receives bytes from a * stream buffer. @@ -583,7 +628,7 @@ size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, * @return The number of bytes read from the stream buffer, if any. * * Example use: - *
+ * @code{c}
  * // A stream buffer that has already been created.
  * StreamBuffer_t xStreamBuffer;
  *
@@ -610,12 +655,12 @@ size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
  *  // priority of the currently executing task was unblocked and a context
  *  // switch should be performed to ensure the ISR returns to the unblocked
  *  // task.  In most FreeRTOS ports this is done by simply passing
- *  // xHigherPriorityTaskWoken into taskYIELD_FROM_ISR(), which will test the
+ *  // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the
  *  // variables value, and perform the context switch if necessary.  Check the
  *  // documentation for the port in use for port specific instructions.
- *  taskYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+ *  portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
  * }
- * 
+ * @endcode * \defgroup xStreamBufferReceiveFromISR xStreamBufferReceiveFromISR * \ingroup StreamBufferManagement */ @@ -627,9 +672,9 @@ size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, /** * stream_buffer.h * - *
+ * @code{c}
  * void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer );
- * 
+ * @endcode * * Deletes a stream buffer that was previously created using a call to * xStreamBufferCreate() or xStreamBufferCreateStatic(). If the stream @@ -649,9 +694,9 @@ void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTI /** * stream_buffer.h * - *
+ * @code{c}
  * BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer );
- * 
+ * @endcode * * Queries a stream buffer to see if it is full. A stream buffer is full if it * does not have any free space, and therefore cannot accept any more data. @@ -669,9 +714,9 @@ BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_ /** * stream_buffer.h * - *
+ * @code{c}
  * BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer );
- * 
+ * @endcode * * Queries a stream buffer to see if it is empty. A stream buffer is empty if * it does not contain any data. @@ -689,9 +734,9 @@ BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED /** * stream_buffer.h * - *
+ * @code{c}
  * BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer );
- * 
+ * @endcode * * Resets a stream buffer to its initial, empty, state. Any data that was in * the stream buffer is discarded. A stream buffer can only be reset if there @@ -712,9 +757,9 @@ BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_F /** * stream_buffer.h * - *
+ * @code{c}
  * size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer );
- * 
+ * @endcode * * Queries a stream buffer to see how much free space it contains, which is * equal to the amount of data that can be sent to the stream buffer before it @@ -733,9 +778,9 @@ size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVIL /** * stream_buffer.h * - *
+ * @code{c}
  * size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer );
- * 
+ * @endcode * * Queries a stream buffer to see how much data it contains, which is equal to * the number of bytes that can be read from the stream buffer before the stream @@ -754,9 +799,9 @@ size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILE /** * stream_buffer.h * - *
+ * @code{c}
  * BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel );
- * 
+ * @endcode * * A stream buffer's trigger level is the number of bytes that must be in the * stream buffer before a task that is blocked on the stream buffer to @@ -792,9 +837,9 @@ BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, /** * stream_buffer.h * - *
+ * @code{c}
  * BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
- * 
+ * @endcode * * For advanced users only. * @@ -832,9 +877,9 @@ BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer /** * stream_buffer.h * - *
+ * @code{c}
  * BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
- * 
+ * @endcode * * For advanced users only. * @@ -873,13 +918,19 @@ BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuf /* Functions below here are not part of the public API. */ StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes, - BaseType_t xIsMessageBuffer ) PRIVILEGED_FUNCTION; + BaseType_t xIsMessageBuffer, + StreamBufferCallbackFunction_t pxSendCompletedCallback, + StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION; -StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes, - size_t xTriggerLevelBytes, - BaseType_t xIsMessageBuffer, - uint8_t * const pucStreamBufferStorageArea, - StaticStreamBuffer_t * const pxStaticStreamBuffer ) PRIVILEGED_FUNCTION; +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes, + size_t xTriggerLevelBytes, + BaseType_t xIsMessageBuffer, + uint8_t * const pucStreamBufferStorageArea, + StaticStreamBuffer_t * const pxStaticStreamBuffer, + StreamBufferCallbackFunction_t pxSendCompletedCallback, + StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION; +#endif size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h index 7f436bcb0d..73af157edc 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -44,10 +50,17 @@ * MACROS AND DEFINITIONS *----------------------------------------------------------*/ -#define tskKERNEL_VERSION_NUMBER "V10.4.3" -#define tskKERNEL_VERSION_MAJOR 10 -#define tskKERNEL_VERSION_MINOR 4 -#define tskKERNEL_VERSION_BUILD 3 +/* + * If tskKERNEL_VERSION_NUMBER ends with + it represents the version in development + * after the numbered release. + * + * The tskKERNEL_VERSION_MAJOR, tskKERNEL_VERSION_MINOR, tskKERNEL_VERSION_BUILD + * values will reflect the last released version number. + */ +#define tskKERNEL_VERSION_NUMBER "V11.0.1" +#define tskKERNEL_VERSION_MAJOR 11 +#define tskKERNEL_VERSION_MINOR 0 +#define tskKERNEL_VERSION_BUILD 1 /* MPU region parameters passed in ulParameters * of MemoryRegion_t struct. */ @@ -57,6 +70,11 @@ #define tskMPU_REGION_NORMAL_MEMORY ( 1UL << 3UL ) #define tskMPU_REGION_DEVICE_MEMORY ( 1UL << 4UL ) +/* MPU region permissions stored in MPU settings to + * authorize access requests. */ +#define tskMPU_READ_PERMISSION ( 1UL << 0UL ) +#define tskMPU_WRITE_PERMISSION ( 1UL << 1UL ) + /* The direct to task notification feature used to have only a single notification * per task. Now there is an array of notifications per task that is dimensioned by * configTASK_NOTIFICATION_ARRAY_ENTRIES. For backward compatibility, any use of the @@ -74,34 +92,35 @@ * \defgroup TaskHandle_t TaskHandle_t * \ingroup Tasks */ -struct tskTaskControlBlock; /* The old naming convention is used to prevent breaking kernel aware debuggers. */ -typedef struct tskTaskControlBlock * TaskHandle_t; +struct tskTaskControlBlock; /* The old naming convention is used to prevent breaking kernel aware debuggers. */ +typedef struct tskTaskControlBlock * TaskHandle_t; +typedef const struct tskTaskControlBlock * ConstTaskHandle_t; /* * Defines the prototype to which the application task hook function must * conform. */ -typedef BaseType_t (* TaskHookFunction_t)( void * ); +typedef BaseType_t (* TaskHookFunction_t)( void * arg ); /* Task states returned by eTaskGetState. */ typedef enum { - eRunning = 0, /* A task is querying the state of itself, so must be running. */ - eReady, /* The task being queried is in a ready or pending ready list. */ - eBlocked, /* The task being queried is in the Blocked state. */ - eSuspended, /* The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */ - eDeleted, /* The task being queried has been deleted, but its TCB has not yet been freed. */ - eInvalid /* Used as an 'invalid state' value. */ + eRunning = 0, /* A task is querying the state of itself, so must be running. */ + eReady, /* The task being queried is in a ready or pending ready list. */ + eBlocked, /* The task being queried is in the Blocked state. */ + eSuspended, /* The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */ + eDeleted, /* The task being queried has been deleted, but its TCB has not yet been freed. */ + eInvalid /* Used as an 'invalid state' value. */ } eTaskState; /* Actions that can be performed when vTaskNotify() is called. */ typedef enum { - eNoAction = 0, /* Notify the task without updating its notify value. */ - eSetBits, /* Set bits in the task's notification value. */ - eIncrement, /* Increment the task's notification value. */ - eSetValueWithOverwrite, /* Set the task's notification value to a specific value even if the previous value has not yet been read by the task. */ - eSetValueWithoutOverwrite /* Set the task's notification value if the previous value has been read by the task. */ + eNoAction = 0, /* Notify the task without updating its notify value. */ + eSetBits, /* Set bits in the task's notification value. */ + eIncrement, /* Increment the task's notification value. */ + eSetValueWithOverwrite, /* Set the task's notification value to a specific value even if the previous value has not yet been read by the task. */ + eSetValueWithoutOverwrite /* Set the task's notification value if the previous value has been read by the task. */ } eNotifyAction; /* @@ -129,7 +148,7 @@ typedef struct xMEMORY_REGION typedef struct xTASK_PARAMETERS { TaskFunction_t pvTaskCode; - const char * pcName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const char * pcName; configSTACK_DEPTH_TYPE usStackDepth; void * pvParameters; UBaseType_t uxPriority; @@ -144,18 +163,22 @@ typedef struct xTASK_PARAMETERS * in the system. */ typedef struct xTASK_STATUS { - TaskHandle_t xHandle; /* The handle of the task to which the rest of the information in the structure relates. */ - const char * pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - UBaseType_t xTaskNumber; /* A number unique to the task. */ - eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */ - UBaseType_t uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */ - UBaseType_t uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */ - uint32_t ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See https://www.FreeRTOS.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */ - StackType_t * pxStackBase; /* Points to the lowest address of the task's stack area. */ - configSTACK_DEPTH_TYPE usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */ -#if ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUM_CORES > 1 ) ) - UBaseType_t uxCoreAffinityMask; /* The core affinity mask for the task */ -#endif + TaskHandle_t xHandle; /* The handle of the task to which the rest of the information in the structure relates. */ + const char * pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ + UBaseType_t xTaskNumber; /* A number unique to the task. */ + eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */ + UBaseType_t uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */ + UBaseType_t uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */ + configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See https://www.FreeRTOS.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */ + StackType_t * pxStackBase; /* Points to the lowest address of the task's stack area. */ + #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) + StackType_t * pxTopOfStack; /* Points to the top address of the task's stack area. */ + StackType_t * pxEndOfStack; /* Points to the end address of the task's stack area. */ + #endif + configSTACK_DEPTH_TYPE usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */ + #if ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) + UBaseType_t uxCoreAffinityMask; /* The core affinity mask for the task */ + #endif } TaskStatus_t; /* Possible return values for eTaskConfirmSleepModeStatus(). */ @@ -163,7 +186,9 @@ typedef enum { eAbortSleep = 0, /* A task has been made ready or a context switch pended since portSUPPRESS_TICKS_AND_SLEEP() was called - abort entering a sleep mode. */ eStandardSleep, /* Enter a sleep mode that will not last any longer than the expected idle time. */ - eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe to enter a sleep mode that can only be exited by an external interrupt. */ + #if ( INCLUDE_vTaskSuspend == 1 ) + eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe to enter a sleep mode that can only be exited by an external interrupt. */ + #endif /* INCLUDE_vTaskSuspend */ } eSleepModeStatus; /** @@ -176,10 +201,9 @@ typedef enum /** * Defines affinity to all available cores. * + * \ingroup TaskUtils */ -#define tskNO_AFFINITY ( ( UBaseType_t ) -1U ) - - +#define tskNO_AFFINITY ( ( UBaseType_t ) -1 ) /** * task. h @@ -189,7 +213,7 @@ typedef enum * \defgroup taskYIELD taskYIELD * \ingroup SchedulerControl */ -#define taskYIELD() portYIELD() +#define taskYIELD() portYIELD() /** * task. h @@ -203,8 +227,12 @@ typedef enum * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL * \ingroup SchedulerControl */ -#define taskENTER_CRITICAL() portENTER_CRITICAL() -#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() +#define taskENTER_CRITICAL() portENTER_CRITICAL() +#if ( configNUMBER_OF_CORES == 1 ) + #define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() +#else + #define taskENTER_CRITICAL_FROM_ISR() portENTER_CRITICAL_FROM_ISR() +#endif /** * task. h @@ -218,21 +246,22 @@ typedef enum * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL * \ingroup SchedulerControl */ -#define taskEXIT_CRITICAL() portEXIT_CRITICAL() -#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) +#define taskEXIT_CRITICAL() portEXIT_CRITICAL() +#if ( configNUMBER_OF_CORES == 1 ) + #define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) +#else + #define taskEXIT_CRITICAL_FROM_ISR( x ) portEXIT_CRITICAL_FROM_ISR( x ) +#endif /** * task. h * * Macro to disable all maskable interrupts. - * This also returns what the interrupt state was - * upon being called. This state may subsequently - * be passed to taskRESTORE_INTERRUPTS(). * * \defgroup taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS * \ingroup SchedulerControl */ -#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() +#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() /** * task. h @@ -242,29 +271,7 @@ typedef enum * \defgroup taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS * \ingroup SchedulerControl */ -#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() - -/** - * task. h - * - * Macro to restore microcontroller interrupts to - * a previous state. - * - * \defgroup taskRESTORE_INTERRUPTS taskRESTORE_INTERRUPTS - * \ingroup SchedulerControl - */ -#define taskRESTORE_INTERRUPTS(ulState) portRESTORE_INTERRUPTS(ulState) - -/** - * task. h - * - * Macro that determines if it is being called from within an ISR - * or a task. Returns non-zero if it is in an ISR. - * - * \defgroup taskCHECK_IF_IN_ISR taskCHECK_IF_IN_ISR - * \ingroup SchedulerControl - */ -#define taskCHECK_IF_IN_ISR() portCHECK_IF_IN_ISR() +#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() /* Definitions returned by xTaskGetSchedulerState(). taskSCHEDULER_SUSPENDED is * 0 to generate more optimal code when configASSERT() is defined as the constant @@ -273,8 +280,8 @@ typedef enum #define taskSCHEDULER_NOT_STARTED ( ( BaseType_t ) 1 ) #define taskSCHEDULER_RUNNING ( ( BaseType_t ) 2 ) -/* Check if core value is valid */ -#define taskVALID_CORE_ID( xCoreID ) ( ( BaseType_t ) ( ( 0 <= (BaseType_t) xCoreID ) && ( (BaseType_t) xCoreID < configNUM_CORES ) ) ) +/* Checks if core ID is valid. */ +#define taskVALID_CORE_ID( xCoreID ) ( ( ( ( ( BaseType_t ) 0 <= ( xCoreID ) ) && ( ( xCoreID ) < ( BaseType_t ) configNUMBER_OF_CORES ) ) ) ? ( pdTRUE ) : ( pdFALSE ) ) /*----------------------------------------------------------- * TASK CREATION API @@ -282,7 +289,7 @@ typedef enum /** * task. h - *
+ * @code{c}
  * BaseType_t xTaskCreate(
  *                            TaskFunction_t pxTaskCode,
  *                            const char *pcName,
@@ -291,7 +298,7 @@ typedef enum
  *                            UBaseType_t uxPriority,
  *                            TaskHandle_t *pxCreatedTask
  *                        );
- * 
+ * @endcode * * Create a new task and add it to the list of tasks that are ready to run. * @@ -341,7 +348,7 @@ typedef enum * list, otherwise an error code defined in the file projdefs.h * * Example usage: - *
+ * @code{c}
  * // Task to be created.
  * void vTaskCode( void * pvParameters )
  * {
@@ -370,22 +377,22 @@ typedef enum
  *      vTaskDelete( xHandle );
  *   }
  * }
- * 
+ * @endcode * \defgroup xTaskCreate xTaskCreate * \ingroup Tasks */ #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, - const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const char * const pcName, const configSTACK_DEPTH_TYPE usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION; #endif -#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) +#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) BaseType_t xTaskCreateAffinitySet( TaskFunction_t pxTaskCode, - const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const char * const pcName, const configSTACK_DEPTH_TYPE usStackDepth, void * const pvParameters, UBaseType_t uxPriority, @@ -395,15 +402,15 @@ typedef enum /** * task. h - *
-* TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
+ * @code{c}
+ * TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
  *                               const char *pcName,
  *                               uint32_t ulStackDepth,
  *                               void *pvParameters,
  *                               UBaseType_t uxPriority,
  *                               StackType_t *puxStackBuffer,
  *                               StaticTask_t *pxTaskBuffer );
- * 
+ * @endcode * * Create a new task and add it to the list of tasks that are ready to run. * @@ -448,7 +455,7 @@ typedef enum * NULL is returned. * * Example usage: - *
+ * @code{c}
  *
  *  // 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
@@ -497,13 +504,13 @@ typedef enum
  *      // to suspend the task.
  *      vTaskSuspend( xHandle );
  *  }
- * 
+ * @endcode * \defgroup xTaskCreateStatic xTaskCreateStatic * \ingroup Tasks */ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, - const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, @@ -511,9 +518,9 @@ typedef enum StaticTask_t * const pxTaskBuffer ) PRIVILEGED_FUNCTION; #endif /* configSUPPORT_STATIC_ALLOCATION */ -#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) +#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) TaskHandle_t xTaskCreateStaticAffinitySet( TaskFunction_t pxTaskCode, - const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, @@ -524,9 +531,9 @@ typedef enum /** * task. h - *
+ * @code{c}
  * BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );
- * 
+ * @endcode * * Only available when configSUPPORT_DYNAMIC_ALLOCATION is set to 1. * @@ -552,7 +559,7 @@ typedef enum * list, otherwise an error code defined in the file projdefs.h * * Example usage: - *
+ * @code{c}
  * // Create an TaskParameters_t structure that defines the task to be created.
  * static const TaskParameters_t xCheckTaskParameters =
  * {
@@ -591,7 +598,7 @@ typedef enum
  *  // and/or timer task.
  *  for( ;; );
  * }
- * 
+ * @endcode * \defgroup xTaskCreateRestricted xTaskCreateRestricted * \ingroup Tasks */ @@ -600,7 +607,7 @@ typedef enum TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; #endif -#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) +#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) BaseType_t xTaskCreateRestrictedAffinitySet( const TaskParameters_t * const pxTaskDefinition, UBaseType_t uxCoreAffinityMask, TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; @@ -608,9 +615,9 @@ typedef enum /** * task. h - *
+ * @code{c}
  * BaseType_t xTaskCreateRestrictedStatic( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );
- * 
+ * @endcode * * Only available when configSUPPORT_STATIC_ALLOCATION is set to 1. * @@ -642,7 +649,7 @@ typedef enum * list, otherwise an error code defined in the file projdefs.h * * 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
@@ -678,7 +685,7 @@ typedef enum
  *  // 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.
- *  xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );
+ *  xTaskCreateRestrictedStatic( &xRegTest1Parameters, &xHandle );
  *
  *  // Start the scheduler.
  *  vTaskStartScheduler();
@@ -687,7 +694,7 @@ typedef enum
  *  // and/or timer task.
  *  for( ;; );
  * }
- * 
+ * @endcode * \defgroup xTaskCreateRestrictedStatic xTaskCreateRestrictedStatic * \ingroup Tasks */ @@ -696,7 +703,7 @@ typedef enum TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; #endif -#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) +#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; @@ -704,21 +711,21 @@ typedef enum /** * 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 xTask The handle of the task being updated. + * @param xTaskToModify The handle of the task being updated. * - * @param xRegions A pointer to a MemoryRegion_t structure that contains the + * @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
@@ -745,18 +752,20 @@ typedef enum
  *  // access its stack and the ucOneKByte array (unless any other statically
  *  // defined or shared regions have been declared elsewhere).
  * }
- * 
- * \defgroup xTaskCreateRestricted xTaskCreateRestricted + * @endcode + * \defgroup vTaskAllocateMPURegions vTaskAllocateMPURegions * \ingroup Tasks */ -void vTaskAllocateMPURegions( TaskHandle_t xTask, - const MemoryRegion_t * const pxRegions ) PRIVILEGED_FUNCTION; +#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. @@ -778,7 +787,7 @@ void vTaskAllocateMPURegions( TaskHandle_t xTask, * cause the calling task to be deleted. * * Example usage: - *
+ * @code{c}
  * void vOtherFunction( void )
  * {
  * TaskHandle_t xHandle;
@@ -789,7 +798,7 @@ void vTaskAllocateMPURegions( TaskHandle_t xTask,
  *   // Use the handle to delete the task.
  *   vTaskDelete( xHandle );
  * }
- * 
+ * @endcode * \defgroup vTaskDelete vTaskDelete * \ingroup Tasks */ @@ -801,9 +810,9 @@ void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; /** * 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 @@ -819,7 +828,7 @@ void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; * 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 effect the frequency + * 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 @@ -851,9 +860,9 @@ 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. @@ -891,7 +900,7 @@ void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION; * 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 )
  * {
@@ -910,7 +919,7 @@ void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION;
  *         // whether a deadline was missed if the code here took too long.
  *     }
  * }
- * 
+ * @endcode * \defgroup xTaskDelayUntil xTaskDelayUntil * \ingroup TaskCtrl */ @@ -921,17 +930,17 @@ BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, * vTaskDelayUntil() is the older version of xTaskDelayUntil() and does not * return a value. */ -#define vTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ) \ -{ \ - ( void ) xTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ); \ -} +#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. @@ -957,13 +966,15 @@ BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, * \defgroup xTaskAbortDelay xTaskAbortDelay * \ingroup TaskCtrl */ -BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; +#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. @@ -976,7 +987,7 @@ BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; * @return The priority of xTask. * * Example usage: - *
+ * @code{c}
  * void vAFunction( void )
  * {
  * TaskHandle_t xHandle;
@@ -1002,7 +1013,7 @@ BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
  *       // Our priority (obtained using NULL handle) is higher.
  *   }
  * }
- * 
+ * @endcode * \defgroup uxTaskPriorityGet uxTaskPriorityGet * \ingroup TaskCtrl */ @@ -1010,9 +1021,9 @@ 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. */ @@ -1020,9 +1031,40 @@ UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) PRIVILEGED_FUNC /** * 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. @@ -1036,13 +1078,15 @@ UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) PRIVILEGED_FUNC * state of the task might change between the function being called, and the * functions return value being tested by the calling task. */ -eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; +#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. @@ -1056,7 +1100,7 @@ eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; * filled with information about the task referenced by the handle passed using * the xTask parameter. * - * @xGetFreeStackSpace The TaskStatus_t structure contains a member to report + * @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 @@ -1072,7 +1116,7 @@ eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; * eState will be reported as the task state in the TaskStatus_t structure. * * Example usage: - *
+ * @code{c}
  * void vAFunction( void )
  * {
  * TaskHandle_t xHandle;
@@ -1090,20 +1134,22 @@ eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
  *                pdTRUE, // Include the high water mark in xTaskDetails.
  *                eInvalid ); // Include the task state in xTaskDetails.
  * }
- * 
+ * @endcode * \defgroup vTaskGetInfo vTaskGetInfo * \ingroup TaskCtrl */ -void vTaskGetInfo( TaskHandle_t xTask, - TaskStatus_t * pxTaskStatus, - BaseType_t xGetFreeStackSpace, - eTaskState eState ) PRIVILEGED_FUNCTION; +#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. @@ -1119,7 +1165,7 @@ void vTaskGetInfo( TaskHandle_t xTask, * @param uxNewPriority The priority to which the task will be set. * * Example usage: - *
+ * @code{c}
  * void vAFunction( void )
  * {
  * TaskHandle_t xHandle;
@@ -1137,7 +1183,7 @@ void vTaskGetInfo( TaskHandle_t xTask,
  *   // Use a NULL handle to raise our priority to the same value.
  *   vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );
  * }
- * 
+ * @endcode * \defgroup vTaskPrioritySet vTaskPrioritySet * \ingroup TaskCtrl */ @@ -1146,9 +1192,9 @@ void vTaskPrioritySet( TaskHandle_t xTask, /** * 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. @@ -1164,7 +1210,7 @@ void vTaskPrioritySet( TaskHandle_t xTask, * handle will cause the calling task to be suspended. * * Example usage: - *
+ * @code{c}
  * void vAFunction( void )
  * {
  * TaskHandle_t xHandle;
@@ -1191,7 +1237,7 @@ void vTaskPrioritySet( TaskHandle_t xTask,
  *   // We cannot get here unless another task calls vTaskResume
  *   // with our handle as the parameter.
  * }
- * 
+ * @endcode * \defgroup vTaskSuspend vTaskSuspend * \ingroup TaskCtrl */ @@ -1199,9 +1245,9 @@ 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. @@ -1215,7 +1261,7 @@ void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION; * @param xTaskToResume Handle to the task being readied. * * Example usage: - *
+ * @code{c}
  * void vAFunction( void )
  * {
  * TaskHandle_t xHandle;
@@ -1242,7 +1288,7 @@ void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION;
  *   // The created task will once again get microcontroller processing
  *   // time in accordance with its priority within the system.
  * }
- * 
+ * @endcode * \defgroup vTaskResume vTaskResume * \ingroup TaskCtrl */ @@ -1250,9 +1296,9 @@ 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. @@ -1279,93 +1325,98 @@ void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; */ 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 configNUM_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 ); +#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 ( 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 - * configNUM_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( const TaskHandle_t xTask ); +#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. * @@ -1395,7 +1446,10 @@ BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; * } * } */ -void vTaskPreemptionDisable( const TaskHandle_t xTask ); + void vTaskPreemptionDisable( const TaskHandle_t xTask ); +#endif + +#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) /** * @brief Enables preemption for a task. @@ -1426,7 +1480,8 @@ void vTaskPreemptionDisable( const TaskHandle_t xTask ); * } * } */ -void vTaskPreemptionEnable( const TaskHandle_t xTask ); + void vTaskPreemptionEnable( const TaskHandle_t xTask ); +#endif /*----------------------------------------------------------- * SCHEDULER CONTROL @@ -1434,9 +1489,9 @@ void vTaskPreemptionEnable( const TaskHandle_t xTask ); /** * 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. @@ -1445,7 +1500,7 @@ void vTaskPreemptionEnable( const TaskHandle_t xTask ); * tasks and starting the kernel. * * Example usage: - *
+ * @code{c}
  * void vAFunction( void )
  * {
  *   // Create at least one task before starting the kernel.
@@ -1456,7 +1511,7 @@ void vTaskPreemptionEnable( const TaskHandle_t xTask );
  *
  *   // Will not get here unless a task calls vTaskEndScheduler ()
  * }
- * 
+ * @endcode * * \defgroup vTaskStartScheduler vTaskStartScheduler * \ingroup SchedulerControl @@ -1465,9 +1520,9 @@ 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. @@ -1489,7 +1544,7 @@ void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; * tasks. * * Example usage: - *
+ * @code{c}
  * void vTaskCode( void * pvParameters )
  * {
  *   for( ;; )
@@ -1514,7 +1569,7 @@ void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION;
  *   // vTaskEndScheduler ().  When we get here we are back to single task
  *   // execution.
  * }
- * 
+ * @endcode * * \defgroup vTaskEndScheduler vTaskEndScheduler * \ingroup SchedulerControl @@ -1523,9 +1578,9 @@ 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. @@ -1539,7 +1594,7 @@ void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; * is suspended. * * Example usage: - *
+ * @code{c}
  * void vTask1( void * pvParameters )
  * {
  *   for( ;; )
@@ -1568,7 +1623,7 @@ void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION;
  *       xTaskResumeAll ();
  *   }
  * }
- * 
+ * @endcode * \defgroup vTaskSuspendAll vTaskSuspendAll * \ingroup SchedulerControl */ @@ -1576,9 +1631,9 @@ 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(). @@ -1590,7 +1645,7 @@ void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; * returned, otherwise pdFALSE is returned. * * Example usage: - *
+ * @code{c}
  * void vTask1( void * pvParameters )
  * {
  *   for( ;; )
@@ -1624,7 +1679,7 @@ void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION;
  *       }
  *   }
  * }
- * 
+ * @endcode * \defgroup xTaskResumeAll xTaskResumeAll * \ingroup SchedulerControl */ @@ -1636,7 +1691,9 @@ BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION; /** * task. h - *
TickType_t xTaskGetTickCount( void );
+ * @code{c} + * TickType_t xTaskGetTickCount( void ); + * @endcode * * @return The count of ticks since vTaskStartScheduler was called. * @@ -1647,7 +1704,9 @@ TickType_t xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; /** * task. h - *
TickType_t xTaskGetTickCountFromISR( void );
+ * @code{c} + * TickType_t xTaskGetTickCountFromISR( void ); + * @endcode * * @return The count of ticks since vTaskStartScheduler was called. * @@ -1663,7 +1722,9 @@ TickType_t xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; /** * task. h - *
uint16_t uxTaskGetNumberOfTasks( void );
+ * @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 @@ -1677,7 +1738,9 @@ UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; /** * task. h - *
char *pcTaskGetName( TaskHandle_t xTaskToQuery );
+ * @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 @@ -1686,11 +1749,13 @@ UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; * \defgroup pcTaskGetName pcTaskGetName * \ingroup TaskUtils */ -char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /** * task. h - *
TaskHandle_t xTaskGetHandle( const char *pcNameToQuery );
+ * @code{c} + * TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ); + * @endcode * * NOTE: This function takes a relatively long time to complete and should be * used sparingly. @@ -1702,7 +1767,9 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lin * \defgroup pcTaskGetHandle pcTaskGetHandle * \ingroup TaskUtils */ -TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +#if ( INCLUDE_xTaskGetHandle == 1 ) + TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) PRIVILEGED_FUNCTION; +#endif /** * task. h @@ -1736,7 +1803,9 @@ TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) PRIVILEGED_FUNCTION; /** * task.h - *
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
+ * @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. @@ -1759,11 +1828,15 @@ TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) PRIVILEGED_FUNCTION; * actual spaces on the stack rather than bytes) since the task referenced by * xTask was created. */ -UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; +#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) + UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; +#endif /** * task.h - *
configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask );
+ * @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. @@ -1786,7 +1859,9 @@ UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) PRIVILEGED_FUNCTIO * actual spaces on the stack rather than bytes) since the task referenced by * xTask was created. */ -configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; +#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, @@ -1799,9 +1874,9 @@ configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVIL /** * 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 @@ -1812,9 +1887,9 @@ configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVIL /** * 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 @@ -1824,9 +1899,9 @@ configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVIL /** * 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. @@ -1852,55 +1927,121 @@ configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVIL #if ( configCHECK_FOR_STACK_OVERFLOW > 0 ) - /** - * task.h - *
void vApplicationStackOverflowHook( TaskHandle_t xTask char *pcTaskName); 
- * - * 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. - */ - void vApplicationStackOverflowHook( TaskHandle_t xTask, - char * pcTaskName ); +/** + * 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_TICK_HOOK > 0 ) - /** - * task.h - *
void vApplicationTickHook( void ); 
- * - * This hook function is called in the system tick handler after any OS work is completed. - */ - void vApplicationTickHook( void ); /*lint !e526 Symbol not defined as it is an application callback. */ +#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 - *
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, StackType_t ** ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) 
- * - * 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 pulIdleTaskStackSize A pointer to the number of elements that will fit in the allocated stack buffer - */ - void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, - StackType_t ** ppxIdleTaskStackBuffer, - uint32_t * pulIdleTaskStackSize ); /*lint !e526 Symbol not defined as it is an application callback. */ -#endif /** * task.h - *
+ * @code{c}
+ * void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, StackType_t ** ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
+ * @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 pulIdleTaskStackSize A pointer to the number of elements that will fit in the allocated stack buffer
+ */
+    void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
+                                        StackType_t ** ppxIdleTaskStackBuffer,
+                                        uint32_t * pulIdleTaskStackSize );
+
+/**
+ * task.h
+ * @code{c}
+ * void vApplicationGetPassiveIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, StackType_t ** ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize, 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 pulIdleTaskStackSize 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,
+                                                   uint32_t * pulIdleTaskStackSize,
+                                                   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. @@ -1909,17 +2050,35 @@ configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVIL * wants. The return value is the value returned by the task hook function * registered by the user. */ -BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, - void * pvParameter ) PRIVILEGED_FUNCTION; +#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. * - * Simply returns a pointer to the array of idle task handles. - * It is not valid to call xTaskGetIdleTaskHandle() before the scheduler has been started. + * 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. */ -TaskHandle_t *xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION; +#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 @@ -1956,7 +2115,7 @@ TaskHandle_t *xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION; * 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
@@ -1964,7 +2123,7 @@ TaskHandle_t *xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION;
  *  {
  *  TaskStatus_t *pxTaskStatusArray;
  *  volatile UBaseType_t uxArraySize, x;
- *  uint32_t ulTotalRunTime, ulStatsAsPercentage;
+ *  configRUN_TIME_COUNTER_TYPE ulTotalRunTime, ulStatsAsPercentage;
  *
  *      // Make sure the write buffer does not contain a string.
  * pcWriteBuffer = 0x00;
@@ -2016,15 +2175,19 @@ TaskHandle_t *xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION;
  *          vPortFree( pxTaskStatusArray );
  *      }
  *  }
- *  
+ * @endcode */ -UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, - const UBaseType_t uxArraySize, - uint32_t * const pulTotalRunTime ) PRIVILEGED_FUNCTION; +#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 - *
void vTaskList( char *pcWriteBuffer );
+ * @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 @@ -2044,16 +2207,77 @@ UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, * 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: + * names, states, priority, stack usage and task number. + * 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 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: * names, states, priority, stack usage and task number. * 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 sprintf() C library function that might + * 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 sprintf() is provided in many of the + * 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!). * @@ -2069,11 +2293,13 @@ UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, * \defgroup vTaskList vTaskList * \ingroup TaskUtils */ -void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +#define vTaskList( pcWriteBuffer ) vTaskListTasks( pcWriteBuffer, configSTATS_BUFFER_MAX_LENGTH ) /** * task. h - *
void vTaskGetRunTimeStats( char *pcWriteBuffer );
+ * @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 @@ -2090,6 +2316,73 @@ void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unq * 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 compatiblity. 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. @@ -2104,10 +2397,10 @@ void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unq * amount of time each task has spent in the Running state in both absolute and * percentage terms. * - * vTaskGetRunTimeStats() has a dependency on the sprintf() C library function + * 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 sprintf() is provided in many of the + * 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!). * @@ -2123,19 +2416,59 @@ void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unq * \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats * \ingroup TaskUtils */ -void vTaskGetRunTimeStats( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +#define vTaskGetRunTimeStats( pcWriteBuffer ) vTaskGetRunTimeStatistics( pcWriteBuffer, configSTATS_BUFFER_MAX_LENGTH ) /** * task. h - *
uint32_t ulTaskGetIdleRunTimeCounter( void );
+ * @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 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. + * 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 @@ -2143,9 +2476,16 @@ void vTaskGetRunTimeStats( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lin * 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. + * 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. * - * @return The total run time of the idle task. This is the amount of time the + * 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. @@ -2153,12 +2493,17 @@ void vTaskGetRunTimeStats( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lin * \defgroup ulTaskGetIdleRunTimeCounter ulTaskGetIdleRunTimeCounter * \ingroup TaskUtils */ -uint32_t ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION; +#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 - *
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 );
+ * @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. * @@ -2273,8 +2618,10 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, /** * task. h - *
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 );
+ * @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. * @@ -2300,8 +2647,10 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, /** * task. h - *
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 );
+ * @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 ); + * @endcode * * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. * @@ -2422,8 +2771,10 @@ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, /** * task. h - *
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 );
+ * @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. * @@ -2449,11 +2800,11 @@ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, /** * 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 );
- * 
+ * @endcode * * Waits for a direct to task notification to be pending at a given index within * an array of direct to task notifications. @@ -2563,8 +2914,10 @@ BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, /** * task. h - *
BaseType_t xTaskNotifyGiveIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify );
- *
BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
+ * @code{c} + * BaseType_t xTaskNotifyGiveIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify ); + * BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify ); + * @endcode * * Sends a direct to task notification to a particular index in the target * task's notification array in a manner similar to giving a counting semaphore. @@ -2598,7 +2951,7 @@ BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, * * 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 ulTaskNotificationTakeIndexed() API function rather than the + * using the ulTaskNotifyTakeIndexed() API function rather than the * xTaskNotifyWaitIndexed() API function. * * **NOTE** Each notification within the array operates independently - a task @@ -2638,8 +2991,10 @@ BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, /** * task. h - *
void vTaskNotifyGiveIndexedFromISR( TaskHandle_t xTaskHandle, UBaseType_t uxIndexToNotify, BaseType_t *pxHigherPriorityTaskWoken );
- *
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken );
+ * @code{c} + * void vTaskNotifyGiveIndexedFromISR( TaskHandle_t xTaskHandle, UBaseType_t uxIndexToNotify, BaseType_t *pxHigherPriorityTaskWoken ); + * void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken ); + * @endcode * * A version of xTaskNotifyGiveIndexed() that can be called from an interrupt * service routine (ISR). @@ -2673,7 +3028,7 @@ BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, * * 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 ulTaskNotificationTakeIndexed() API function rather than the + * using the ulTaskNotifyTakeIndexed() API function rather than the * xTaskNotifyWaitIndexed() API function. * * **NOTE** Each notification within the array operates independently - a task @@ -2717,17 +3072,17 @@ void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; #define vTaskNotifyGiveFromISR( xTaskToNotify, pxHigherPriorityTaskWoken ) \ - vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( pxHigherPriorityTaskWoken ) ); + vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( pxHigherPriorityTaskWoken ) ) #define vTaskNotifyGiveIndexedFromISR( xTaskToNotify, uxIndexToNotify, pxHigherPriorityTaskWoken ) \ - vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( pxHigherPriorityTaskWoken ) ); + vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( pxHigherPriorityTaskWoken ) ) /** * task. h - *
+ * @code{c}
  * uint32_t ulTaskNotifyTakeIndexed( UBaseType_t uxIndexToWaitOn, BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
  *
  * uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
- * 
+ * @endcode * * Waits for a direct to task notification on a particular index in the calling * task's notification array in a manner similar to taking a counting semaphore. @@ -2829,11 +3184,11 @@ 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. * @@ -2893,11 +3248,11 @@ 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 );
- * 
+ * @endcode * * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. * @@ -2959,9 +3314,9 @@ uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask, /** * task.h - *
+ * @code{c}
  * void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut );
- * 
+ * @endcode * * Capture the current time for future use with xTaskCheckForTimeOut(). * @@ -2975,9 +3330,9 @@ void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; /** * task.h - *
+ * @code{c}
  * BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait );
- * 
+ * @endcode * * Determines if pxTicksToWait ticks has passed since a time was captured * using a call to vTaskSetTimeOutState(). The captured time includes the tick @@ -2999,7 +3354,7 @@ void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; * @see https://www.FreeRTOS.org/xTaskCheckForTimeOut.html * * Example Usage: - *
+ * @code{c}
  *  // Driver library function used to receive uxWantedBytes from an Rx buffer
  *  // that is filled by a UART interrupt. If there are not enough bytes in the
  *  // Rx buffer then the task enters the Blocked state until it is notified that
@@ -3009,7 +3364,7 @@ void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION;
  *  // spent in the Blocked state does not exceed MAX_TIME_TO_WAIT. This
  *  // continues until either the buffer contains at least uxWantedBytes bytes,
  *  // or the total amount of time spent in the Blocked state reaches
- *  // MAX_TIME_TO_WAIT – at which point the task reads however many bytes are
+ *  // MAX_TIME_TO_WAIT - at which point the task reads however many bytes are
  *  // available up to a maximum of uxWantedBytes.
  *
  *  size_t xUART_Receive( uint8_t *pucBuffer, size_t uxWantedBytes )
@@ -3052,7 +3407,7 @@ void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION;
  *
  *      return uxReceived;
  *  }
- * 
+ * @endcode * \defgroup xTaskCheckForTimeOut xTaskCheckForTimeOut * \ingroup TaskCtrl */ @@ -3061,9 +3416,9 @@ BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, /** * task.h - *
+ * @code{c}
  * BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp );
- * 
+ * @endcode * * This function corrects the tick count value after the application code has held * interrupts disabled for an extended period resulting in tick interrupts having @@ -3092,6 +3447,12 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) PRIVILEGED_FUNCTION; * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES *----------------------------------------------------------*/ +#if ( configNUMBER_OF_CORES == 1 ) + #define taskYIELD_WITHIN_API() portYIELD_WITHIN_API() +#else /* #if ( configNUMBER_OF_CORES == 1 ) */ + #define taskYIELD_WITHIN_API() vTaskYieldWithinAPI() +#endif /* #if ( configNUMBER_OF_CORES == 1 ) */ + /* * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS @@ -3197,7 +3558,11 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, * Sets the pointer to the current TCB to the TCB of the highest priority task * that is ready to run. */ -portDONT_DISCARD void vTaskSwitchContext( BaseType_t xCoreID ) PRIVILEGED_FUNCTION; +#if ( configNUMBER_OF_CORES == 1 ) + portDONT_DISCARD void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION; +#else + portDONT_DISCARD void vTaskSwitchContext( BaseType_t xCoreID ) PRIVILEGED_FUNCTION; +#endif /* * THESE FUNCTIONS MUST NOT BE USED FROM APPLICATION CODE. THEY ARE USED BY @@ -3213,7 +3578,9 @@ TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; /* * Return the handle of the task running on specified core. */ -TaskHandle_t xTaskGetCurrentTaskHandleCPU( UBaseType_t xCoreID ) PRIVILEGED_FUNCTION; +#if ( configNUMBER_OF_CORES > 1 ) + TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID ) PRIVILEGED_FUNCTION; +#endif /* * Shortcut used by the queue implementation to prevent unnecessary call to @@ -3251,16 +3618,20 @@ void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder, UBaseType_t uxHighestPriorityWaitingTask ) PRIVILEGED_FUNCTION; /* - * Get the uxTCBNumber assigned to the task referenced by the xTask parameter. + * Get the uxTaskNumber assigned to the task referenced by the xTask parameter. */ -UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; +#if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; +#endif /* * Set the uxTaskNumber of the task referenced by the xTask parameter to * uxHandle. */ -void vTaskSetTaskNumber( TaskHandle_t xTask, - const UBaseType_t uxHandle ) PRIVILEGED_FUNCTION; +#if ( configUSE_TRACE_FACILITY == 1 ) + void vTaskSetTaskNumber( TaskHandle_t xTask, + const UBaseType_t uxHandle ) PRIVILEGED_FUNCTION; +#endif /* * Only available when configUSE_TICKLESS_IDLE is set to 1. @@ -3270,7 +3641,9 @@ void vTaskSetTaskNumber( TaskHandle_t xTask, * to date with the actual execution time by being skipped forward by a time * equal to the idle period. */ -void vTaskStepTick( const TickType_t xTicksToJump ) PRIVILEGED_FUNCTION; +#if ( configUSE_TICKLESS_IDLE != 0 ) + void vTaskStepTick( TickType_t xTicksToJump ) PRIVILEGED_FUNCTION; +#endif /* * Only available when configUSE_TICKLESS_IDLE is set to 1. @@ -3286,7 +3659,9 @@ void vTaskStepTick( const TickType_t xTicksToJump ) PRIVILEGED_FUNCTION; * critical section between the timer being stopped and the sleep mode being * entered to ensure it is ok to proceed into the sleep mode. */ -eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION; +#if ( configUSE_TICKLESS_IDLE != 0 ) + eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION; +#endif /* * For internal use only. Increment the mutex held count when a mutex is @@ -3304,7 +3679,83 @@ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNC * For internal use only. Same as portYIELD_WITHIN_API() in single core FreeRTOS. * For SMP this is not defined by the port. */ -void vTaskYieldWithinAPI( void ); +#if ( configNUMBER_OF_CORES > 1 ) + void vTaskYieldWithinAPI( void ); +#endif + +/* + * This function is only intended for use when implementing a port of the scheduler + * and is only available when portCRITICAL_NESTING_IN_TCB is set to 1 or configNUMBER_OF_CORES + * is greater than 1. This function can be used in the implementation of portENTER_CRITICAL + * if port wants to maintain critical nesting count in TCB in single core FreeRTOS. + * It should be used in the implementation of portENTER_CRITICAL if port is running a + * multiple core FreeRTOS. + */ +#if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) || ( configNUMBER_OF_CORES > 1 ) ) + void vTaskEnterCritical( void ); +#endif + +/* + * This function is only intended for use when implementing a port of the scheduler + * and is only available when portCRITICAL_NESTING_IN_TCB is set to 1 or configNUMBER_OF_CORES + * is greater than 1. This function can be used in the implementation of portEXIT_CRITICAL + * if port wants to maintain critical nesting count in TCB in single core FreeRTOS. + * It should be used in the implementation of portEXIT_CRITICAL if port is running a + * multiple core FreeRTOS. + */ +#if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) || ( configNUMBER_OF_CORES > 1 ) ) + void vTaskExitCritical( void ); +#endif + +/* + * This function is only intended for use when implementing a port of the scheduler + * and is only available when configNUMBER_OF_CORES is greater than 1. This function + * should be used in the implementation of portENTER_CRITICAL_FROM_ISR if port is + * running a multiple core FreeRTOS. + */ +#if ( configNUMBER_OF_CORES > 1 ) + UBaseType_t vTaskEnterCriticalFromISR( void ); +#endif + +/* + * This function is only intended for use when implementing a port of the scheduler + * and is only available when configNUMBER_OF_CORES is greater than 1. This function + * should be used in the implementation of portEXIT_CRITICAL_FROM_ISR if port is + * running a multiple core FreeRTOS. + */ +#if ( configNUMBER_OF_CORES > 1 ) + void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus ); +#endif + +#if ( portUSING_MPU_WRAPPERS == 1 ) + +/* + * For internal use only. Get MPU settings associated with a task. + */ + xMPU_SETTINGS * xTaskGetMPUSettings( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + +#endif /* portUSING_MPU_WRAPPERS */ + + +#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) ) + +/* + * For internal use only. Grant/Revoke a task's access to a kernel object. + */ + void vGrantAccessToKernelObject( TaskHandle_t xExternalTaskHandle, + int32_t lExternalKernelObjectHandle ) PRIVILEGED_FUNCTION; + void vRevokeAccessToKernelObject( TaskHandle_t xExternalTaskHandle, + int32_t lExternalKernelObjectHandle ) PRIVILEGED_FUNCTION; + +/* + * For internal use only. Grant/Revoke a task's access to a kernel object. + */ + void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle, + int32_t lInternalIndexOfKernelObject ) PRIVILEGED_FUNCTION; + void vPortRevokeAccessToKernelObject( TaskHandle_t xInternalTaskHandle, + int32_t lInternalIndexOfKernelObject ) PRIVILEGED_FUNCTION; + +#endif /* #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) ) */ /* *INDENT-OFF* */ #ifdef __cplusplus diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/timers.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/timers.h index 5604cdd91e..bc4dca6a0d 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/timers.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/timers.h @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -32,10 +38,8 @@ #error "include FreeRTOS.h must appear in source files before include timers.h" #endif -/*lint -save -e537 This headers are only multiply included if the application code - * happens to also be including task.h. */ #include "task.h" -/*lint -restore */ + /* *INDENT-OFF* */ #ifdef __cplusplus @@ -86,13 +90,13 @@ typedef void (* TimerCallbackFunction_t)( TimerHandle_t xTimer ); * Defines the prototype to which functions used with the * xTimerPendFunctionCallFromISR() function must conform. */ -typedef void (* PendedFunction_t)( void *, - uint32_t ); +typedef void (* PendedFunction_t)( void * arg1, + uint32_t arg2 ); /** * TimerHandle_t xTimerCreate( const char * const pcTimerName, * TickType_t xTimerPeriodInTicks, - * UBaseType_t uxAutoReload, + * BaseType_t xAutoReload, * void * pvTimerID, * TimerCallbackFunction_t pxCallbackFunction ); * @@ -125,9 +129,9 @@ typedef void (* PendedFunction_t)( void *, * to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than or * equal to 1000. Time timer period must be greater than 0. * - * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will + * @param xAutoReload If xAutoReload is set to pdTRUE then the timer will * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter. - * If uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and + * If xAutoReload is set to pdFALSE then the timer will be a one-shot timer and * enter the dormant state after it expires. * * @param pvTimerID An identifier that is assigned to the timer being created. @@ -190,11 +194,11 @@ typedef void (* PendedFunction_t)( void *, * // the scheduler starts. * for( x = 0; x < NUM_TIMERS; x++ ) * { - * xTimers[ x ] = xTimerCreate( "Timer", // Just a text name, not used by the kernel. - * ( 100 * x ), // The timer period in ticks. - * pdTRUE, // The timers will auto-reload themselves when they expire. - * ( void * ) x, // Assign each timer a unique id equal to its array index. - * vTimerCallback // Each timer calls the same callback when it expires. + * xTimers[ x ] = xTimerCreate( "Timer", // Just a text name, not used by the kernel. + * ( 100 * ( x + 1 ) ), // The timer period in ticks. + * pdTRUE, // The timers will auto-reload themselves when they expire. + * ( void * ) x, // Assign each timer a unique id equal to its array index. + * vTimerCallback // Each timer calls the same callback when it expires. * ); * * if( xTimers[ x ] == NULL ) @@ -227,9 +231,9 @@ typedef void (* PendedFunction_t)( void *, * @endverbatim */ #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - TimerHandle_t xTimerCreate( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, - const UBaseType_t uxAutoReload, + const BaseType_t xAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION; #endif @@ -237,7 +241,7 @@ typedef void (* PendedFunction_t)( void *, /** * TimerHandle_t xTimerCreateStatic(const char * const pcTimerName, * TickType_t xTimerPeriodInTicks, - * UBaseType_t uxAutoReload, + * BaseType_t xAutoReload, * void * pvTimerID, * TimerCallbackFunction_t pxCallbackFunction, * StaticTimer_t *pxTimerBuffer ); @@ -271,9 +275,9 @@ typedef void (* PendedFunction_t)( void *, * to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than or * equal to 1000. The timer period must be greater than 0. * - * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will + * @param xAutoReload If xAutoReload is set to pdTRUE then the timer will * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter. - * If uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and + * If xAutoReload is set to pdFALSE then the timer will be a one-shot timer and * enter the dormant state after it expires. * * @param pvTimerID An identifier that is assigned to the timer being created. @@ -357,9 +361,9 @@ typedef void (* PendedFunction_t)( void *, * @endverbatim */ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) - TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, - const UBaseType_t uxAutoReload, + const BaseType_t xAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, StaticTimer_t * pxTimerBuffer ) PRIVILEGED_FUNCTION; @@ -1196,10 +1200,12 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; * } * @endverbatim */ -BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, - void * pvParameter1, - uint32_t ulParameter2, - BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +#if ( INCLUDE_xTimerPendFunctionCall == 1 ) + BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, + void * pvParameter1, + uint32_t ulParameter2, + BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +#endif /** * BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, @@ -1233,10 +1239,12 @@ BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, * timer daemon task, otherwise pdFALSE is returned. * */ -BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, - void * pvParameter1, - uint32_t ulParameter2, - TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +#if ( INCLUDE_xTimerPendFunctionCall == 1 ) + BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, + void * pvParameter1, + uint32_t ulParameter2, + TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +#endif /** * const char * const pcTimerGetName( TimerHandle_t xTimer ); @@ -1247,10 +1255,10 @@ BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, * * @return The name assigned to the timer specified by the xTimer parameter. */ -const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /** - * void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload ); + * void vTimerSetReloadMode( TimerHandle_t xTimer, const BaseType_t xAutoReload ); * * Updates a timer to be either an auto-reload timer, in which case the timer * automatically resets itself each time it expires, or a one-shot timer, in @@ -1258,14 +1266,28 @@ const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*lint * * @param xTimer The handle of the timer being updated. * - * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will + * @param xAutoReload If xAutoReload is set to pdTRUE then the timer will * expire repeatedly with a frequency set by the timer's period (see the * xTimerPeriodInTicks parameter of the xTimerCreate() API function). If - * uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and + * xAutoReload is set to pdFALSE then the timer will be a one-shot timer and * enter the dormant state after it expires. */ void vTimerSetReloadMode( TimerHandle_t xTimer, - const UBaseType_t uxAutoReload ) PRIVILEGED_FUNCTION; + const BaseType_t xAutoReload ) PRIVILEGED_FUNCTION; + +/** + * BaseType_t xTimerGetReloadMode( TimerHandle_t xTimer ); + * + * Queries a timer to determine if it is an auto-reload timer, in which case the timer + * automatically resets itself each time it expires, or a one-shot timer, in + * which case the timer will only expire once unless it is manually restarted. + * + * @param xTimer The handle of the timer being queried. + * + * @return If the timer is an auto-reload timer then pdTRUE is returned, otherwise + * pdFALSE is returned. + */ +BaseType_t xTimerGetReloadMode( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /** * UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer ); @@ -1317,7 +1339,7 @@ TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; * * @param xTimer The timer for which to retrieve the buffer. * - * @param ppxTimerBuffer Used to return a pointer to the timers's data + * @param ppxTaskBuffer Used to return a pointer to the timers's data * structure buffer. * * @return pdTRUE if the buffer was retrieved, pdFALSE otherwise. @@ -1326,6 +1348,7 @@ TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; BaseType_t xTimerGetStaticBuffer( TimerHandle_t xTimer, StaticTimer_t ** ppxTimerBuffer ) PRIVILEGED_FUNCTION; #endif /* configSUPPORT_STATIC_ALLOCATION */ + /* * Functions beyond this part are not part of the public API and are intended * for use by the kernel only. @@ -1354,7 +1377,6 @@ BaseType_t xTimerGenericCommandFromISR( TimerHandle_t xTimer, ( ( xCommandID ) < tmrFIRST_FROM_ISR_COMMAND ? \ xTimerGenericCommandFromTask( xTimer, xCommandID, xOptionalValue, pxHigherPriorityTaskWoken, xTicksToWait ) : \ xTimerGenericCommandFromISR( xTimer, xCommandID, xOptionalValue, pxHigherPriorityTaskWoken, xTicksToWait ) ) - #if ( configUSE_TRACE_FACILITY == 1 ) void vTimerSetTimerNumber( TimerHandle_t xTimer, UBaseType_t uxTimerNumber ) PRIVILEGED_FUNCTION; @@ -1363,20 +1385,39 @@ BaseType_t xTimerGenericCommandFromISR( TimerHandle_t xTimer, #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) - /** - * task.h - *
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, StackType_t ** ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) 
- * - * This function is used to provide a statically allocated block of memory to FreeRTOS to hold the Timer 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 ppxTimerTaskTCBBuffer A handle to a statically allocated TCB buffer - * @param ppxTimerTaskStackBuffer A handle to a statically allocated Stack buffer for thie idle task - * @param pulTimerTaskStackSize A pointer to the number of elements that will fit in the allocated stack buffer - */ +/** + * task.h + * @code{c} + * void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, StackType_t ** ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) + * @endcode + * + * This function is used to provide a statically allocated block of memory to FreeRTOS to hold the Timer 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 ppxTimerTaskTCBBuffer A handle to a statically allocated TCB buffer + * @param ppxTimerTaskStackBuffer A handle to a statically allocated Stack buffer for the idle task + * @param pulTimerTaskStackSize A pointer to the number of elements that will fit in the allocated stack buffer + */ void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, - StackType_t ** ppxTimerTaskStackBuffer, - uint32_t * pulTimerTaskStackSize ); + StackType_t ** ppxTimerTaskStackBuffer, + uint32_t * pulTimerTaskStackSize ); + +#endif + +#if ( configUSE_DAEMON_TASK_STARTUP_HOOK != 0 ) + +/** + * timers.h + * @code{c} + * void vApplicationDaemonTaskStartupHook( void ); + * @endcode + * + * This hook function is called form the timer task once when the task starts running. + */ + /* 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 vApplicationDaemonTaskStartupHook( void ); #endif diff --git a/components/freertos/FreeRTOS-Kernel-SMP/list.c b/components/freertos/FreeRTOS-Kernel-SMP/list.c index c679709f73..e700b981a3 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/list.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/list.c @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -35,11 +41,10 @@ #include "FreeRTOS.h" #include "list.h" -/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified - * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be +/* The MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be * defined for the header files above, but not in this file, in order to * generate the correct privileged Vs unprivileged linkage and placement. */ -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*----------------------------------------------------------- * PUBLIC LIST API documented in list.h @@ -47,10 +52,14 @@ void vListInitialise( List_t * const pxList ) { + traceENTER_vListInitialise( pxList ); + /* The list structure contains a list item which is used to mark the * end of the list. To initialise the list the list end is inserted * as the only list entry. */ - pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); + + listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) ); /* The list end value is the highest possible value in the list to * ensure it remains at the end of the list. */ @@ -58,8 +67,17 @@ void vListInitialise( List_t * const pxList ) /* The list end next and previous pointers point to itself so we know * when the list is empty. */ - pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ - pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); + pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); + + /* Initialize the remaining fields of xListEnd when it is a proper ListItem_t */ + #if ( configUSE_MINI_LIST_ITEM == 0 ) + { + pxList->xListEnd.pvOwner = NULL; + pxList->xListEnd.pxContainer = NULL; + listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) ); + } + #endif pxList->uxNumberOfItems = ( UBaseType_t ) 0U; @@ -67,11 +85,15 @@ void vListInitialise( List_t * const pxList ) * configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ); listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ); + + traceRETURN_vListInitialise(); } /*-----------------------------------------------------------*/ void vListInitialiseItem( ListItem_t * const pxItem ) { + traceENTER_vListInitialiseItem( pxItem ); + /* Make sure the list item is not recorded as being on a list. */ pxItem->pxContainer = NULL; @@ -79,6 +101,8 @@ void vListInitialiseItem( ListItem_t * const pxItem ) * configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); + + traceRETURN_vListInitialiseItem(); } /*-----------------------------------------------------------*/ @@ -87,6 +111,8 @@ void vListInsertEnd( List_t * const pxList, { ListItem_t * const pxIndex = pxList->pxIndex; + traceENTER_vListInsertEnd( pxList, pxNewListItem ); + /* Only effective when configASSERT() is also defined, these tests may catch * the list data structures being overwritten in memory. They will not catch * data errors caused by incorrect configuration or use of FreeRTOS. */ @@ -109,6 +135,8 @@ void vListInsertEnd( List_t * const pxList, pxNewListItem->pxContainer = pxList; ( pxList->uxNumberOfItems )++; + + traceRETURN_vListInsertEnd(); } /*-----------------------------------------------------------*/ @@ -118,6 +146,8 @@ void vListInsert( List_t * const pxList, ListItem_t * pxIterator; const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; + traceENTER_vListInsert( pxList, pxNewListItem ); + /* Only effective when configASSERT() is also defined, these tests may catch * the list data structures being overwritten in memory. They will not catch * data errors caused by incorrect configuration or use of FreeRTOS. */ @@ -163,7 +193,7 @@ void vListInsert( List_t * const pxList, * configMAX_SYSCALL_INTERRUPT_PRIORITY. **********************************************************************/ - for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. *//*lint !e440 The iterator moves to a different value, not xValueOfInsertion. */ + for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) { /* There is nothing to do here, just iterating to the wanted * insertion position. */ @@ -180,15 +210,21 @@ void vListInsert( List_t * const pxList, pxNewListItem->pxContainer = pxList; ( pxList->uxNumberOfItems )++; + + traceRETURN_vListInsert(); } /*-----------------------------------------------------------*/ UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) { -/* The list item knows which list it is in. Obtain the list from the list - * item. */ + /* The list item knows which list it is in. Obtain the list from the list + * item. */ List_t * const pxList = pxItemToRemove->pxContainer; + traceENTER_uxListRemove( pxItemToRemove ); + + + pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; @@ -208,6 +244,8 @@ UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) pxItemToRemove->pxContainer = NULL; ( pxList->uxNumberOfItems )--; + traceRETURN_uxListRemove( pxList->uxNumberOfItems ); + return pxList->uxNumberOfItems; } /*-----------------------------------------------------------*/ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/queue.c b/components/freertos/FreeRTOS-Kernel-SMP/queue.c index 51895e5a23..ecca2a4a0d 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/queue.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/queue.c @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -40,11 +46,10 @@ #include "croutine.h" #endif -/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified - * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined +/* The MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined * for the header files above, but not in this file, in order to generate the * correct privileged Vs unprivileged linkage and placement. */ -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /* Constants used with the cRxLock and cTxLock structure members. */ @@ -66,14 +71,14 @@ typedef struct QueuePointers { - int8_t * pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ - int8_t * pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */ + int8_t * pcTail; /**< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ + int8_t * pcReadFrom; /**< Points to the last place that a queued item was read from when the structure is used as a queue. */ } QueuePointers_t; typedef struct SemaphoreData { - TaskHandle_t xMutexHolder; /*< The handle of the task that holds the mutex. */ - UBaseType_t uxRecursiveCallCount; /*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */ + TaskHandle_t xMutexHolder; /**< The handle of the task that holds the mutex. */ + UBaseType_t uxRecursiveCallCount; /**< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */ } SemaphoreData_t; /* Semaphores do not actually store or copy data, so have an item size of @@ -87,7 +92,11 @@ typedef struct SemaphoreData * performed just because a higher priority task has been woken. */ #define queueYIELD_IF_USING_PREEMPTION() #else - #define queueYIELD_IF_USING_PREEMPTION() vTaskYieldWithinAPI() + #if ( configNUMBER_OF_CORES == 1 ) + #define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() + #else /* #if ( configNUMBER_OF_CORES == 1 ) */ + #define queueYIELD_IF_USING_PREEMPTION() vTaskYieldWithinAPI() + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ #endif /* @@ -97,27 +106,27 @@ typedef struct SemaphoreData */ typedef struct QueueDefinition /* The old naming convention is used to prevent breaking kernel aware debuggers. */ { - int8_t * pcHead; /*< Points to the beginning of the queue storage area. */ - int8_t * pcWriteTo; /*< Points to the free next place in the storage area. */ + int8_t * pcHead; /**< Points to the beginning of the queue storage area. */ + int8_t * pcWriteTo; /**< Points to the free next place in the storage area. */ union { - QueuePointers_t xQueue; /*< Data required exclusively when this structure is used as a queue. */ - SemaphoreData_t xSemaphore; /*< Data required exclusively when this structure is used as a semaphore. */ + QueuePointers_t xQueue; /**< Data required exclusively when this structure is used as a queue. */ + SemaphoreData_t xSemaphore; /**< Data required exclusively when this structure is used as a semaphore. */ } u; - List_t xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ - List_t xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ + List_t xTasksWaitingToSend; /**< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ + List_t xTasksWaitingToReceive; /**< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ - volatile UBaseType_t uxMessagesWaiting; /*< The number of items currently in the queue. */ - UBaseType_t uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */ - UBaseType_t uxItemSize; /*< The size of each items that the queue will hold. */ + volatile UBaseType_t uxMessagesWaiting; /**< The number of items currently in the queue. */ + UBaseType_t uxLength; /**< The length of the queue defined as the number of items it will hold, not the number of bytes. */ + UBaseType_t uxItemSize; /**< The size of each items that the queue will hold. */ - volatile int8_t cRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ - volatile int8_t cTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + volatile int8_t cRxLock; /**< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + volatile int8_t cTxLock; /**< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */ + uint8_t ucStaticallyAllocated; /**< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */ #endif #if ( configUSE_QUEUE_SETS == 1 ) @@ -147,7 +156,7 @@ typedef xQUEUE Queue_t; * more user friendly. */ typedef struct QUEUE_REGISTRY_ITEM { - const char * pcQueueName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const char * pcQueueName; QueueHandle_t xHandle; } xQueueRegistryItem; @@ -159,6 +168,10 @@ typedef xQUEUE Queue_t; /* The queue registry is simply an array of QueueRegistryItem_t structures. * The pcQueueName member of a structure being NULL is indicative of the * array position being vacant. */ + +/* MISRA Ref 8.4.2 [Declaration shall be visible] */ +/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-84 */ +/* coverity[misra_c_2012_rule_8_4_violation] */ PRIVILEGED_DATA QueueRegistryItem_t xQueueRegistry[ configQUEUE_REGISTRY_SIZE ]; #endif /* configQUEUE_REGISTRY_SIZE */ @@ -259,36 +272,79 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, } \ } \ taskEXIT_CRITICAL() + +/* + * Macro to increment cTxLock member of the queue data structure. It is + * capped at the number of tasks in the system as we cannot unblock more + * tasks than the number of tasks in the system. + */ +#define prvIncrementQueueTxLock( pxQueue, cTxLock ) \ + do { \ + const UBaseType_t uxNumberOfTasks = uxTaskGetNumberOfTasks(); \ + if( ( UBaseType_t ) ( cTxLock ) < uxNumberOfTasks ) \ + { \ + configASSERT( ( cTxLock ) != queueINT8_MAX ); \ + ( pxQueue )->cTxLock = ( int8_t ) ( ( cTxLock ) + ( int8_t ) 1 ); \ + } \ + } while( 0 ) + +/* + * Macro to increment cRxLock member of the queue data structure. It is + * capped at the number of tasks in the system as we cannot unblock more + * tasks than the number of tasks in the system. + */ +#define prvIncrementQueueRxLock( pxQueue, cRxLock ) \ + do { \ + const UBaseType_t uxNumberOfTasks = uxTaskGetNumberOfTasks(); \ + if( ( UBaseType_t ) ( cRxLock ) < uxNumberOfTasks ) \ + { \ + configASSERT( ( cRxLock ) != queueINT8_MAX ); \ + ( pxQueue )->cRxLock = ( int8_t ) ( ( cRxLock ) + ( int8_t ) 1 ); \ + } \ + } while( 0 ) /*-----------------------------------------------------------*/ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) { + BaseType_t xReturn = pdPASS; Queue_t * const pxQueue = xQueue; + traceENTER_xQueueGenericReset( xQueue, xNewQueue ); + configASSERT( pxQueue ); - taskENTER_CRITICAL(); + if( ( pxQueue != NULL ) && + ( pxQueue->uxLength >= 1U ) && + /* Check for multiplication overflow. */ + ( ( SIZE_MAX / pxQueue->uxLength ) >= pxQueue->uxItemSize ) ) { - pxQueue->u.xQueue.pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */ - pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U; - pxQueue->pcWriteTo = pxQueue->pcHead; - pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - 1U ) * pxQueue->uxItemSize ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */ - pxQueue->cRxLock = queueUNLOCKED; - pxQueue->cTxLock = queueUNLOCKED; - - if( xNewQueue == pdFALSE ) + taskENTER_CRITICAL(); { - /* If there are tasks blocked waiting to read from the queue, then - * the tasks will remain blocked as after this function exits the queue - * will still be empty. If there are tasks blocked waiting to write to - * the queue, then one should be unblocked as after this function exits - * it will be possible to write to it. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + pxQueue->u.xQueue.pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize ); + pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U; + pxQueue->pcWriteTo = pxQueue->pcHead; + pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - 1U ) * pxQueue->uxItemSize ); + pxQueue->cRxLock = queueUNLOCKED; + pxQueue->cTxLock = queueUNLOCKED; + + if( xNewQueue == pdFALSE ) { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + /* If there are tasks blocked waiting to read from the queue, then + * the tasks will remain blocked as after this function exits the queue + * will still be empty. If there are tasks blocked waiting to write to + * the queue, then one should be unblocked as after this function exits + * it will be possible to write to it. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) { - queueYIELD_IF_USING_PREEMPTION(); + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } else { @@ -297,21 +353,25 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, } else { - mtCOVERAGE_TEST_MARKER(); + /* Ensure the event queues start in the correct state. */ + vListInitialise( &( pxQueue->xTasksWaitingToSend ) ); + vListInitialise( &( pxQueue->xTasksWaitingToReceive ) ); } } - else - { - /* Ensure the event queues start in the correct state. */ - vListInitialise( &( pxQueue->xTasksWaitingToSend ) ); - vListInitialise( &( pxQueue->xTasksWaitingToReceive ) ); - } + taskEXIT_CRITICAL(); } - taskEXIT_CRITICAL(); + else + { + xReturn = pdFAIL; + } + + configASSERT( xReturn != pdFAIL ); /* A value is returned for calling semantic consistency with previous * versions. */ - return pdPASS; + traceRETURN_xQueueGenericReset( xReturn ); + + return xReturn; } /*-----------------------------------------------------------*/ @@ -323,20 +383,23 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, StaticQueue_t * pxStaticQueue, const uint8_t ucQueueType ) { - Queue_t * pxNewQueue; + Queue_t * pxNewQueue = NULL; - configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); + traceENTER_xQueueGenericCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxStaticQueue, ucQueueType ); /* The StaticQueue_t structure and the queue storage area must be * supplied. */ - configASSERT( pxStaticQueue != NULL ); + configASSERT( pxStaticQueue ); - /* A queue storage area should be provided if the item size is not 0, and - * should not be provided if the item size is 0. */ - configASSERT( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) ); - configASSERT( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) ); + if( ( uxQueueLength > ( UBaseType_t ) 0 ) && + ( pxStaticQueue != NULL ) && - #if ( configASSERT_DEFINED == 1 ) + /* A queue storage area should be provided if the item size is not 0, and + * should not be provided if the item size is 0. */ + ( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0U ) ) ) && + ( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0U ) ) ) ) + { + #if ( configASSERT_DEFINED == 1 ) { /* Sanity check that the size of the structure used to declare a * variable of type StaticQueue_t or StaticSemaphore_t equals the size of @@ -345,34 +408,37 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, /* This assertion cannot be branch covered in unit tests */ configASSERT( xSize == sizeof( Queue_t ) ); /* LCOV_EXCL_BR_LINE */ - ( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */ + ( void ) xSize; /* Prevent unused variable warning when configASSERT() is not defined. */ } - #endif /* configASSERT_DEFINED */ + #endif /* configASSERT_DEFINED */ - /* The address of a statically allocated queue was passed in, use it. - * The address of a statically allocated storage area was also passed in - * but is already set. */ - pxNewQueue = ( Queue_t * ) pxStaticQueue; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */ + /* The address of a statically allocated queue was passed in, use it. + * The address of a statically allocated storage area was also passed in + * but is already set. */ + /* MISRA Ref 11.3.1 [Misaligned access] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */ + /* coverity[misra_c_2012_rule_11_3_violation] */ + pxNewQueue = ( Queue_t * ) pxStaticQueue; - if( pxNewQueue != NULL ) - { #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - { - /* Queues can be allocated wither statically or dynamically, so - * note this queue was allocated statically in case the queue is - * later deleted. */ - pxNewQueue->ucStaticallyAllocated = pdTRUE; - } + { + /* Queues can be allocated wither statically or dynamically, so + * note this queue was allocated statically in case the queue is + * later deleted. */ + pxNewQueue->ucStaticallyAllocated = pdTRUE; + } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue ); } else { - traceQUEUE_CREATE_FAILED( ucQueueType ); + configASSERT( pxNewQueue ); mtCOVERAGE_TEST_MARKER(); } + traceRETURN_xQueueGenericCreateStatic( pxNewQueue ); + return pxNewQueue; } @@ -388,6 +454,8 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xReturn; Queue_t * const pxQueue = xQueue; + traceENTER_xQueueGenericGetStaticBuffers( xQueue, ppucQueueStorage, ppxStaticQueue ); + configASSERT( pxQueue ); configASSERT( ppxStaticQueue ); @@ -401,6 +469,9 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, *ppucQueueStorage = ( uint8_t * ) pxQueue->pcHead; } + /* MISRA Ref 11.3.1 [Misaligned access] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */ + /* coverity[misra_c_2012_rule_11_3_violation] */ *ppxStaticQueue = ( StaticQueue_t * ) pxQueue; xReturn = pdTRUE; } @@ -422,6 +493,8 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + traceRETURN_xQueueGenericGetStaticBuffers( xReturn ); + return xReturn; } @@ -434,58 +507,60 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) { - Queue_t * pxNewQueue; + Queue_t * pxNewQueue = NULL; size_t xQueueSizeInBytes; uint8_t * pucQueueStorage; - configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); + traceENTER_xQueueGenericCreate( uxQueueLength, uxItemSize, ucQueueType ); - /* Allocate enough space to hold the maximum number of items that - * can be in the queue at any time. It is valid for uxItemSize to be - * zero in the case the queue is used as a semaphore. */ - xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - - /* Check for multiplication overflow. */ - configASSERT( ( uxItemSize == 0 ) || ( uxQueueLength == ( xQueueSizeInBytes / uxItemSize ) ) ); - - /* Check for addition overflow. */ - configASSERT( ( sizeof( Queue_t ) + xQueueSizeInBytes ) > xQueueSizeInBytes ); - - /* Allocate the queue and storage area. Justification for MISRA - * deviation as follows: pvPortMalloc() always ensures returned memory - * blocks are aligned per the requirements of the MCU stack. In this case - * pvPortMalloc() must return a pointer that is guaranteed to meet the - * alignment requirements of the Queue_t structure - which in this case - * is an int8_t *. Therefore, whenever the stack alignment requirements - * are greater than or equal to the pointer to char requirements the cast - * is safe. In other cases alignment requirements are not strict (one or - * two bytes). */ - pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); /*lint !e9087 !e9079 see comment above. */ - - if( pxNewQueue != NULL ) + if( ( uxQueueLength > ( UBaseType_t ) 0 ) && + /* Check for multiplication overflow. */ + ( ( SIZE_MAX / uxQueueLength ) >= uxItemSize ) && + /* Check for addition overflow. */ + ( ( UBaseType_t ) ( SIZE_MAX - sizeof( Queue_t ) ) >= ( uxQueueLength * uxItemSize ) ) ) { - /* Jump past the queue structure to find the location of the queue - * storage area. */ - pucQueueStorage = ( uint8_t * ) pxNewQueue; - pucQueueStorage += sizeof( Queue_t ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */ + /* Allocate enough space to hold the maximum number of items that + * can be in the queue at any time. It is valid for uxItemSize to be + * zero in the case the queue is used as a semaphore. */ + xQueueSizeInBytes = ( size_t ) ( ( size_t ) uxQueueLength * ( size_t ) uxItemSize ); - #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + /* MISRA Ref 11.5.1 [Malloc memory assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); + + if( pxNewQueue != NULL ) + { + /* Jump past the queue structure to find the location of the queue + * storage area. */ + pucQueueStorage = ( uint8_t * ) pxNewQueue; + pucQueueStorage += sizeof( Queue_t ); + + #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) { /* Queues can be created either statically or dynamically, so * note this task was created dynamically in case it is later * deleted. */ pxNewQueue->ucStaticallyAllocated = pdFALSE; } - #endif /* configSUPPORT_STATIC_ALLOCATION */ + #endif /* configSUPPORT_STATIC_ALLOCATION */ - prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue ); + prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue ); + } + else + { + traceQUEUE_CREATE_FAILED( ucQueueType ); + mtCOVERAGE_TEST_MARKER(); + } } else { - traceQUEUE_CREATE_FAILED( ucQueueType ); + configASSERT( pxNewQueue ); mtCOVERAGE_TEST_MARKER(); } + traceRETURN_xQueueGenericCreate( pxNewQueue ); + return pxNewQueue; } @@ -523,15 +598,15 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, ( void ) xQueueGenericReset( pxNewQueue, pdTRUE ); #if ( configUSE_TRACE_FACILITY == 1 ) - { - pxNewQueue->ucQueueType = ucQueueType; - } + { + pxNewQueue->ucQueueType = ucQueueType; + } #endif /* configUSE_TRACE_FACILITY */ #if ( configUSE_QUEUE_SETS == 1 ) - { - pxNewQueue->pxQueueSetContainer = NULL; - } + { + pxNewQueue->pxQueueSetContainer = NULL; + } #endif /* configUSE_QUEUE_SETS */ traceQUEUE_CREATE( pxNewQueue ); @@ -575,9 +650,13 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, QueueHandle_t xNewQueue; const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0; + traceENTER_xQueueCreateMutex( ucQueueType ); + xNewQueue = xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType ); prvInitialiseMutex( ( Queue_t * ) xNewQueue ); + traceRETURN_xQueueCreateMutex( xNewQueue ); + return xNewQueue; } @@ -592,6 +671,8 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, QueueHandle_t xNewQueue; const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0; + traceENTER_xQueueCreateMutexStatic( ucQueueType, pxStaticQueue ); + /* Prevent compiler warnings about unused parameters if * configUSE_TRACE_FACILITY does not equal 1. */ ( void ) ucQueueType; @@ -599,6 +680,8 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, xNewQueue = xQueueGenericCreateStatic( uxMutexLength, uxMutexSize, NULL, pxStaticQueue, ucQueueType ); prvInitialiseMutex( ( Queue_t * ) xNewQueue ); + traceRETURN_xQueueCreateMutexStatic( xNewQueue ); + return xNewQueue; } @@ -612,6 +695,8 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, TaskHandle_t pxReturn; Queue_t * const pxSemaphore = ( Queue_t * ) xSemaphore; + traceENTER_xQueueGetMutexHolder( xSemaphore ); + configASSERT( xSemaphore ); /* This function is called by xSemaphoreGetMutexHolder(), and should not @@ -632,8 +717,10 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, } taskEXIT_CRITICAL(); + traceRETURN_xQueueGetMutexHolder( pxReturn ); + return pxReturn; - } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */ + } #endif /* if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */ /*-----------------------------------------------------------*/ @@ -644,6 +731,8 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, { TaskHandle_t pxReturn; + traceENTER_xQueueGetMutexHolderFromISR( xSemaphore ); + configASSERT( xSemaphore ); /* Mutexes cannot be used in interrupt service routines, so the mutex @@ -658,8 +747,10 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, pxReturn = NULL; } + traceRETURN_xQueueGetMutexHolderFromISR( pxReturn ); + return pxReturn; - } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */ + } #endif /* if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */ /*-----------------------------------------------------------*/ @@ -671,6 +762,8 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, BaseType_t xReturn; Queue_t * const pxMutex = ( Queue_t * ) xMutex; + traceENTER_xQueueGiveMutexRecursive( xMutex ); + configASSERT( pxMutex ); /* If this is the task that holds the mutex then xMutexHolder will not @@ -713,6 +806,8 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ); } + traceRETURN_xQueueGiveMutexRecursive( xReturn ); + return xReturn; } @@ -727,6 +822,8 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, BaseType_t xReturn; Queue_t * const pxMutex = ( Queue_t * ) xMutex; + traceENTER_xQueueTakeMutexRecursive( xMutex, xTicksToWait ); + configASSERT( pxMutex ); /* Comments regarding mutual exclusion as per those within @@ -756,6 +853,8 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, } } + traceRETURN_xQueueTakeMutexRecursive( xReturn ); + return xReturn; } @@ -768,24 +867,34 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxInitialCount, StaticQueue_t * pxStaticQueue ) { - QueueHandle_t xHandle; + QueueHandle_t xHandle = NULL; - configASSERT( uxMaxCount != 0 ); - configASSERT( uxInitialCount <= uxMaxCount ); + traceENTER_xQueueCreateCountingSemaphoreStatic( uxMaxCount, uxInitialCount, pxStaticQueue ); - xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); - - if( xHandle != NULL ) + if( ( uxMaxCount != 0U ) && + ( uxInitialCount <= uxMaxCount ) ) { - ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; + xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); - traceCREATE_COUNTING_SEMAPHORE(); + if( xHandle != NULL ) + { + ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; + + traceCREATE_COUNTING_SEMAPHORE(); + } + else + { + traceCREATE_COUNTING_SEMAPHORE_FAILED(); + } } else { - traceCREATE_COUNTING_SEMAPHORE_FAILED(); + configASSERT( xHandle ); + mtCOVERAGE_TEST_MARKER(); } + traceRETURN_xQueueCreateCountingSemaphoreStatic( xHandle ); + return xHandle; } @@ -797,24 +906,34 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) { - QueueHandle_t xHandle; + QueueHandle_t xHandle = NULL; - configASSERT( uxMaxCount != 0 ); - configASSERT( uxInitialCount <= uxMaxCount ); + traceENTER_xQueueCreateCountingSemaphore( uxMaxCount, uxInitialCount ); - xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); - - if( xHandle != NULL ) + if( ( uxMaxCount != 0U ) && + ( uxInitialCount <= uxMaxCount ) ) { - ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; + xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); - traceCREATE_COUNTING_SEMAPHORE(); + if( xHandle != NULL ) + { + ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; + + traceCREATE_COUNTING_SEMAPHORE(); + } + else + { + traceCREATE_COUNTING_SEMAPHORE_FAILED(); + } } else { - traceCREATE_COUNTING_SEMAPHORE_FAILED(); + configASSERT( xHandle ); + mtCOVERAGE_TEST_MARKER(); } + traceRETURN_xQueueCreateCountingSemaphore( xHandle ); + return xHandle; } @@ -830,18 +949,17 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, TimeOut_t xTimeOut; Queue_t * const pxQueue = xQueue; + traceENTER_xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, xCopyPosition ); + configASSERT( pxQueue ); configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - { - configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); - } + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } #endif - /*lint -save -e904 This function relaxes the coding standard somewhat to - * allow return statements within the function itself. This is done in the - * interest of execution time efficiency. */ for( ; ; ) { taskENTER_CRITICAL(); @@ -855,69 +973,34 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, traceQUEUE_SEND( pxQueue ); #if ( configUSE_QUEUE_SETS == 1 ) + { + const UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting; + + xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + if( pxQueue->pxQueueSetContainer != NULL ) { - const UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting; - - xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); - - if( pxQueue->pxQueueSetContainer != NULL ) + if( ( xCopyPosition == queueOVERWRITE ) && ( uxPreviousMessagesWaiting != ( UBaseType_t ) 0 ) ) { - if( ( xCopyPosition == queueOVERWRITE ) && ( uxPreviousMessagesWaiting != ( UBaseType_t ) 0 ) ) - { - /* Do not notify the queue set as an existing item - * was overwritten in the queue so the number of items - * in the queue has not changed. */ - mtCOVERAGE_TEST_MARKER(); - } - else if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE ) - { - /* The queue is a member of a queue set, and posting - * to the queue set caused a higher priority task to - * unblock. A context switch is required. */ - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Do not notify the queue set as an existing item + * was overwritten in the queue so the number of items + * in the queue has not changed. */ + mtCOVERAGE_TEST_MARKER(); + } + else if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE ) + { + /* The queue is a member of a queue set, and posting + * to the queue set caused a higher priority task to + * unblock. A context switch is required. */ + queueYIELD_IF_USING_PREEMPTION(); } else { - /* If there was a task waiting for data to arrive on the - * queue then unblock it now. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The unblocked task has a priority higher than - * our own so yield immediately. Yes it is ok to - * do this from within the critical section - the - * kernel takes care of that. */ - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else if( xYieldRequired != pdFALSE ) - { - /* This path is a special case that will only get - * executed if the task was holding multiple mutexes - * and the mutexes were given back in an order that is - * different to that in which they were taken. */ - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + mtCOVERAGE_TEST_MARKER(); } } - #else /* configUSE_QUEUE_SETS */ + else { - xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); - /* If there was a task waiting for data to arrive on the * queue then unblock it now. */ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) @@ -925,9 +1008,9 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { /* The unblocked task has a priority higher than - * our own so yield immediately. Yes it is ok to do - * this from within the critical section - the kernel - * takes care of that. */ + * our own so yield immediately. Yes it is ok to + * do this from within the critical section - the + * kernel takes care of that. */ queueYIELD_IF_USING_PREEMPTION(); } else @@ -938,8 +1021,8 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, else if( xYieldRequired != pdFALSE ) { /* This path is a special case that will only get - * executed if the task was holding multiple mutexes and - * the mutexes were given back in an order that is + * executed if the task was holding multiple mutexes + * and the mutexes were given back in an order that is * different to that in which they were taken. */ queueYIELD_IF_USING_PREEMPTION(); } @@ -948,9 +1031,47 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, mtCOVERAGE_TEST_MARKER(); } } + } + #else /* configUSE_QUEUE_SETS */ + { + xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + /* If there was a task waiting for data to arrive on the + * queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The unblocked task has a priority higher than + * our own so yield immediately. Yes it is ok to do + * this from within the critical section - the kernel + * takes care of that. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xYieldRequired != pdFALSE ) + { + /* This path is a special case that will only get + * executed if the task was holding multiple mutexes and + * the mutexes were given back in an order that is + * different to that in which they were taken. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } #endif /* configUSE_QUEUE_SETS */ taskEXIT_CRITICAL(); + + traceRETURN_xQueueGenericSend( pdPASS ); + return pdPASS; } else @@ -964,6 +1085,8 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, /* Return to the original privilege level before exiting * the function. */ traceQUEUE_SEND_FAILED( pxQueue ); + traceRETURN_xQueueGenericSend( errQUEUE_FULL ); + return errQUEUE_FULL; } else if( xEntryTimeSet == pdFALSE ) @@ -1010,7 +1133,7 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, * is also a higher priority task in the pending ready list. */ if( xTaskResumeAll() == pdFALSE ) { - vTaskYieldWithinAPI(); + taskYIELD_WITHIN_API(); } } else @@ -1027,9 +1150,11 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, ( void ) xTaskResumeAll(); traceQUEUE_SEND_FAILED( pxQueue ); + traceRETURN_xQueueGenericSend( errQUEUE_FULL ); + return errQUEUE_FULL; } - } /*lint -restore */ + } } /*-----------------------------------------------------------*/ @@ -1042,6 +1167,8 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, UBaseType_t uxSavedInterruptStatus; Queue_t * const pxQueue = xQueue; + traceENTER_xQueueGenericSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken, xCopyPosition ); + configASSERT( pxQueue ); configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); @@ -1067,7 +1194,7 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, * read, instead return a flag to say whether a context switch is required or * not (i.e. has a task with a higher priority than us been woken by this * post). */ - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); { if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) { @@ -1088,29 +1215,24 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, if( cTxLock == queueUNLOCKED ) { #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) { - if( pxQueue->pxQueueSetContainer != NULL ) + if( ( xCopyPosition == queueOVERWRITE ) && ( uxPreviousMessagesWaiting != ( UBaseType_t ) 0 ) ) { - if( ( xCopyPosition == queueOVERWRITE ) && ( uxPreviousMessagesWaiting != ( UBaseType_t ) 0 ) ) + /* Do not notify the queue set as an existing item + * was overwritten in the queue so the number of items + * in the queue has not changed. */ + mtCOVERAGE_TEST_MARKER(); + } + else if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE ) + { + /* The queue is a member of a queue set, and posting + * to the queue set caused a higher priority task to + * unblock. A context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) { - /* Do not notify the queue set as an existing item - * was overwritten in the queue so the number of items - * in the queue has not changed. */ - mtCOVERAGE_TEST_MARKER(); - } - else if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE ) - { - /* The queue is a member of a queue set, and posting - * to the queue set caused a higher priority task to - * unblock. A context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + *pxHigherPriorityTaskWoken = pdTRUE; } else { @@ -1119,40 +1241,17 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, } else { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority so - * record that a context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + mtCOVERAGE_TEST_MARKER(); } } - #else /* configUSE_QUEUE_SETS */ + else { if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) { if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { - /* The task waiting has a higher priority so record that a - * context switch is required. */ + /* The task waiting has a higher priority so + * record that a context switch is required. */ if( pxHigherPriorityTaskWoken != NULL ) { *pxHigherPriorityTaskWoken = pdTRUE; @@ -1171,19 +1270,45 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, { mtCOVERAGE_TEST_MARKER(); } - - /* Not used in this path. */ - ( void ) uxPreviousMessagesWaiting; } + } + #else /* configUSE_QUEUE_SETS */ + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + * context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Not used in this path. */ + ( void ) uxPreviousMessagesWaiting; + } #endif /* configUSE_QUEUE_SETS */ } else { /* Increment the lock count so the task that unlocks the queue * knows that data was posted while it was locked. */ - configASSERT( cTxLock != queueINT8_MAX ); - - pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 ); + prvIncrementQueueTxLock( pxQueue, cTxLock ); } xReturn = pdPASS; @@ -1194,7 +1319,9 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, xReturn = errQUEUE_FULL; } } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); + + traceRETURN_xQueueGenericSendFromISR( xReturn ); return xReturn; } @@ -1207,6 +1334,8 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, UBaseType_t uxSavedInterruptStatus; Queue_t * const pxQueue = xQueue; + traceENTER_xQueueGiveFromISR( xQueue, pxHigherPriorityTaskWoken ); + /* Similar to xQueueGenericSendFromISR() but used with semaphores where the * item size is 0. Don't directly wake a task that was blocked on a queue * read, instead return a flag to say whether a context switch is required or @@ -1240,7 +1369,7 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); { const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; @@ -1251,9 +1380,7 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, { const int8_t cTxLock = pxQueue->cTxLock; -#ifdef ESP_PLATFORM // IDF-5384 - traceQUEUE_GIVE_FROM_ISR( pxQueue ); -#endif + traceQUEUE_SEND_FROM_ISR( pxQueue ); /* A task can only have an inherited priority if it is a mutex * holder - and if there is a mutex holder then the mutex cannot be @@ -1261,29 +1388,24 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, * can be assumed there is no mutex holder and no need to determine if * priority disinheritance is needed. Simply increase the count of * messages (semaphores) available. */ - pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1; + pxQueue->uxMessagesWaiting = ( UBaseType_t ) ( uxMessagesWaiting + ( UBaseType_t ) 1 ); /* The event list is not altered if the queue is locked. This will * be done when the queue is unlocked later. */ if( cTxLock == queueUNLOCKED ) { #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) { - if( pxQueue->pxQueueSetContainer != NULL ) + if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE ) { - if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE ) + /* The semaphore is a member of a queue set, and + * posting to the queue set caused a higher priority + * task to unblock. A context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) { - /* The semaphore is a member of a queue set, and - * posting to the queue set caused a higher priority - * task to unblock. A context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + *pxHigherPriorityTaskWoken = pdTRUE; } else { @@ -1292,40 +1414,17 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, } else { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority so - * record that a context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + mtCOVERAGE_TEST_MARKER(); } } - #else /* configUSE_QUEUE_SETS */ + else { if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) { if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { - /* The task waiting has a higher priority so record that a - * context switch is required. */ + /* The task waiting has a higher priority so + * record that a context switch is required. */ if( pxHigherPriorityTaskWoken != NULL ) { *pxHigherPriorityTaskWoken = pdTRUE; @@ -1345,28 +1444,54 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, mtCOVERAGE_TEST_MARKER(); } } + } + #else /* configUSE_QUEUE_SETS */ + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + * context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } #endif /* configUSE_QUEUE_SETS */ } else { /* Increment the lock count so the task that unlocks the queue * knows that data was posted while it was locked. */ - configASSERT( cTxLock != queueINT8_MAX ); - - pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 ); + prvIncrementQueueTxLock( pxQueue, cTxLock ); } xReturn = pdPASS; } else { -#ifdef ESP_PLATFORM // IDF-5384 - traceQUEUE_GIVE_FROM_ISR_FAILED( pxQueue ); -#endif + traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); xReturn = errQUEUE_FULL; } } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); + + traceRETURN_xQueueGiveFromISR( xReturn ); return xReturn; } @@ -1380,6 +1505,8 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, TimeOut_t xTimeOut; Queue_t * const pxQueue = xQueue; + traceENTER_xQueueReceive( xQueue, pvBuffer, xTicksToWait ); + /* Check the pointer is not NULL. */ configASSERT( ( pxQueue ) ); @@ -1389,14 +1516,11 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, /* Cannot block if the scheduler is suspended. */ #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - { - configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); - } + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } #endif - /*lint -save -e904 This function relaxes the coding standard somewhat to - * allow return statements within the function itself. This is done in the - * interest of execution time efficiency. */ for( ; ; ) { taskENTER_CRITICAL(); @@ -1410,7 +1534,7 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, /* Data available, remove one item. */ prvCopyDataFromQueue( pxQueue, pvBuffer ); traceQUEUE_RECEIVE( pxQueue ); - pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1; + pxQueue->uxMessagesWaiting = ( UBaseType_t ) ( uxMessagesWaiting - ( UBaseType_t ) 1 ); /* There is now space in the queue, were any tasks waiting to * post to the queue? If so, unblock the highest priority waiting @@ -1432,6 +1556,9 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, } taskEXIT_CRITICAL(); + + traceRETURN_xQueueReceive( pdPASS ); + return pdPASS; } else @@ -1441,7 +1568,10 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, /* The queue was empty and no block time is specified (or * the block time has expired) so leave now. */ taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + traceRETURN_xQueueReceive( errQUEUE_EMPTY ); + return errQUEUE_EMPTY; } else if( xEntryTimeSet == pdFALSE ) @@ -1479,7 +1609,7 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, if( xTaskResumeAll() == pdFALSE ) { - vTaskYieldWithinAPI(); + taskYIELD_WITHIN_API(); } else { @@ -1504,6 +1634,8 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) { traceQUEUE_RECEIVE_FAILED( pxQueue ); + traceRETURN_xQueueReceive( errQUEUE_EMPTY ); + return errQUEUE_EMPTY; } else @@ -1511,7 +1643,7 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue, mtCOVERAGE_TEST_MARKER(); } } - } /*lint -restore */ + } } /*-----------------------------------------------------------*/ @@ -1526,6 +1658,8 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, BaseType_t xInheritanceOccurred = pdFALSE; #endif + traceENTER_xQueueSemaphoreTake( xQueue, xTicksToWait ); + /* Check the queue pointer is not NULL. */ configASSERT( ( pxQueue ) ); @@ -1535,14 +1669,11 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, /* Cannot block if the scheduler is suspended. */ #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - { - configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); - } + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } #endif - /*lint -save -e904 This function relaxes the coding standard somewhat to allow return - * statements within the function itself. This is done in the interest - * of execution time efficiency. */ for( ; ; ) { taskENTER_CRITICAL(); @@ -1555,26 +1686,25 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, * must be the highest priority task wanting to access the queue. */ if( uxSemaphoreCount > ( UBaseType_t ) 0 ) { -#ifdef ESP_PLATFORM - traceQUEUE_SEMAPHORE_RECEIVE( pxQueue ); -#endif + traceQUEUE_RECEIVE( pxQueue ); + /* Semaphores are queues with a data size of zero and where the * messages waiting is the semaphore's count. Reduce the count. */ - pxQueue->uxMessagesWaiting = uxSemaphoreCount - ( UBaseType_t ) 1; + pxQueue->uxMessagesWaiting = ( UBaseType_t ) ( uxSemaphoreCount - ( UBaseType_t ) 1 ); #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) { - if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) - { - /* Record the information required to implement - * priority inheritance should it become necessary. */ - pxQueue->u.xSemaphore.xMutexHolder = pvTaskIncrementMutexHeldCount(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Record the information required to implement + * priority inheritance should it become necessary. */ + pxQueue->u.xSemaphore.xMutexHolder = pvTaskIncrementMutexHeldCount(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } #endif /* configUSE_MUTEXES */ /* Check to see if other tasks are blocked waiting to give the @@ -1596,25 +1726,22 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, } taskEXIT_CRITICAL(); + + traceRETURN_xQueueSemaphoreTake( pdPASS ); + return pdPASS; } else { if( xTicksToWait == ( TickType_t ) 0 ) { - /* For inheritance to have occurred there must have been an - * initial timeout, and an adjusted timeout cannot become 0, as - * if it were 0 the function would have exited. */ - #if ( configUSE_MUTEXES == 1 ) - { - configASSERT( xInheritanceOccurred == pdFALSE ); - } - #endif /* configUSE_MUTEXES */ - /* The semaphore count was 0 and no block time is specified * (or the block time has expired) so exit now. */ taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + traceRETURN_xQueueSemaphoreTake( errQUEUE_EMPTY ); + return errQUEUE_EMPTY; } else if( xEntryTimeSet == pdFALSE ) @@ -1651,20 +1778,20 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) { - if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + taskENTER_CRITICAL(); { - taskENTER_CRITICAL(); - { - xInheritanceOccurred = xTaskPriorityInherit( pxQueue->u.xSemaphore.xMutexHolder ); - } - taskEXIT_CRITICAL(); - } - else - { - mtCOVERAGE_TEST_MARKER(); + xInheritanceOccurred = xTaskPriorityInherit( pxQueue->u.xSemaphore.xMutexHolder ); } + taskEXIT_CRITICAL(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } #endif /* if ( configUSE_MUTEXES == 1 ) */ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); @@ -1672,7 +1799,7 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, if( xTaskResumeAll() == pdFALSE ) { - vTaskYieldWithinAPI(); + taskYIELD_WITHIN_API(); } else { @@ -1700,30 +1827,40 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) { #if ( configUSE_MUTEXES == 1 ) + { + /* xInheritanceOccurred could only have be set if + * pxQueue->uxQueueType == queueQUEUE_IS_MUTEX so no need to + * test the mutex type again to check it is actually a mutex. */ + if( xInheritanceOccurred != pdFALSE ) { - /* xInheritanceOccurred could only have be set if - * pxQueue->uxQueueType == queueQUEUE_IS_MUTEX so no need to - * test the mutex type again to check it is actually a mutex. */ - if( xInheritanceOccurred != pdFALSE ) + taskENTER_CRITICAL(); { - taskENTER_CRITICAL(); - { - UBaseType_t uxHighestWaitingPriority; + UBaseType_t uxHighestWaitingPriority; - /* This task blocking on the mutex caused another - * task to inherit this task's priority. Now this task - * has timed out the priority should be disinherited - * again, but only as low as the next highest priority - * task that is waiting for the same mutex. */ - uxHighestWaitingPriority = prvGetDisinheritPriorityAfterTimeout( pxQueue ); - vTaskPriorityDisinheritAfterTimeout( pxQueue->u.xSemaphore.xMutexHolder, uxHighestWaitingPriority ); - } - taskEXIT_CRITICAL(); + /* This task blocking on the mutex caused another + * task to inherit this task's priority. Now this task + * has timed out the priority should be disinherited + * again, but only as low as the next highest priority + * task that is waiting for the same mutex. */ + uxHighestWaitingPriority = prvGetDisinheritPriorityAfterTimeout( pxQueue ); + + /* vTaskPriorityDisinheritAfterTimeout uses the uxHighestWaitingPriority + * parameter to index pxReadyTasksLists when adding the task holding + * mutex to the ready list for its new priority. Coverity thinks that + * it can result in out-of-bounds access which is not true because + * uxHighestWaitingPriority, as returned by prvGetDisinheritPriorityAfterTimeout, + * is capped at ( configMAX_PRIORITIES - 1 ). */ + /* coverity[overrun] */ + vTaskPriorityDisinheritAfterTimeout( pxQueue->u.xSemaphore.xMutexHolder, uxHighestWaitingPriority ); } + taskEXIT_CRITICAL(); } + } #endif /* configUSE_MUTEXES */ traceQUEUE_RECEIVE_FAILED( pxQueue ); + traceRETURN_xQueueSemaphoreTake( errQUEUE_EMPTY ); + return errQUEUE_EMPTY; } else @@ -1731,7 +1868,7 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, mtCOVERAGE_TEST_MARKER(); } } - } /*lint -restore */ + } } /*-----------------------------------------------------------*/ @@ -1744,6 +1881,8 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, int8_t * pcOriginalReadPosition; Queue_t * const pxQueue = xQueue; + traceENTER_xQueuePeek( xQueue, pvBuffer, xTicksToWait ); + /* Check the pointer is not NULL. */ configASSERT( ( pxQueue ) ); @@ -1753,14 +1892,11 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, /* Cannot block if the scheduler is suspended. */ #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - { - configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); - } + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } #endif - /*lint -save -e904 This function relaxes the coding standard somewhat to - * allow return statements within the function itself. This is done in the - * interest of execution time efficiency. */ for( ; ; ) { taskENTER_CRITICAL(); @@ -1802,6 +1938,9 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, } taskEXIT_CRITICAL(); + + traceRETURN_xQueuePeek( pdPASS ); + return pdPASS; } else @@ -1811,7 +1950,10 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, /* The queue was empty and no block time is specified (or * the block time has expired) so leave now. */ taskEXIT_CRITICAL(); + traceQUEUE_PEEK_FAILED( pxQueue ); + traceRETURN_xQueuePeek( errQUEUE_EMPTY ); + return errQUEUE_EMPTY; } else if( xEntryTimeSet == pdFALSE ) @@ -1850,7 +1992,7 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, if( xTaskResumeAll() == pdFALSE ) { - vTaskYieldWithinAPI(); + taskYIELD_WITHIN_API(); } else { @@ -1875,6 +2017,8 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) { traceQUEUE_PEEK_FAILED( pxQueue ); + traceRETURN_xQueuePeek( errQUEUE_EMPTY ); + return errQUEUE_EMPTY; } else @@ -1882,7 +2026,7 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, mtCOVERAGE_TEST_MARKER(); } } - } /*lint -restore */ + } } /*-----------------------------------------------------------*/ @@ -1894,6 +2038,8 @@ BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, UBaseType_t uxSavedInterruptStatus; Queue_t * const pxQueue = xQueue; + traceENTER_xQueueReceiveFromISR( xQueue, pvBuffer, pxHigherPriorityTaskWoken ); + configASSERT( pxQueue ); configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); @@ -1913,7 +2059,7 @@ BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); { const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; @@ -1925,7 +2071,7 @@ BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, traceQUEUE_RECEIVE_FROM_ISR( pxQueue ); prvCopyDataFromQueue( pxQueue, pvBuffer ); - pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1; + pxQueue->uxMessagesWaiting = ( UBaseType_t ) ( uxMessagesWaiting - ( UBaseType_t ) 1 ); /* If the queue is locked the event list will not be modified. * Instead update the lock count so the task that unlocks the queue @@ -1962,9 +2108,7 @@ BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, { /* Increment the lock count so the task that unlocks the queue * knows that data was removed while it was locked. */ - configASSERT( cRxLock != queueINT8_MAX ); - - pxQueue->cRxLock = ( int8_t ) ( cRxLock + 1 ); + prvIncrementQueueRxLock( pxQueue, cRxLock ); } xReturn = pdPASS; @@ -1975,7 +2119,9 @@ BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ); } } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); + + traceRETURN_xQueueReceiveFromISR( xReturn ); return xReturn; } @@ -1989,6 +2135,8 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, int8_t * pcOriginalReadPosition; Queue_t * const pxQueue = xQueue; + traceENTER_xQueuePeekFromISR( xQueue, pvBuffer ); + configASSERT( pxQueue ); configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); configASSERT( pxQueue->uxItemSize != 0 ); /* Can't peek a semaphore. */ @@ -2009,7 +2157,7 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); { /* Cannot block in an ISR, so check there is data available. */ if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) @@ -2030,7 +2178,9 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ); } } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); + + traceRETURN_xQueuePeekFromISR( xReturn ); return xReturn; } @@ -2040,6 +2190,8 @@ UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) { UBaseType_t uxReturn; + traceENTER_uxQueueMessagesWaiting( xQueue ); + configASSERT( xQueue ); taskENTER_CRITICAL(); @@ -2048,8 +2200,10 @@ UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) } taskEXIT_CRITICAL(); + traceRETURN_uxQueueMessagesWaiting( uxReturn ); + return uxReturn; -} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +} /*-----------------------------------------------------------*/ UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) @@ -2057,16 +2211,20 @@ UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) UBaseType_t uxReturn; Queue_t * const pxQueue = xQueue; + traceENTER_uxQueueSpacesAvailable( xQueue ); + configASSERT( pxQueue ); taskENTER_CRITICAL(); { - uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting; + uxReturn = ( UBaseType_t ) ( pxQueue->uxLength - pxQueue->uxMessagesWaiting ); } taskEXIT_CRITICAL(); + traceRETURN_uxQueueSpacesAvailable( uxReturn ); + return uxReturn; -} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +} /*-----------------------------------------------------------*/ UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) @@ -2074,52 +2232,60 @@ UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) UBaseType_t uxReturn; Queue_t * const pxQueue = xQueue; + traceENTER_uxQueueMessagesWaitingFromISR( xQueue ); + configASSERT( pxQueue ); uxReturn = pxQueue->uxMessagesWaiting; + traceRETURN_uxQueueMessagesWaitingFromISR( uxReturn ); + return uxReturn; -} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +} /*-----------------------------------------------------------*/ void vQueueDelete( QueueHandle_t xQueue ) { Queue_t * const pxQueue = xQueue; + traceENTER_vQueueDelete( xQueue ); + configASSERT( pxQueue ); traceQUEUE_DELETE( pxQueue ); #if ( configQUEUE_REGISTRY_SIZE > 0 ) - { - vQueueUnregisterQueue( pxQueue ); - } + { + vQueueUnregisterQueue( pxQueue ); + } #endif #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) + { + /* The queue can only have been allocated dynamically - free it + * again. */ + vPortFree( pxQueue ); + } + #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + { + /* The queue could have been allocated statically or dynamically, so + * check before attempting to free the memory. */ + if( pxQueue->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) { - /* The queue can only have been allocated dynamically - free it - * again. */ vPortFree( pxQueue ); } - #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + else { - /* The queue could have been allocated statically or dynamically, so - * check before attempting to free the memory. */ - if( pxQueue->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) - { - vPortFree( pxQueue ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + mtCOVERAGE_TEST_MARKER(); } + } #else /* if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) */ - { - /* The queue must have been statically allocated, so is not going to be - * deleted. Avoid compiler warnings about the unused parameter. */ - ( void ) pxQueue; - } + { + /* The queue must have been statically allocated, so is not going to be + * deleted. Avoid compiler warnings about the unused parameter. */ + ( void ) pxQueue; + } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + + traceRETURN_vQueueDelete(); } /*-----------------------------------------------------------*/ @@ -2127,6 +2293,10 @@ void vQueueDelete( QueueHandle_t xQueue ) UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) { + traceENTER_uxQueueGetQueueNumber( xQueue ); + + traceRETURN_uxQueueGetQueueNumber( ( ( Queue_t * ) xQueue )->uxQueueNumber ); + return ( ( Queue_t * ) xQueue )->uxQueueNumber; } @@ -2138,7 +2308,11 @@ void vQueueDelete( QueueHandle_t xQueue ) void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) { + traceENTER_vQueueSetQueueNumber( xQueue, uxQueueNumber ); + ( ( Queue_t * ) xQueue )->uxQueueNumber = uxQueueNumber; + + traceRETURN_vQueueSetQueueNumber(); } #endif /* configUSE_TRACE_FACILITY */ @@ -2148,12 +2322,36 @@ void vQueueDelete( QueueHandle_t xQueue ) uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) { + traceENTER_ucQueueGetQueueType( xQueue ); + + traceRETURN_ucQueueGetQueueType( ( ( Queue_t * ) xQueue )->ucQueueType ); + return ( ( Queue_t * ) xQueue )->ucQueueType; } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ +UBaseType_t uxQueueGetQueueItemSize( QueueHandle_t xQueue ) /* PRIVILEGED_FUNCTION */ +{ + traceENTER_uxQueueGetQueueItemSize( xQueue ); + + traceRETURN_uxQueueGetQueueItemSize( ( ( Queue_t * ) xQueue )->uxItemSize ); + + return ( ( Queue_t * ) xQueue )->uxItemSize; +} +/*-----------------------------------------------------------*/ + +UBaseType_t uxQueueGetQueueLength( QueueHandle_t xQueue ) /* PRIVILEGED_FUNCTION */ +{ + traceENTER_uxQueueGetQueueLength( xQueue ); + + traceRETURN_uxQueueGetQueueLength( ( ( Queue_t * ) xQueue )->uxLength ); + + return ( ( Queue_t * ) xQueue )->uxLength; +} +/*-----------------------------------------------------------*/ + #if ( configUSE_MUTEXES == 1 ) static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue ) @@ -2168,7 +2366,7 @@ void vQueueDelete( QueueHandle_t xQueue ) * mutex. */ if( listCURRENT_LIST_LENGTH( &( pxQueue->xTasksWaitingToReceive ) ) > 0U ) { - uxHighestPriorityOfWaitingTasks = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) listGET_ITEM_VALUE_OF_HEAD_ENTRY( &( pxQueue->xTasksWaitingToReceive ) ); + uxHighestPriorityOfWaitingTasks = ( UBaseType_t ) ( ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) listGET_ITEM_VALUE_OF_HEAD_ENTRY( &( pxQueue->xTasksWaitingToReceive ) ) ); } else { @@ -2195,26 +2393,26 @@ static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, if( pxQueue->uxItemSize == ( UBaseType_t ) 0 ) { #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) { - if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) - { - /* The mutex is no longer being held. */ - xReturn = xTaskPriorityDisinherit( pxQueue->u.xSemaphore.xMutexHolder ); - pxQueue->u.xSemaphore.xMutexHolder = NULL; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* The mutex is no longer being held. */ + xReturn = xTaskPriorityDisinherit( pxQueue->u.xSemaphore.xMutexHolder ); + pxQueue->u.xSemaphore.xMutexHolder = NULL; } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } #endif /* configUSE_MUTEXES */ } else if( xPosition == queueSEND_TO_BACK ) { - ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 !e9087 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. */ - pxQueue->pcWriteTo += pxQueue->uxItemSize; /*lint !e9016 Pointer arithmetic on char types ok, especially in this use case where it is the clearest way of conveying intent. */ + ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); + pxQueue->pcWriteTo += pxQueue->uxItemSize; - if( pxQueue->pcWriteTo >= pxQueue->u.xQueue.pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ + if( pxQueue->pcWriteTo >= pxQueue->u.xQueue.pcTail ) { pxQueue->pcWriteTo = pxQueue->pcHead; } @@ -2225,10 +2423,10 @@ static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, } else { - ( void ) memcpy( ( void * ) pxQueue->u.xQueue.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e9087 !e418 MISRA exception as the casts are only redundant for some ports. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. Assert checks null pointer only used when length is 0. */ + ( void ) memcpy( ( void * ) pxQueue->u.xQueue.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); pxQueue->u.xQueue.pcReadFrom -= pxQueue->uxItemSize; - if( pxQueue->u.xQueue.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ + if( pxQueue->u.xQueue.pcReadFrom < pxQueue->pcHead ) { pxQueue->u.xQueue.pcReadFrom = ( pxQueue->u.xQueue.pcTail - pxQueue->uxItemSize ); } @@ -2258,7 +2456,7 @@ static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, } } - pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1; + pxQueue->uxMessagesWaiting = ( UBaseType_t ) ( uxMessagesWaiting + ( UBaseType_t ) 1 ); return xReturn; } @@ -2269,9 +2467,9 @@ static void prvCopyDataFromQueue( Queue_t * const pxQueue, { if( pxQueue->uxItemSize != ( UBaseType_t ) 0 ) { - pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize; /*lint !e9016 Pointer arithmetic on char types ok, especially in this use case where it is the clearest way of conveying intent. */ + pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize; - if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */ + if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail ) { pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead; } @@ -2280,7 +2478,7 @@ static void prvCopyDataFromQueue( Queue_t * const pxQueue, mtCOVERAGE_TEST_MARKER(); } - ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 !e9087 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. */ + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); } } /*-----------------------------------------------------------*/ @@ -2303,55 +2501,32 @@ static void prvUnlockQueue( Queue_t * const pxQueue ) /* Data was posted while the queue was locked. Are any tasks * blocked waiting for data to become available? */ #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) { - if( pxQueue->pxQueueSetContainer != NULL ) + if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE ) { - if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE ) - { - /* The queue is a member of a queue set, and posting to - * the queue set caused a higher priority task to unblock. - * A context switch is required. */ - vTaskMissedYield(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* The queue is a member of a queue set, and posting to + * the queue set caused a higher priority task to unblock. + * A context switch is required. */ + vTaskMissedYield(); } else { - /* Tasks that are removed from the event list will get - * added to the pending ready list as the scheduler is still - * suspended. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority so record that a - * context switch is required. */ - vTaskMissedYield(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - break; - } + mtCOVERAGE_TEST_MARKER(); } } - #else /* configUSE_QUEUE_SETS */ + else { - /* Tasks that are removed from the event list will get added to - * the pending ready list as the scheduler is still suspended. */ + /* Tasks that are removed from the event list will get + * added to the pending ready list as the scheduler is still + * suspended. */ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) { if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { - /* The task waiting has a higher priority so record that - * a context switch is required. */ + /* The task waiting has a higher priority so record that a + * context switch is required. */ vTaskMissedYield(); } else @@ -2364,6 +2539,29 @@ static void prvUnlockQueue( Queue_t * const pxQueue ) break; } } + } + #else /* configUSE_QUEUE_SETS */ + { + /* Tasks that are removed from the event list will get added to + * the pending ready list as the scheduler is still suspended. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that + * a context switch is required. */ + vTaskMissedYield(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + break; + } + } #endif /* configUSE_QUEUE_SETS */ --cTxLock; @@ -2431,6 +2629,8 @@ BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) BaseType_t xReturn; Queue_t * const pxQueue = xQueue; + traceENTER_xQueueIsQueueEmptyFromISR( xQueue ); + configASSERT( pxQueue ); if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) @@ -2442,8 +2642,10 @@ BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) xReturn = pdFALSE; } + traceRETURN_xQueueIsQueueEmptyFromISR( xReturn ); + return xReturn; -} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ +} /*-----------------------------------------------------------*/ static BaseType_t prvIsQueueFull( const Queue_t * pxQueue ) @@ -2472,6 +2674,8 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) BaseType_t xReturn; Queue_t * const pxQueue = xQueue; + traceENTER_xQueueIsQueueFullFromISR( xQueue ); + configASSERT( pxQueue ); if( pxQueue->uxMessagesWaiting == pxQueue->uxLength ) @@ -2483,8 +2687,10 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) xReturn = pdFALSE; } + traceRETURN_xQueueIsQueueFullFromISR( xReturn ); + return xReturn; -} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ +} /*-----------------------------------------------------------*/ #if ( configUSE_CO_ROUTINES == 1 ) @@ -2496,6 +2702,8 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) BaseType_t xReturn; Queue_t * const pxQueue = xQueue; + traceENTER_xQueueCRSend( xQueue, pvItemToQueue, xTicksToWait ); + /* If the queue is already full we may have to block. A critical section * is required to prevent an interrupt removing something from the queue * between the check to see if the queue is full and blocking on the queue. */ @@ -2560,6 +2768,8 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) } portENABLE_INTERRUPTS(); + traceRETURN_xQueueCRSend( xReturn ); + return xReturn; } @@ -2575,6 +2785,8 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) BaseType_t xReturn; Queue_t * const pxQueue = xQueue; + traceENTER_xQueueCRReceive( xQueue, pvBuffer, xTicksToWait ); + /* If the queue is already empty we may have to block. A critical section * is required to prevent an interrupt adding something to the queue * between the check to see if the queue is empty and blocking on the queue. */ @@ -2654,6 +2866,8 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) } portENABLE_INTERRUPTS(); + traceRETURN_xQueueCRReceive( xReturn ); + return xReturn; } @@ -2668,6 +2882,8 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) { Queue_t * const pxQueue = xQueue; + traceENTER_xQueueCRSendFromISR( xQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ); + /* Cannot block within an ISR so if there is no space on the queue then * exit without doing anything. */ if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) @@ -2704,6 +2920,8 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) mtCOVERAGE_TEST_MARKER(); } + traceRETURN_xQueueCRSendFromISR( xCoRoutinePreviouslyWoken ); + return xCoRoutinePreviouslyWoken; } @@ -2719,6 +2937,8 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) BaseType_t xReturn; Queue_t * const pxQueue = xQueue; + traceENTER_xQueueCRReceiveFromISR( xQueue, pvBuffer, pxCoRoutineWoken ); + /* We cannot block from an ISR, so check there is data available. If * not then just leave without doing anything. */ if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) @@ -2768,6 +2988,8 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) xReturn = pdFAIL; } + traceRETURN_xQueueCRReceiveFromISR( xReturn ); + return xReturn; } @@ -2777,31 +2999,49 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) #if ( configQUEUE_REGISTRY_SIZE > 0 ) void vQueueAddToRegistry( QueueHandle_t xQueue, - const char * pcQueueName ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const char * pcQueueName ) { UBaseType_t ux; + QueueRegistryItem_t * pxEntryToWrite = NULL; + + traceENTER_vQueueAddToRegistry( xQueue, pcQueueName ); configASSERT( xQueue ); - configASSERT( pcQueueName ); - /* See if there is an empty space in the registry. A NULL name denotes - * a free slot. */ - for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) + if( pcQueueName != NULL ) { - if( xQueueRegistry[ ux ].pcQueueName == NULL ) + /* See if there is an empty space in the registry. A NULL name denotes + * a free slot. */ + for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) { - /* Store the information on this queue. */ - xQueueRegistry[ ux ].pcQueueName = pcQueueName; - xQueueRegistry[ ux ].xHandle = xQueue; - - traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName ); - break; - } - else - { - mtCOVERAGE_TEST_MARKER(); + /* Replace an existing entry if the queue is already in the registry. */ + if( xQueue == xQueueRegistry[ ux ].xHandle ) + { + pxEntryToWrite = &( xQueueRegistry[ ux ] ); + break; + } + /* Otherwise, store in the next empty location */ + else if( ( pxEntryToWrite == NULL ) && ( xQueueRegistry[ ux ].pcQueueName == NULL ) ) + { + pxEntryToWrite = &( xQueueRegistry[ ux ] ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } } + + if( pxEntryToWrite != NULL ) + { + /* Store the information on this queue. */ + pxEntryToWrite->pcQueueName = pcQueueName; + pxEntryToWrite->xHandle = xQueue; + + traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName ); + } + + traceRETURN_vQueueAddToRegistry(); } #endif /* configQUEUE_REGISTRY_SIZE */ @@ -2809,10 +3049,12 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) #if ( configQUEUE_REGISTRY_SIZE > 0 ) - const char * pcQueueGetName( QueueHandle_t xQueue ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const char * pcQueueGetName( QueueHandle_t xQueue ) { UBaseType_t ux; - const char * pcReturn = NULL; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const char * pcReturn = NULL; + + traceENTER_pcQueueGetName( xQueue ); configASSERT( xQueue ); @@ -2832,8 +3074,10 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) } } + traceRETURN_pcQueueGetName( pcReturn ); + return pcReturn; - } /*lint !e818 xQueue cannot be a pointer to const because it is a typedef. */ + } #endif /* configQUEUE_REGISTRY_SIZE */ /*-----------------------------------------------------------*/ @@ -2844,6 +3088,8 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) { UBaseType_t ux; + traceENTER_vQueueUnregisterQueue( xQueue ); + configASSERT( xQueue ); /* See if the handle of the queue being unregistered in actually in the @@ -2866,7 +3112,9 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) mtCOVERAGE_TEST_MARKER(); } } - } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ + + traceRETURN_vQueueUnregisterQueue(); + } #endif /* configQUEUE_REGISTRY_SIZE */ /*-----------------------------------------------------------*/ @@ -2879,6 +3127,8 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) { Queue_t * const pxQueue = xQueue; + traceENTER_vQueueWaitForMessageRestricted( xQueue, xTicksToWait, xWaitIndefinitely ); + /* This function should not be called by application code hence the * 'Restricted' in its name. It is not part of the public API. It is * designed for use by kernel code, and has special calling requirements. @@ -2906,6 +3156,8 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) } prvUnlockQueue( pxQueue ); + + traceRETURN_vQueueWaitForMessageRestricted(); } #endif /* configUSE_TIMERS */ @@ -2917,8 +3169,12 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) { QueueSetHandle_t pxQueue; + traceENTER_xQueueCreateSet( uxEventQueueLength ); + pxQueue = xQueueGenericCreate( uxEventQueueLength, ( UBaseType_t ) sizeof( Queue_t * ), queueQUEUE_TYPE_SET ); + traceRETURN_xQueueCreateSet( pxQueue ); + return pxQueue; } @@ -2932,6 +3188,8 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) { BaseType_t xReturn; + traceENTER_xQueueAddToSet( xQueueOrSemaphore, xQueueSet ); + taskENTER_CRITICAL(); { if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) @@ -2953,6 +3211,8 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) } taskEXIT_CRITICAL(); + traceRETURN_xQueueAddToSet( xReturn ); + return xReturn; } @@ -2967,6 +3227,8 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) BaseType_t xReturn; Queue_t * const pxQueueOrSemaphore = ( Queue_t * ) xQueueOrSemaphore; + traceENTER_xQueueRemoveFromSet( xQueueOrSemaphore, xQueueSet ); + if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet ) { /* The queue was not a member of the set. */ @@ -2990,8 +3252,10 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) xReturn = pdPASS; } + traceRETURN_xQueueRemoveFromSet( xReturn ); + return xReturn; - } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */ + } #endif /* configUSE_QUEUE_SETS */ /*-----------------------------------------------------------*/ @@ -3003,7 +3267,12 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) { QueueSetMemberHandle_t xReturn = NULL; - ( void ) xQueueReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait ); /*lint !e961 Casting from one typedef to another is not redundant. */ + traceENTER_xQueueSelectFromSet( xQueueSet, xTicksToWait ); + + ( void ) xQueueReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait ); + + traceRETURN_xQueueSelectFromSet( xReturn ); + return xReturn; } @@ -3016,7 +3285,12 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) { QueueSetMemberHandle_t xReturn = NULL; - ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */ + traceENTER_xQueueSelectFromSetFromISR( xQueueSet ); + + ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet, &xReturn, NULL ); + + traceRETURN_xQueueSelectFromSetFromISR( xReturn ); + return xReturn; } @@ -3068,9 +3342,7 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) } else { - configASSERT( cTxLock != queueINT8_MAX ); - - pxQueueSetContainer->cTxLock = ( int8_t ) ( cTxLock + 1 ); + prvIncrementQueueTxLock( pxQueueSetContainer, cTxLock ); } } else diff --git a/components/freertos/FreeRTOS-Kernel-SMP/stream_buffer.c b/components/freertos/FreeRTOS-Kernel-SMP/stream_buffer.c index 0208032186..e337fbf332 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/stream_buffer.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/stream_buffer.c @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -25,7 +31,6 @@ */ /* Standard includes. */ -#include #include /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining @@ -42,55 +47,98 @@ #error configUSE_TASK_NOTIFICATIONS must be set to 1 to build stream_buffer.c #endif -/* Lint e961, e9021 and e750 are suppressed as a MISRA exception justified - * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined +#if ( INCLUDE_xTaskGetCurrentTaskHandle != 1 ) + #error INCLUDE_xTaskGetCurrentTaskHandle must be set to 1 to build stream_buffer.c +#endif + +/* The MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined * for the header files above, but not in this file, in order to generate the * correct privileged Vs unprivileged linkage and placement. */ -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /* If the user has not provided application specific Rx notification macros, * or #defined the notification macros away, then provide default implementations * that uses task notifications. */ -/*lint -save -e9026 Function like macros allowed and needed here so they can be overridden. */ #ifndef sbRECEIVE_COMPLETED - #define sbRECEIVE_COMPLETED( pxStreamBuffer ) \ - vTaskSuspendAll(); \ - { \ - if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) \ - { \ - ( void ) xTaskNotify( ( pxStreamBuffer )->xTaskWaitingToSend, \ - ( uint32_t ) 0, \ - eNoAction ); \ - ( pxStreamBuffer )->xTaskWaitingToSend = NULL; \ - } \ - } \ - ( void ) xTaskResumeAll(); + #define sbRECEIVE_COMPLETED( pxStreamBuffer ) \ + do \ + { \ + vTaskSuspendAll(); \ + { \ + if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) \ + { \ + ( void ) xTaskNotify( ( pxStreamBuffer )->xTaskWaitingToSend, \ + ( uint32_t ) 0, \ + eNoAction ); \ + ( pxStreamBuffer )->xTaskWaitingToSend = NULL; \ + } \ + } \ + ( void ) xTaskResumeAll(); \ + } while( 0 ) #endif /* sbRECEIVE_COMPLETED */ +/* If user has provided a per-instance receive complete callback, then + * invoke the callback else use the receive complete macro which is provided by default for all instances. + */ +#if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) + #define prvRECEIVE_COMPLETED( pxStreamBuffer ) \ + do { \ + if( ( pxStreamBuffer )->pxReceiveCompletedCallback != NULL ) \ + { \ + ( pxStreamBuffer )->pxReceiveCompletedCallback( ( pxStreamBuffer ), pdFALSE, NULL ); \ + } \ + else \ + { \ + sbRECEIVE_COMPLETED( ( pxStreamBuffer ) ); \ + } \ + } while( 0 ) +#else /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */ + #define prvRECEIVE_COMPLETED( pxStreamBuffer ) sbRECEIVE_COMPLETED( ( pxStreamBuffer ) ) +#endif /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */ + #ifndef sbRECEIVE_COMPLETED_FROM_ISR #define sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, \ pxHigherPriorityTaskWoken ) \ - { \ + do { \ UBaseType_t uxSavedInterruptStatus; \ \ - uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \ + uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); \ { \ if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) \ { \ ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToSend, \ ( uint32_t ) 0, \ eNoAction, \ - pxHigherPriorityTaskWoken ); \ + ( pxHigherPriorityTaskWoken ) ); \ ( pxStreamBuffer )->xTaskWaitingToSend = NULL; \ } \ } \ - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \ - } + taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); \ + } while( 0 ) #endif /* sbRECEIVE_COMPLETED_FROM_ISR */ +#if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) + #define prvRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, \ + pxHigherPriorityTaskWoken ) \ + do { \ + if( ( pxStreamBuffer )->pxReceiveCompletedCallback != NULL ) \ + { \ + ( pxStreamBuffer )->pxReceiveCompletedCallback( ( pxStreamBuffer ), pdTRUE, ( pxHigherPriorityTaskWoken ) ); \ + } \ + else \ + { \ + sbRECEIVE_COMPLETED_FROM_ISR( ( pxStreamBuffer ), ( pxHigherPriorityTaskWoken ) ); \ + } \ + } while( 0 ) +#else /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */ + #define prvRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \ + sbRECEIVE_COMPLETED_FROM_ISR( ( pxStreamBuffer ), ( pxHigherPriorityTaskWoken ) ) +#endif /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */ + /* If the user has not provided an application specific Tx notification macro, - * or #defined the notification macro away, them provide a default implementation - * that uses task notifications. */ + * or #defined the notification macro away, then provide a default + * implementation that uses task notifications. + */ #ifndef sbSEND_COMPLETED #define sbSEND_COMPLETED( pxStreamBuffer ) \ vTaskSuspendAll(); \ @@ -103,29 +151,66 @@ ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; \ } \ } \ - ( void ) xTaskResumeAll(); + ( void ) xTaskResumeAll() #endif /* sbSEND_COMPLETED */ +/* If user has provided a per-instance send completed callback, then + * invoke the callback else use the send complete macro which is provided by default for all instances. + */ +#if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) + #define prvSEND_COMPLETED( pxStreamBuffer ) \ + do { \ + if( ( pxStreamBuffer )->pxSendCompletedCallback != NULL ) \ + { \ + ( pxStreamBuffer )->pxSendCompletedCallback( ( pxStreamBuffer ), pdFALSE, NULL ); \ + } \ + else \ + { \ + sbSEND_COMPLETED( ( pxStreamBuffer ) ); \ + } \ + } while( 0 ) +#else /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */ + #define prvSEND_COMPLETED( pxStreamBuffer ) sbSEND_COMPLETED( ( pxStreamBuffer ) ) +#endif /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */ + + #ifndef sbSEND_COMPLETE_FROM_ISR #define sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \ - { \ + do { \ UBaseType_t uxSavedInterruptStatus; \ \ - uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \ + uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); \ { \ if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL ) \ { \ ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToReceive, \ ( uint32_t ) 0, \ eNoAction, \ - pxHigherPriorityTaskWoken ); \ + ( pxHigherPriorityTaskWoken ) ); \ ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; \ } \ } \ - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \ - } + taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); \ + } while( 0 ) #endif /* sbSEND_COMPLETE_FROM_ISR */ -/*lint -restore (9026) */ + + +#if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) + #define prvSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \ + do { \ + if( ( pxStreamBuffer )->pxSendCompletedCallback != NULL ) \ + { \ + ( pxStreamBuffer )->pxSendCompletedCallback( ( pxStreamBuffer ), pdTRUE, ( pxHigherPriorityTaskWoken ) ); \ + } \ + else \ + { \ + sbSEND_COMPLETE_FROM_ISR( ( pxStreamBuffer ), ( pxHigherPriorityTaskWoken ) ); \ + } \ + } while( 0 ) +#else /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */ + #define prvSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \ + sbSEND_COMPLETE_FROM_ISR( ( pxStreamBuffer ), ( pxHigherPriorityTaskWoken ) ) +#endif /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */ /* The number of bytes used to hold the length of a message in the buffer. */ #define sbBYTES_TO_STORE_MESSAGE_LENGTH ( sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ) ) @@ -137,7 +222,7 @@ /*-----------------------------------------------------------*/ /* Structure that hold state information on the buffer. */ -typedef struct StreamBufferDef_t /*lint !e9058 Style convention uses tag. */ +typedef struct StreamBufferDef_t { volatile size_t xTail; /* Index to the next item to read within the buffer. */ volatile size_t xHead; /* Index to the next item to write within the buffer. */ @@ -151,6 +236,11 @@ typedef struct StreamBufferDef_t /*lint !e9058 Style convention #if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxStreamBufferNumber; /* Used for tracing purposes. */ #endif + + #if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) + StreamBufferCallbackFunction_t pxSendCompletedCallback; /* Optional callback called on send complete. sbSEND_COMPLETED is called if this is NULL. */ + StreamBufferCallbackFunction_t pxReceiveCompletedCallback; /* Optional callback called on receive complete. sbRECEIVE_COMPLETED is called if this is NULL. */ + #endif } StreamBuffer_t; /* @@ -159,14 +249,20 @@ typedef struct StreamBufferDef_t /*lint !e9058 Style convention static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer ) PRIVILEGED_FUNCTION; /* - * Add xCount bytes from pucData into the pxStreamBuffer message buffer. - * Returns the number of bytes written, which will either equal xCount in the - * success case, or 0 if there was not enough space in the buffer (in which case - * no data is written into the buffer). + * Add xCount bytes from pucData into the pxStreamBuffer's data storage area. + * This function does not update the buffer's xHead pointer, so multiple writes + * may be chained together "atomically". This is useful for Message Buffers where + * the length and data bytes are written in two separate chunks, and we don't want + * the reader to see the buffer as having grown until after all data is copied over. + * This function takes a custom xHead value to indicate where to write to (necessary + * for chaining) and returns the the resulting xHead position. + * To mark the write as complete, manually set the buffer's xHead field with the + * returned xHead from this function. */ static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, const uint8_t * pucData, - size_t xCount ) PRIVILEGED_FUNCTION; + size_t xCount, + size_t xHead ) PRIVILEGED_FUNCTION; /* * If the stream buffer is being used as a message buffer, then reads an entire @@ -178,8 +274,7 @@ static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, static size_t prvReadMessageFromBuffer( StreamBuffer_t * pxStreamBuffer, void * pvRxData, size_t xBufferLengthBytes, - size_t xBytesAvailable, - size_t xBytesToStoreMessageLength ) PRIVILEGED_FUNCTION; + size_t xBytesAvailable ) PRIVILEGED_FUNCTION; /* * If the stream buffer is being used as a message buffer, then writes an entire @@ -195,13 +290,21 @@ static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer, size_t xRequiredSpace ) PRIVILEGED_FUNCTION; /* - * Read xMaxCount bytes from the pxStreamBuffer message buffer and write them - * to pucData. + * Copies xCount bytes from the pxStreamBuffer's data storage area to pucData. + * This function does not update the buffer's xTail pointer, so multiple reads + * may be chained together "atomically". This is useful for Message Buffers where + * the length and data bytes are read in two separate chunks, and we don't want + * the writer to see the buffer as having more free space until after all data is + * copied over, especially if we have to abort the read due to insufficient receiving space. + * This function takes a custom xTail value to indicate where to read from (necessary + * for chaining) and returns the the resulting xTail position. + * To mark the read as complete, manually set the buffer's xTail field with the + * returned xTail from this function. */ static size_t prvReadBytesFromBuffer( StreamBuffer_t * pxStreamBuffer, uint8_t * pucData, - size_t xMaxCount, - size_t xBytesAvailable ) PRIVILEGED_FUNCTION; + size_t xCount, + size_t xTail ) PRIVILEGED_FUNCTION; /* * Called by both pxStreamBufferCreate() and pxStreamBufferCreateStatic() to @@ -211,19 +314,23 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, uint8_t * const pucBuffer, size_t xBufferSizeBytes, size_t xTriggerLevelBytes, - uint8_t ucFlags ) PRIVILEGED_FUNCTION; + uint8_t ucFlags, + StreamBufferCallbackFunction_t pxSendCompletedCallback, + StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION; /*-----------------------------------------------------------*/ - #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes, - BaseType_t xIsMessageBuffer ) + BaseType_t xIsMessageBuffer, + StreamBufferCallbackFunction_t pxSendCompletedCallback, + StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) { - uint8_t * pucAllocatedMemory; + void * pvAllocatedMemory; uint8_t ucFlags; + traceENTER_xStreamBufferGenericCreate( xBufferSizeBytes, xTriggerLevelBytes, xIsMessageBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback ); + /* In case the stream buffer is going to be used as a message buffer * (that is, it will hold discrete messages with a little meta data that * says how big the next message is) check the buffer will be large enough @@ -258,34 +365,46 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, * this is a quirk of the implementation that means otherwise the free * space would be reported as one byte smaller than would be logically * expected. */ - if( xBufferSizeBytes < ( xBufferSizeBytes + 1 + sizeof( StreamBuffer_t ) ) ) + if( xBufferSizeBytes < ( xBufferSizeBytes + 1U + sizeof( StreamBuffer_t ) ) ) { xBufferSizeBytes++; - pucAllocatedMemory = ( uint8_t * ) pvPortMalloc( xBufferSizeBytes + sizeof( StreamBuffer_t ) ); /*lint !e9079 malloc() only returns void*. */ + pvAllocatedMemory = pvPortMalloc( xBufferSizeBytes + sizeof( StreamBuffer_t ) ); } else { - pucAllocatedMemory = NULL; + pvAllocatedMemory = NULL; } - if( pucAllocatedMemory != NULL ) + if( pvAllocatedMemory != NULL ) { - prvInitialiseNewStreamBuffer( ( StreamBuffer_t * ) pucAllocatedMemory, /* Structure at the start of the allocated memory. */ /*lint !e9087 Safe cast as allocated memory is aligned. */ /*lint !e826 Area is not too small and alignment is guaranteed provided malloc() behaves as expected and returns aligned buffer. */ - pucAllocatedMemory + sizeof( StreamBuffer_t ), /* Storage area follows. */ /*lint !e9016 Indexing past structure valid for uint8_t pointer, also storage area has no alignment requirement. */ + /* MISRA Ref 11.5.1 [Malloc memory assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + prvInitialiseNewStreamBuffer( ( StreamBuffer_t * ) pvAllocatedMemory, /* Structure at the start of the allocated memory. */ + /* MISRA Ref 11.5.1 [Malloc memory assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + ( ( uint8_t * ) pvAllocatedMemory ) + sizeof( StreamBuffer_t ), /* Storage area follows. */ xBufferSizeBytes, xTriggerLevelBytes, - ucFlags ); + ucFlags, + pxSendCompletedCallback, + pxReceiveCompletedCallback ); - traceSTREAM_BUFFER_CREATE( ( ( StreamBuffer_t * ) pucAllocatedMemory ), xIsMessageBuffer ); + traceSTREAM_BUFFER_CREATE( ( ( StreamBuffer_t * ) pvAllocatedMemory ), xIsMessageBuffer ); } else { traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ); } - return ( StreamBufferHandle_t ) pucAllocatedMemory; /*lint !e9087 !e826 Safe cast as allocated memory is aligned. */ - } + traceRETURN_xStreamBufferGenericCreate( pvAllocatedMemory ); + /* MISRA Ref 11.5.1 [Malloc memory assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + return ( StreamBufferHandle_t ) pvAllocatedMemory; + } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ /*-----------------------------------------------------------*/ @@ -295,12 +414,19 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, size_t xTriggerLevelBytes, BaseType_t xIsMessageBuffer, uint8_t * const pucStreamBufferStorageArea, - StaticStreamBuffer_t * const pxStaticStreamBuffer ) + StaticStreamBuffer_t * const pxStaticStreamBuffer, + StreamBufferCallbackFunction_t pxSendCompletedCallback, + StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) { - StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) pxStaticStreamBuffer; /*lint !e740 !e9087 Safe cast as StaticStreamBuffer_t is opaque Streambuffer_t. */ + /* MISRA Ref 11.3.1 [Misaligned access] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */ + /* coverity[misra_c_2012_rule_11_3_violation] */ + StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) pxStaticStreamBuffer; StreamBufferHandle_t xReturn; uint8_t ucFlags; + traceENTER_xStreamBufferGenericCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, xIsMessageBuffer, pucStreamBufferStorageArea, pxStaticStreamBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback ); + configASSERT( pucStreamBufferStorageArea ); configASSERT( pxStaticStreamBuffer ); configASSERT( xTriggerLevelBytes <= xBufferSizeBytes ); @@ -312,10 +438,16 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, xTriggerLevelBytes = ( size_t ) 1; } + /* In case the stream buffer is going to be used as a message buffer + * (that is, it will hold discrete messages with a little meta data that + * says how big the next message is) check the buffer will be large enough + * to hold at least one message. */ + if( xIsMessageBuffer != pdFALSE ) { /* Statically allocated message buffer. */ ucFlags = sbFLAGS_IS_MESSAGE_BUFFER | sbFLAGS_IS_STATICALLY_ALLOCATED; + configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH ); } else { @@ -323,20 +455,14 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, ucFlags = sbFLAGS_IS_STATICALLY_ALLOCATED; } - /* In case the stream buffer is going to be used as a message buffer - * (that is, it will hold discrete messages with a little meta data that - * says how big the next message is) check the buffer will be large enough - * to hold at least one message. */ - configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH ); - #if ( configASSERT_DEFINED == 1 ) - { - /* Sanity check that the size of the structure used to declare a - * variable of type StaticStreamBuffer_t equals the size of the real - * message buffer structure. */ - volatile size_t xSize = sizeof( StaticStreamBuffer_t ); - configASSERT( xSize == sizeof( StreamBuffer_t ) ); - } /*lint !e529 xSize is referenced is configASSERT() is defined. */ + { + /* Sanity check that the size of the structure used to declare a + * variable of type StaticStreamBuffer_t equals the size of the real + * message buffer structure. */ + volatile size_t xSize = sizeof( StaticStreamBuffer_t ); + configASSERT( xSize == sizeof( StreamBuffer_t ) ); + } #endif /* configASSERT_DEFINED */ if( ( pucStreamBufferStorageArea != NULL ) && ( pxStaticStreamBuffer != NULL ) ) @@ -345,7 +471,9 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, pucStreamBufferStorageArea, xBufferSizeBytes, xTriggerLevelBytes, - ucFlags ); + ucFlags, + pxSendCompletedCallback, + pxReceiveCompletedCallback ); /* Remember this was statically allocated in case it is ever deleted * again. */ @@ -353,7 +481,10 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer ); - xReturn = ( StreamBufferHandle_t ) pxStaticStreamBuffer; /*lint !e9087 Data hiding requires cast to opaque type. */ + /* MISRA Ref 11.3.1 [Misaligned access] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */ + /* coverity[misra_c_2012_rule_11_3_violation] */ + xReturn = ( StreamBufferHandle_t ) pxStaticStreamBuffer; } else { @@ -361,9 +492,10 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer ); } + traceRETURN_xStreamBufferGenericCreateStatic( xReturn ); + return xReturn; } - #endif /* ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /*-----------------------------------------------------------*/ @@ -373,7 +505,9 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, StaticStreamBuffer_t ** ppxStaticStreamBuffer ) { BaseType_t xReturn; - const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + + traceENTER_xStreamBufferGetStaticBuffers( xStreamBuffer, ppucStreamBufferStorageArea, ppxStaticStreamBuffer ); configASSERT( pxStreamBuffer ); configASSERT( ppucStreamBufferStorageArea ); @@ -382,6 +516,9 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_STATICALLY_ALLOCATED ) != ( uint8_t ) 0 ) { *ppucStreamBufferStorageArea = pxStreamBuffer->pucBuffer; + /* MISRA Ref 11.3.1 [Misaligned access] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */ + /* coverity[misra_c_2012_rule_11_3_violation] */ *ppxStaticStreamBuffer = ( StaticStreamBuffer_t * ) pxStreamBuffer; xReturn = pdTRUE; } @@ -390,6 +527,8 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, xReturn = pdFALSE; } + traceRETURN_xStreamBufferGetStaticBuffers( xReturn ); + return xReturn; } #endif /* configSUPPORT_STATIC_ALLOCATION */ @@ -399,6 +538,8 @@ void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) { StreamBuffer_t * pxStreamBuffer = xStreamBuffer; + traceENTER_vStreamBufferDelete( xStreamBuffer ); + configASSERT( pxStreamBuffer ); traceSTREAM_BUFFER_DELETE( xStreamBuffer ); @@ -406,17 +547,17 @@ void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) pdFALSE ) { #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - { - /* Both the structure and the buffer were allocated using a single call - * to pvPortMalloc(), hence only one call to vPortFree() is required. */ - vPortFree( ( void * ) pxStreamBuffer ); /*lint !e9087 Standard free() semantics require void *, plus pxStreamBuffer was allocated by pvPortMalloc(). */ - } + { + /* Both the structure and the buffer were allocated using a single call + * to pvPortMalloc(), hence only one call to vPortFree() is required. */ + vPortFree( ( void * ) pxStreamBuffer ); + } #else - { - /* Should not be possible to get here, ucFlags must be corrupt. - * Force an assert. */ - configASSERT( xStreamBuffer == ( StreamBufferHandle_t ) ~0 ); - } + { + /* Should not be possible to get here, ucFlags must be corrupt. + * Force an assert. */ + configASSERT( xStreamBuffer == ( StreamBufferHandle_t ) ~0 ); + } #endif } else @@ -425,6 +566,8 @@ void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) * freed - just scrub the structure so future use will assert. */ ( void ) memset( pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) ); } + + traceRETURN_vStreamBufferDelete(); } /*-----------------------------------------------------------*/ @@ -432,47 +575,59 @@ BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) { StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; BaseType_t xReturn = pdFAIL; + StreamBufferCallbackFunction_t pxSendCallback = NULL, pxReceiveCallback = NULL; #if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxStreamBufferNumber; #endif + traceENTER_xStreamBufferReset( xStreamBuffer ); + configASSERT( pxStreamBuffer ); #if ( configUSE_TRACE_FACILITY == 1 ) - { - /* Store the stream buffer number so it can be restored after the - * reset. */ - uxStreamBufferNumber = pxStreamBuffer->uxStreamBufferNumber; - } + { + /* Store the stream buffer number so it can be restored after the + * reset. */ + uxStreamBufferNumber = pxStreamBuffer->uxStreamBufferNumber; + } #endif /* Can only reset a message buffer if there are no tasks blocked on it. */ taskENTER_CRITICAL(); { - if( pxStreamBuffer->xTaskWaitingToReceive == NULL ) + if( ( pxStreamBuffer->xTaskWaitingToReceive == NULL ) && ( pxStreamBuffer->xTaskWaitingToSend == NULL ) ) { - if( pxStreamBuffer->xTaskWaitingToSend == NULL ) + #if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) { - prvInitialiseNewStreamBuffer( pxStreamBuffer, - pxStreamBuffer->pucBuffer, - pxStreamBuffer->xLength, - pxStreamBuffer->xTriggerLevelBytes, - pxStreamBuffer->ucFlags ); - xReturn = pdPASS; - - #if ( configUSE_TRACE_FACILITY == 1 ) - { - pxStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber; - } - #endif - - traceSTREAM_BUFFER_RESET( xStreamBuffer ); + pxSendCallback = pxStreamBuffer->pxSendCompletedCallback; + pxReceiveCallback = pxStreamBuffer->pxReceiveCompletedCallback; } + #endif + + prvInitialiseNewStreamBuffer( pxStreamBuffer, + pxStreamBuffer->pucBuffer, + pxStreamBuffer->xLength, + pxStreamBuffer->xTriggerLevelBytes, + pxStreamBuffer->ucFlags, + pxSendCallback, + pxReceiveCallback ); + + #if ( configUSE_TRACE_FACILITY == 1 ) + { + pxStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber; + } + #endif + + traceSTREAM_BUFFER_RESET( xStreamBuffer ); + + xReturn = pdPASS; } } taskEXIT_CRITICAL(); + traceRETURN_xStreamBufferReset( xReturn ); + return xReturn; } /*-----------------------------------------------------------*/ @@ -483,6 +638,8 @@ BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; BaseType_t xReturn; + traceENTER_xStreamBufferSetTriggerLevel( xStreamBuffer, xTriggerLevel ); + configASSERT( pxStreamBuffer ); /* It is not valid for the trigger level to be 0. */ @@ -503,6 +660,8 @@ BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, xReturn = pdFALSE; } + traceRETURN_xStreamBufferSetTriggerLevel( xReturn ); + return xReturn; } /*-----------------------------------------------------------*/ @@ -511,11 +670,22 @@ size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) { const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; size_t xSpace; + size_t xOriginalTail; + + traceENTER_xStreamBufferSpacesAvailable( xStreamBuffer ); configASSERT( pxStreamBuffer ); - xSpace = pxStreamBuffer->xLength + pxStreamBuffer->xTail; - xSpace -= pxStreamBuffer->xHead; + /* The code below reads xTail and then xHead. This is safe if the stream + * buffer is updated once between the two reads - but not if the stream buffer + * is updated more than once between the two reads - hence the loop. */ + do + { + xOriginalTail = pxStreamBuffer->xTail; + xSpace = pxStreamBuffer->xLength + pxStreamBuffer->xTail; + xSpace -= pxStreamBuffer->xHead; + } while( xOriginalTail != pxStreamBuffer->xTail ); + xSpace -= ( size_t ) 1; if( xSpace >= pxStreamBuffer->xLength ) @@ -527,6 +697,8 @@ size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) mtCOVERAGE_TEST_MARKER(); } + traceRETURN_xStreamBufferSpacesAvailable( xSpace ); + return xSpace; } /*-----------------------------------------------------------*/ @@ -536,9 +708,14 @@ size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; size_t xReturn; + traceENTER_xStreamBufferBytesAvailable( xStreamBuffer ); + configASSERT( pxStreamBuffer ); xReturn = prvBytesInBuffer( pxStreamBuffer ); + + traceRETURN_xStreamBufferBytesAvailable( xReturn ); + return xReturn; } /*-----------------------------------------------------------*/ @@ -554,6 +731,8 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, TimeOut_t xTimeOut; size_t xMaxReportedSpace = 0; + traceENTER_xStreamBufferSend( xStreamBuffer, pvTxData, xDataLengthBytes, xTicksToWait ); + configASSERT( pvTxData ); configASSERT( pxStreamBuffer ); @@ -657,7 +836,7 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, /* Was a task waiting for the data? */ if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes ) { - sbSEND_COMPLETED( pxStreamBuffer ); + prvSEND_COMPLETED( pxStreamBuffer ); } else { @@ -670,6 +849,8 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer ); } + traceRETURN_xStreamBufferSend( xReturn ); + return xReturn; } /*-----------------------------------------------------------*/ @@ -683,6 +864,8 @@ size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, size_t xReturn, xSpace; size_t xRequiredSpace = xDataLengthBytes; + traceENTER_xStreamBufferSendFromISR( xStreamBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ); + configASSERT( pvTxData ); configASSERT( pxStreamBuffer ); @@ -707,7 +890,7 @@ size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, /* Was a task waiting for the data? */ if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes ) { - sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ); + prvSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ); } else { @@ -720,6 +903,7 @@ size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, } traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xReturn ); + traceRETURN_xStreamBufferSendFromISR( xReturn ); return xReturn; } @@ -731,49 +915,50 @@ static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer, size_t xSpace, size_t xRequiredSpace ) { - BaseType_t xShouldWrite; - size_t xReturn; + size_t xNextHead = pxStreamBuffer->xHead; + configMESSAGE_BUFFER_LENGTH_TYPE xMessageLength; - if( xSpace == ( size_t ) 0 ) + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) { - /* Doesn't matter if this is a stream buffer or a message buffer, there - * is no space to write. */ - xShouldWrite = pdFALSE; + /* This is a message buffer, as opposed to a stream buffer. */ + + /* Convert xDataLengthBytes to the message length type. */ + xMessageLength = ( configMESSAGE_BUFFER_LENGTH_TYPE ) xDataLengthBytes; + + /* Ensure the data length given fits within configMESSAGE_BUFFER_LENGTH_TYPE. */ + configASSERT( ( size_t ) xMessageLength == xDataLengthBytes ); + + if( xSpace >= xRequiredSpace ) + { + /* There is enough space to write both the message length and the message + * itself into the buffer. Start by writing the length of the data, the data + * itself will be written later in this function. */ + xNextHead = prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) &( xMessageLength ), sbBYTES_TO_STORE_MESSAGE_LENGTH, xNextHead ); + } + else + { + /* Not enough space, so do not write data to the buffer. */ + xDataLengthBytes = 0; + } } - else if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) == ( uint8_t ) 0 ) + else { /* This is a stream buffer, as opposed to a message buffer, so writing a - * stream of bytes rather than discrete messages. Write as many bytes as - * possible. */ - xShouldWrite = pdTRUE; + * stream of bytes rather than discrete messages. Plan to write as many + * bytes as possible. */ xDataLengthBytes = configMIN( xDataLengthBytes, xSpace ); } - else if( xSpace >= xRequiredSpace ) + + if( xDataLengthBytes != ( size_t ) 0 ) { - /* This is a message buffer, as opposed to a stream buffer, and there - * is enough space to write both the message length and the message itself - * into the buffer. Start by writing the length of the data, the data - * itself will be written later in this function. */ - xShouldWrite = pdTRUE; - ( void ) prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) &( xDataLengthBytes ), sbBYTES_TO_STORE_MESSAGE_LENGTH ); - } - else - { - /* There is space available, but not enough space. */ - xShouldWrite = pdFALSE; + /* Write the data to the buffer. */ + /* MISRA Ref 11.5.5 [Void pointer assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + pxStreamBuffer->xHead = prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) pvTxData, xDataLengthBytes, xNextHead ); } - if( xShouldWrite != pdFALSE ) - { - /* Writes the data itself. */ - xReturn = prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) pvTxData, xDataLengthBytes ); /*lint !e9079 Storage buffer is implemented as uint8_t for ease of sizing, alignment and access. */ - } - else - { - xReturn = 0; - } - - return xReturn; + return xDataLengthBytes; } /*-----------------------------------------------------------*/ @@ -785,6 +970,8 @@ size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength; + traceENTER_xStreamBufferReceive( xStreamBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ); + configASSERT( pvRxData ); configASSERT( pxStreamBuffer ); @@ -858,13 +1045,13 @@ size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, * read bytes from the buffer. */ if( xBytesAvailable > xBytesToStoreMessageLength ) { - xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength ); + xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable ); /* Was a task waiting for space in the buffer? */ if( xReceivedLength != ( size_t ) 0 ) { traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength ); - sbRECEIVE_COMPLETED( pxStreamBuffer ); + prvRECEIVE_COMPLETED( xStreamBuffer ); } else { @@ -877,6 +1064,8 @@ size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, mtCOVERAGE_TEST_MARKER(); } + traceRETURN_xStreamBufferReceive( xReceivedLength ); + return xReceivedLength; } /*-----------------------------------------------------------*/ @@ -884,9 +1073,11 @@ size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) { StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; - size_t xReturn, xBytesAvailable, xOriginalTail; + size_t xReturn, xBytesAvailable; configMESSAGE_BUFFER_LENGTH_TYPE xTempReturn; + traceENTER_xStreamBufferNextMessageLengthBytes( xStreamBuffer ); + configASSERT( pxStreamBuffer ); /* Ensure the stream buffer is being used as a message buffer. */ @@ -898,14 +1089,9 @@ size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) { /* The number of bytes available is greater than the number of bytes * required to hold the length of the next message, so another message - * is available. Return its length without removing the length bytes - * from the buffer. A copy of the tail is stored so the buffer can be - * returned to its prior state as the message is not actually being - * removed from the buffer. */ - xOriginalTail = pxStreamBuffer->xTail; - ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempReturn, sbBYTES_TO_STORE_MESSAGE_LENGTH, xBytesAvailable ); + * is available. */ + ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempReturn, sbBYTES_TO_STORE_MESSAGE_LENGTH, pxStreamBuffer->xTail ); xReturn = ( size_t ) xTempReturn; - pxStreamBuffer->xTail = xOriginalTail; } else { @@ -922,6 +1108,8 @@ size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) xReturn = 0; } + traceRETURN_xStreamBufferNextMessageLengthBytes( xReturn ); + return xReturn; } /*-----------------------------------------------------------*/ @@ -934,6 +1122,8 @@ size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength; + traceENTER_xStreamBufferReceiveFromISR( xStreamBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ); + configASSERT( pvRxData ); configASSERT( pxStreamBuffer ); @@ -960,12 +1150,12 @@ size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, * read bytes from the buffer. */ if( xBytesAvailable > xBytesToStoreMessageLength ) { - xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength ); + xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable ); /* Was a task waiting for space in the buffer? */ if( xReceivedLength != ( size_t ) 0 ) { - sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ); + prvRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ); } else { @@ -978,6 +1168,7 @@ size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, } traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength ); + traceRETURN_xStreamBufferReceiveFromISR( xReceivedLength ); return xReceivedLength; } @@ -986,34 +1177,28 @@ size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, static size_t prvReadMessageFromBuffer( StreamBuffer_t * pxStreamBuffer, void * pvRxData, size_t xBufferLengthBytes, - size_t xBytesAvailable, - size_t xBytesToStoreMessageLength ) + size_t xBytesAvailable ) { - size_t xOriginalTail, xReceivedLength, xNextMessageLength; + size_t xCount, xNextMessageLength; configMESSAGE_BUFFER_LENGTH_TYPE xTempNextMessageLength; + size_t xNextTail = pxStreamBuffer->xTail; - if( xBytesToStoreMessageLength != ( size_t ) 0 ) + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) { /* A discrete message is being received. First receive the length - * of the message. A copy of the tail is stored so the buffer can be - * returned to its prior state if the length of the message is too - * large for the provided buffer. */ - xOriginalTail = pxStreamBuffer->xTail; - ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempNextMessageLength, xBytesToStoreMessageLength, xBytesAvailable ); + * of the message. */ + xNextTail = prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempNextMessageLength, sbBYTES_TO_STORE_MESSAGE_LENGTH, xNextTail ); xNextMessageLength = ( size_t ) xTempNextMessageLength; /* Reduce the number of bytes available by the number of bytes just * read out. */ - xBytesAvailable -= xBytesToStoreMessageLength; + xBytesAvailable -= sbBYTES_TO_STORE_MESSAGE_LENGTH; /* Check there is enough space in the buffer provided by the * user. */ if( xNextMessageLength > xBufferLengthBytes ) { - /* The user has provided insufficient space to read the message - * so return the buffer to its previous state (so the length of - * the message is in the buffer again). */ - pxStreamBuffer->xTail = xOriginalTail; + /* The user has provided insufficient space to read the message. */ xNextMessageLength = 0; } else @@ -1028,10 +1213,19 @@ static size_t prvReadMessageFromBuffer( StreamBuffer_t * pxStreamBuffer, xNextMessageLength = xBufferLengthBytes; } - /* Read the actual data. */ - xReceivedLength = prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) pvRxData, xNextMessageLength, xBytesAvailable ); /*lint !e9079 Data storage area is implemented as uint8_t array for ease of sizing, indexing and alignment. */ + /* Use the minimum of the wanted bytes and the available bytes. */ + xCount = configMIN( xNextMessageLength, xBytesAvailable ); - return xReceivedLength; + if( xCount != ( size_t ) 0 ) + { + /* Read the actual data and update the tail to mark the data as officially consumed. */ + /* MISRA Ref 11.5.5 [Void pointer assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + pxStreamBuffer->xTail = prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) pvRxData, xCount, xNextTail ); + } + + return xCount; } /*-----------------------------------------------------------*/ @@ -1041,6 +1235,8 @@ BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) BaseType_t xReturn; size_t xTail; + traceENTER_xStreamBufferIsEmpty( xStreamBuffer ); + configASSERT( pxStreamBuffer ); /* True if no bytes are available. */ @@ -1055,6 +1251,8 @@ BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) xReturn = pdFALSE; } + traceRETURN_xStreamBufferIsEmpty( xReturn ); + return xReturn; } /*-----------------------------------------------------------*/ @@ -1065,6 +1263,8 @@ BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) size_t xBytesToStoreMessageLength; const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + traceENTER_xStreamBufferIsFull( xStreamBuffer ); + configASSERT( pxStreamBuffer ); /* This generic version of the receive function is used by both message @@ -1090,6 +1290,8 @@ BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) xReturn = pdFALSE; } + traceRETURN_xStreamBufferIsFull( xReturn ); + return xReturn; } /*-----------------------------------------------------------*/ @@ -1101,9 +1303,11 @@ BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer BaseType_t xReturn; UBaseType_t uxSavedInterruptStatus; + traceENTER_xStreamBufferSendCompletedFromISR( xStreamBuffer, pxHigherPriorityTaskWoken ); + configASSERT( pxStreamBuffer ); - uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); + uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); { if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL ) { @@ -1119,7 +1323,9 @@ BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer xReturn = pdFALSE; } } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); + + traceRETURN_xStreamBufferSendCompletedFromISR( xReturn ); return xReturn; } @@ -1132,9 +1338,11 @@ BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuf BaseType_t xReturn; UBaseType_t uxSavedInterruptStatus; + traceENTER_xStreamBufferReceiveCompletedFromISR( xStreamBuffer, pxHigherPriorityTaskWoken ); + configASSERT( pxStreamBuffer ); - uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); + uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); { if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) { @@ -1150,7 +1358,9 @@ BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuf xReturn = pdFALSE; } } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); + + traceRETURN_xStreamBufferReceiveCompletedFromISR( xReturn ); return xReturn; } @@ -1158,22 +1368,21 @@ BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuf static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, const uint8_t * pucData, - size_t xCount ) + size_t xCount, + size_t xHead ) { - size_t xNextHead, xFirstLength; + size_t xFirstLength; configASSERT( xCount > ( size_t ) 0 ); - xNextHead = pxStreamBuffer->xHead; - /* Calculate the number of bytes that can be added in the first write - * which may be less than the total number of bytes that need to be added if * the buffer will wrap back to the beginning. */ - xFirstLength = configMIN( pxStreamBuffer->xLength - xNextHead, xCount ); + xFirstLength = configMIN( pxStreamBuffer->xLength - xHead, xCount ); /* Write as many bytes as can be written in the first write. */ - configASSERT( ( xNextHead + xFirstLength ) <= pxStreamBuffer->xLength ); - ( void ) memcpy( ( void * ) ( &( pxStreamBuffer->pucBuffer[ xNextHead ] ) ), ( const void * ) pucData, xFirstLength ); /*lint !e9087 memcpy() requires void *. */ + configASSERT( ( xHead + xFirstLength ) <= pxStreamBuffer->xLength ); + ( void ) memcpy( ( void * ) ( &( pxStreamBuffer->pucBuffer[ xHead ] ) ), ( const void * ) pucData, xFirstLength ); /* If the number of bytes written was less than the number that could be * written in the first write... */ @@ -1181,85 +1390,69 @@ static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, { /* ...then write the remaining bytes to the start of the buffer. */ configASSERT( ( xCount - xFirstLength ) <= pxStreamBuffer->xLength ); - ( void ) memcpy( ( void * ) pxStreamBuffer->pucBuffer, ( const void * ) &( pucData[ xFirstLength ] ), xCount - xFirstLength ); /*lint !e9087 memcpy() requires void *. */ + ( void ) memcpy( ( void * ) pxStreamBuffer->pucBuffer, ( const void * ) &( pucData[ xFirstLength ] ), xCount - xFirstLength ); } else { mtCOVERAGE_TEST_MARKER(); } - xNextHead += xCount; + xHead += xCount; - if( xNextHead >= pxStreamBuffer->xLength ) + if( xHead >= pxStreamBuffer->xLength ) { - xNextHead -= pxStreamBuffer->xLength; + xHead -= pxStreamBuffer->xLength; } else { mtCOVERAGE_TEST_MARKER(); } - pxStreamBuffer->xHead = xNextHead; - - return xCount; + return xHead; } /*-----------------------------------------------------------*/ static size_t prvReadBytesFromBuffer( StreamBuffer_t * pxStreamBuffer, uint8_t * pucData, - size_t xMaxCount, - size_t xBytesAvailable ) + size_t xCount, + size_t xTail ) { - size_t xCount, xFirstLength, xNextTail; + size_t xFirstLength; - /* Use the minimum of the wanted bytes and the available bytes. */ - xCount = configMIN( xBytesAvailable, xMaxCount ); + configASSERT( xCount != ( size_t ) 0 ); - if( xCount > ( size_t ) 0 ) + /* Calculate the number of bytes that can be read - which may be + * less than the number wanted if the data wraps around to the start of + * the buffer. */ + xFirstLength = configMIN( pxStreamBuffer->xLength - xTail, xCount ); + + /* Obtain the number of bytes it is possible to obtain in the first + * read. Asserts check bounds of read and write. */ + configASSERT( xFirstLength <= xCount ); + configASSERT( ( xTail + xFirstLength ) <= pxStreamBuffer->xLength ); + ( void ) memcpy( ( void * ) pucData, ( const void * ) &( pxStreamBuffer->pucBuffer[ xTail ] ), xFirstLength ); + + /* If the total number of wanted bytes is greater than the number + * that could be read in the first read... */ + if( xCount > xFirstLength ) { - xNextTail = pxStreamBuffer->xTail; - - /* Calculate the number of bytes that can be read - which may be - * less than the number wanted if the data wraps around to the start of - * the buffer. */ - xFirstLength = configMIN( pxStreamBuffer->xLength - xNextTail, xCount ); - - /* Obtain the number of bytes it is possible to obtain in the first - * read. Asserts check bounds of read and write. */ - configASSERT( xFirstLength <= xMaxCount ); - configASSERT( ( xNextTail + xFirstLength ) <= pxStreamBuffer->xLength ); - ( void ) memcpy( ( void * ) pucData, ( const void * ) &( pxStreamBuffer->pucBuffer[ xNextTail ] ), xFirstLength ); /*lint !e9087 memcpy() requires void *. */ - - /* If the total number of wanted bytes is greater than the number - * that could be read in the first read... */ - if( xCount > xFirstLength ) - { - /*...then read the remaining bytes from the start of the buffer. */ - configASSERT( xCount <= xMaxCount ); - ( void ) memcpy( ( void * ) &( pucData[ xFirstLength ] ), ( void * ) ( pxStreamBuffer->pucBuffer ), xCount - xFirstLength ); /*lint !e9087 memcpy() requires void *. */ - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - /* Move the tail pointer to effectively remove the data read from - * the buffer. */ - xNextTail += xCount; - - if( xNextTail >= pxStreamBuffer->xLength ) - { - xNextTail -= pxStreamBuffer->xLength; - } - - pxStreamBuffer->xTail = xNextTail; + /* ...then read the remaining bytes from the start of the buffer. */ + ( void ) memcpy( ( void * ) &( pucData[ xFirstLength ] ), ( void * ) ( pxStreamBuffer->pucBuffer ), xCount - xFirstLength ); } else { mtCOVERAGE_TEST_MARKER(); } - return xCount; + /* Move the tail pointer to effectively remove the data read from the buffer. */ + xTail += xCount; + + if( xTail >= pxStreamBuffer->xLength ) + { + xTail -= pxStreamBuffer->xLength; + } + + return xTail; } /*-----------------------------------------------------------*/ @@ -1288,32 +1481,56 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, uint8_t * const pucBuffer, size_t xBufferSizeBytes, size_t xTriggerLevelBytes, - uint8_t ucFlags ) + uint8_t ucFlags, + StreamBufferCallbackFunction_t pxSendCompletedCallback, + StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) { /* Assert here is deliberately writing to the entire buffer to ensure it can * be written to without generating exceptions, and is setting the buffer to a * known value to assist in development/debugging. */ #if ( configASSERT_DEFINED == 1 ) - { - /* The value written just has to be identifiable when looking at the - * memory. Don't use 0xA5 as that is the stack fill value and could - * result in confusion as to what is actually being observed. */ - const BaseType_t xWriteValue = 0x55; - configASSERT( memset( pucBuffer, ( int ) xWriteValue, xBufferSizeBytes ) == pucBuffer ); - } /*lint !e529 !e438 xWriteValue is only used if configASSERT() is defined. */ + { + /* The value written just has to be identifiable when looking at the + * memory. Don't use 0xA5 as that is the stack fill value and could + * result in confusion as to what is actually being observed. */ + #define STREAM_BUFFER_BUFFER_WRITE_VALUE ( 0x55 ) + configASSERT( memset( pucBuffer, ( int ) STREAM_BUFFER_BUFFER_WRITE_VALUE, xBufferSizeBytes ) == pucBuffer ); + } #endif - ( void ) memset( ( void * ) pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) ); /*lint !e9087 memset() requires void *. */ + ( void ) memset( ( void * ) pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) ); pxStreamBuffer->pucBuffer = pucBuffer; pxStreamBuffer->xLength = xBufferSizeBytes; pxStreamBuffer->xTriggerLevelBytes = xTriggerLevelBytes; pxStreamBuffer->ucFlags = ucFlags; + #if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) + { + pxStreamBuffer->pxSendCompletedCallback = pxSendCompletedCallback; + pxStreamBuffer->pxReceiveCompletedCallback = pxReceiveCompletedCallback; + } + #else + { + /* MISRA Ref 11.1.1 [Object type casting] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-111 */ + /* coverity[misra_c_2012_rule_11_1_violation] */ + ( void ) pxSendCompletedCallback; + + /* MISRA Ref 11.1.1 [Object type casting] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-111 */ + /* coverity[misra_c_2012_rule_11_1_violation] */ + ( void ) pxReceiveCompletedCallback; + } + #endif /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */ } #if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer ) { + traceENTER_uxStreamBufferGetStreamBufferNumber( xStreamBuffer ); + + traceRETURN_uxStreamBufferGetStreamBufferNumber( xStreamBuffer->uxStreamBufferNumber ); + return xStreamBuffer->uxStreamBufferNumber; } @@ -1325,7 +1542,11 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer, UBaseType_t uxStreamBufferNumber ) { + traceENTER_vStreamBufferSetStreamBufferNumber( xStreamBuffer, uxStreamBufferNumber ); + xStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber; + + traceRETURN_vStreamBufferSetStreamBufferNumber(); } #endif /* configUSE_TRACE_FACILITY */ @@ -1335,7 +1556,11 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer ) { - return( xStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ); + traceENTER_ucStreamBufferGetStreamBufferType( xStreamBuffer ); + + traceRETURN_ucStreamBufferGetStreamBufferType( ( uint8_t ) ( xStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) ); + + return( ( uint8_t ) ( xStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) ); } #endif /* configUSE_TRACE_FACILITY */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/tasks.c b/components/freertos/FreeRTOS-Kernel-SMP/tasks.c index 254fc0a830..d021999871 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/tasks.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/tasks.c @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -39,19 +45,10 @@ #include "timers.h" #include "stack_macros.h" -#ifdef ESP_PLATFORM -#if ( configUSE_NEWLIB_REENTRANT == 1 ) -#include "esp_newlib.h" /* required for esp_reent_init() in tasks.c */ -#undef _REENT_INIT_PTR -#define _REENT_INIT_PTR esp_reent_init -#endif -#endif - -/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified - * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined +/* The MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined * for the header files above, but not in this file, in order to generate the * correct privileged Vs unprivileged linkage and placement. */ -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting * functions but without including stdio.h here. */ @@ -68,10 +65,45 @@ /* If the cooperative scheduler is being used then a yield should not be * performed just because a higher priority task has been woken. */ - #define taskYIELD_IF_USING_PREEMPTION() + #define taskYIELD_TASK_CORE_IF_USING_PREEMPTION( pxTCB ) + #define taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB ) #else - #define taskYIELD_IF_USING_PREEMPTION() vTaskYieldWithinAPI() -#endif + + #if ( configNUMBER_OF_CORES == 1 ) + +/* This macro requests the running task pxTCB to yield. In single core + * scheduler, a running task always runs on core 0 and portYIELD_WITHIN_API() + * can be used to request the task running on core 0 to yield. Therefore, pxTCB + * is not used in this macro. */ + #define taskYIELD_TASK_CORE_IF_USING_PREEMPTION( pxTCB ) \ + do { \ + ( void ) ( pxTCB ); \ + portYIELD_WITHIN_API(); \ + } while( 0 ) + + #define taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB ) \ + do { \ + if( pxCurrentTCB->uxPriority < ( pxTCB )->uxPriority ) \ + { \ + portYIELD_WITHIN_API(); \ + } \ + else \ + { \ + mtCOVERAGE_TEST_MARKER(); \ + } \ + } while( 0 ) + + #else /* if ( configNUMBER_OF_CORES == 1 ) */ + +/* Yield the core on which this task is running. */ + #define taskYIELD_TASK_CORE_IF_USING_PREEMPTION( pxTCB ) prvYieldCore( ( pxTCB )->xTaskRunState ) + +/* Yield for the task if a running task has priority lower than this task. */ + #define taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB ) prvYieldForTask( pxTCB ) + + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ + +#endif /* if ( configUSE_PREEMPTION == 0 ) */ /* Values that can be assigned to the ucNotifyState member of the TCB. */ #define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 ) /* Must be zero as it is the initialised value. */ @@ -130,14 +162,39 @@ /* uxTopReadyPriority holds the priority of the highest priority ready * state task. */ #define taskRECORD_READY_PRIORITY( uxPriority ) \ - { \ + do { \ if( ( uxPriority ) > uxTopReadyPriority ) \ { \ uxTopReadyPriority = ( uxPriority ); \ } \ - } /* taskRECORD_READY_PRIORITY */ + } while( 0 ) /* taskRECORD_READY_PRIORITY */ - /*-----------------------------------------------------------*/ +/*-----------------------------------------------------------*/ + + #if ( configNUMBER_OF_CORES == 1 ) + #define taskSELECT_HIGHEST_PRIORITY_TASK() \ + do { \ + UBaseType_t uxTopPriority = uxTopReadyPriority; \ + \ + /* Find the highest priority queue that contains ready tasks. */ \ + while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \ + { \ + configASSERT( uxTopPriority ); \ + --uxTopPriority; \ + } \ + \ + /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \ + * the same priority get an equal share of the processor time. */ \ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \ + uxTopReadyPriority = uxTopPriority; \ + } while( 0 ) /* taskSELECT_HIGHEST_PRIORITY_TASK */ + #else /* if ( configNUMBER_OF_CORES == 1 ) */ + + #define taskSELECT_HIGHEST_PRIORITY_TASK( xCoreID ) prvSelectHighestPriorityTask( xCoreID ) + + #endif /* if ( configNUMBER_OF_CORES == 1 ) */ + +/*-----------------------------------------------------------*/ /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as * they are only required when a port optimised method of task selection is @@ -147,27 +204,37 @@ #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ - #error configUSE_PORT_OPTIMISED_TASK_SELECTION not yet supported in SMP - /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is * performed in a way that is tailored to the particular microcontroller * architecture being used. */ /* A port optimised version is provided. Call the port defined macros. */ - #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority ) + #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( ( uxPriority ), uxTopReadyPriority ) - /*-----------------------------------------------------------*/ +/*-----------------------------------------------------------*/ + + #define taskSELECT_HIGHEST_PRIORITY_TASK() \ + do { \ + UBaseType_t uxTopPriority; \ + \ + /* Find the highest priority list that contains ready tasks. */ \ + portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \ + configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \ + } while( 0 ) + +/*-----------------------------------------------------------*/ /* A port optimised version is provided, call it only if the TCB being reset * is being referenced from a ready list. If it is referenced from a delayed * or suspended list then it won't be in a ready list. */ #define taskRESET_READY_PRIORITY( uxPriority ) \ - { \ + do { \ if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \ { \ portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \ } \ - } + } while( 0 ) #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ @@ -176,7 +243,7 @@ /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick * count overflows. */ #define taskSWITCH_DELAYED_LISTS() \ - { \ + do { \ List_t * pxTemp; \ \ /* The delayed tasks list should be empty when the lists are switched. */ \ @@ -187,7 +254,7 @@ pxOverflowDelayedTaskList = pxTemp; \ xNumOfOverflows++; \ prvResetNextTaskUnblockTime(); \ - } + } while( 0 ) /*-----------------------------------------------------------*/ @@ -195,11 +262,13 @@ * Place the task represented by pxTCB into the appropriate ready list for * the task. It is inserted at the end of the list. */ -#define prvAddTaskToReadyList( pxTCB ) \ - traceMOVED_TASK_TO_READY_STATE( pxTCB ); \ - taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \ - vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \ - tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB ) +#define prvAddTaskToReadyList( pxTCB ) \ + do { \ + traceMOVED_TASK_TO_READY_STATE( pxTCB ); \ + taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \ + listINSERT_END( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \ + tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB ); \ + } while( 0 ) /*-----------------------------------------------------------*/ /* @@ -218,22 +287,65 @@ * the scheduler that the value should not be changed - in which case it is the * responsibility of whichever module is using the value to ensure it gets set back * to its original value when it is released. */ -#if ( configUSE_16_BIT_TICKS == 1 ) - #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U -#else - #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + #define taskEVENT_LIST_ITEM_VALUE_IN_USE ( ( uint16_t ) 0x8000U ) +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + #define taskEVENT_LIST_ITEM_VALUE_IN_USE ( ( uint32_t ) 0x80000000UL ) +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_64_BITS ) + #define taskEVENT_LIST_ITEM_VALUE_IN_USE ( ( uint64_t ) 0x8000000000000000ULL ) #endif /* Indicates that the task is not actively running on any core. */ -#define taskTASK_NOT_RUNNING ( TaskRunning_t ) ( -1 ) +#define taskTASK_NOT_RUNNING ( ( BaseType_t ) ( -1 ) ) /* Indicates that the task is actively running but scheduled to yield. */ -#define taskTASK_YIELDING ( TaskRunning_t ) ( -2 ) +#define taskTASK_SCHEDULED_TO_YIELD ( ( BaseType_t ) ( -2 ) ) /* Returns pdTRUE if the task is actively running and not scheduled to yield. */ -#define taskTASK_IS_RUNNING( xTaskRunState ) ( ( 0 <= xTaskRunState ) && ( xTaskRunState < configNUM_CORES ) ) +#if ( configNUMBER_OF_CORES == 1 ) + #define taskTASK_IS_RUNNING( pxTCB ) ( ( ( pxTCB ) == pxCurrentTCB ) ? ( pdTRUE ) : ( pdFALSE ) ) + #define taskTASK_IS_RUNNING_OR_SCHEDULED_TO_YIELD( pxTCB ) ( ( ( pxTCB ) == pxCurrentTCB ) ? ( pdTRUE ) : ( pdFALSE ) ) +#else + #define taskTASK_IS_RUNNING( pxTCB ) ( ( ( ( pxTCB )->xTaskRunState >= ( BaseType_t ) 0 ) && ( ( pxTCB )->xTaskRunState < ( BaseType_t ) configNUMBER_OF_CORES ) ) ? ( pdTRUE ) : ( pdFALSE ) ) + #define taskTASK_IS_RUNNING_OR_SCHEDULED_TO_YIELD( pxTCB ) ( ( ( pxTCB )->xTaskRunState != taskTASK_NOT_RUNNING ) ? ( pdTRUE ) : ( pdFALSE ) ) +#endif -typedef BaseType_t TaskRunning_t; +/* Indicates that the task is an Idle task. */ +#define taskATTRIBUTE_IS_IDLE ( UBaseType_t ) ( 1UL << 0UL ) + +#if ( ( configNUMBER_OF_CORES > 1 ) && ( portCRITICAL_NESTING_IN_TCB == 1 ) ) + #define portGET_CRITICAL_NESTING_COUNT() ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxCriticalNesting ) + #define portSET_CRITICAL_NESTING_COUNT( x ) ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxCriticalNesting = ( x ) ) + #define portINCREMENT_CRITICAL_NESTING_COUNT() ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxCriticalNesting++ ) + #define portDECREMENT_CRITICAL_NESTING_COUNT() ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxCriticalNesting-- ) +#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( portCRITICAL_NESTING_IN_TCB == 1 ) ) */ + +#define taskBITS_PER_BYTE ( ( size_t ) 8 ) + +#if ( configNUMBER_OF_CORES > 1 ) + +/* Yields the given core. This must be called from a critical section and xCoreID + * must be valid. This macro is not required in single core since there is only + * one core to yield. */ + #define prvYieldCore( xCoreID ) \ + do { \ + if( ( xCoreID ) == ( BaseType_t ) portGET_CORE_ID() ) \ + { \ + /* Pending a yield for this core since it is in the critical section. */ \ + xYieldPendings[ ( xCoreID ) ] = pdTRUE; \ + } \ + else \ + { \ + /* Request other core to yield if it is not requested before. */ \ + if( pxCurrentTCBs[ ( xCoreID ) ]->xTaskRunState != taskTASK_SCHEDULED_TO_YIELD ) \ + { \ + portYIELD_CORE( xCoreID ); \ + pxCurrentTCBs[ ( xCoreID ) ]->xTaskRunState = taskTASK_SCHEDULED_TO_YIELD; \ + } \ + } \ + } while( 0 ) +#endif /* #if ( configNUMBER_OF_CORES > 1 ) */ +/*-----------------------------------------------------------*/ /* * Task control block. A task control block (TCB) is allocated for each task, @@ -242,43 +354,45 @@ typedef BaseType_t TaskRunning_t; */ typedef struct tskTaskControlBlock /* The old naming convention is used to prevent breaking kernel aware debuggers. */ { - volatile StackType_t * pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */ + volatile StackType_t * pxTopOfStack; /**< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */ #if ( portUSING_MPU_WRAPPERS == 1 ) - xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */ + xMPU_SETTINGS xMPUSettings; /**< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */ #endif - #if ( configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 ) - UBaseType_t uxCoreAffinityMask; /*< Used to link the task to certain cores. UBaseType_t must have >= the same number of bits as SMP confNUM_CORES */ + #if ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) + UBaseType_t uxCoreAffinityMask; /**< Used to link the task to certain cores. UBaseType_t must have greater than or equal to the number of bits as configNUMBER_OF_CORES. */ #endif - ListItem_t xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */ - ListItem_t xEventListItem; /*< Used to reference a task from an event list. */ - UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */ - StackType_t * pxStack; /*< Points to the start of the stack. */ - volatile TaskRunning_t xTaskRunState; /*< Used to identify the core the task is running on, if any. */ - BaseType_t xIsIdle; /*< Used to identify the idle tasks. */ - char pcTaskName[ configMAX_TASK_NAME_LEN ]; /*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + ListItem_t xStateListItem; /**< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */ + ListItem_t xEventListItem; /**< Used to reference a task from an event list. */ + UBaseType_t uxPriority; /**< The priority of the task. 0 is the lowest priority. */ + StackType_t * pxStack; /**< Points to the start of the stack. */ + #if ( configNUMBER_OF_CORES > 1 ) + volatile BaseType_t xTaskRunState; /**< Used to identify the core the task is running on, if the task is running. Otherwise, identifies the task's state - not running or yielding. */ + UBaseType_t uxTaskAttributes; /**< Task's attributes - currently used to identify the idle tasks. */ + #endif + char pcTaskName[ configMAX_TASK_NAME_LEN ]; /**< Descriptive name given to the task when created. Facilitates debugging only. */ #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - BaseType_t xPreemptionDisable; /*< Used to prevent the task from being preempted */ + BaseType_t xPreemptionDisable; /**< Used to prevent the task from being preempted. */ #endif #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) - StackType_t * pxEndOfStack; /*< Points to the highest valid address for the stack. */ + StackType_t * pxEndOfStack; /**< Points to the highest valid address for the stack. */ #endif #if ( portCRITICAL_NESTING_IN_TCB == 1 ) - UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */ + UBaseType_t uxCriticalNesting; /**< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */ #endif #if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */ - UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */ + UBaseType_t uxTCBNumber; /**< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */ + UBaseType_t uxTaskNumber; /**< Stores a number specifically for use by third party trace code. */ #endif #if ( configUSE_MUTEXES == 1 ) - UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ + UBaseType_t uxBasePriority; /**< The priority last assigned to the task - used by the priority inheritance mechanism. */ UBaseType_t uxMutexesHeld; #endif @@ -291,21 +405,11 @@ typedef struct tskTaskControlBlock /* The old naming convention is used to #endif #if ( configGENERATE_RUN_TIME_STATS == 1 ) - uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */ + configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /**< Stores the amount of time the task has spent in the Running state. */ #endif - #if ( configUSE_NEWLIB_REENTRANT == 1 ) - /* Allocate a Newlib reent structure that is specific to this task. - * Note Newlib support has been included by popular demand, but is not - * used by the FreeRTOS maintainers themselves. FreeRTOS is not - * responsible for resulting newlib operation. User must be familiar with - * newlib and must provide system-wide implementations of the necessary - * stubs. Be warned that (at the time of writing) the current newlib design - * implements a system-wide malloc() that must be provided with locks. - * - * See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html - * for additional information. */ - struct _reent xNewLib_reent; + #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) + configTLS_BLOCK_TYPE xTLSBlock; /**< Memory block used as Thread Local Storage (TLS) Block for the task. */ #endif #if ( configUSE_TASK_NOTIFICATIONS == 1 ) @@ -315,8 +419,8 @@ typedef struct tskTaskControlBlock /* The old naming convention is used to /* See the comments in FreeRTOS.h with the definition of * tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */ - #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */ - uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */ + #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) + uint8_t ucStaticallyAllocated; /**< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */ #endif #if ( INCLUDE_xTaskAbortDelay == 1 ) @@ -332,32 +436,40 @@ typedef struct tskTaskControlBlock /* The old naming convention is used to * below to enable the use of older kernel aware debuggers. */ typedef tskTCB TCB_t; -/*lint -save -e956 A manual analysis and inspection has been used to determine - * which static variables must be declared volatile. */ -PRIVILEGED_DATA TCB_t * volatile pxCurrentTCBs[ configNUM_CORES ] = { NULL }; -#define pxCurrentTCB xTaskGetCurrentTaskHandle() +#if ( configNUMBER_OF_CORES == 1 ) + /* MISRA Ref 8.4.1 [Declaration shall be visible] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-84 */ + /* coverity[misra_c_2012_rule_8_4_violation] */ + portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL; +#else + /* MISRA Ref 8.4.1 [Declaration shall be visible] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-84 */ + /* coverity[misra_c_2012_rule_8_4_violation] */ + portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCBs[ configNUMBER_OF_CORES ]; + #define pxCurrentTCB xTaskGetCurrentTaskHandle() +#endif /* Lists for ready and blocked tasks. -------------------- * xDelayedTaskList1 and xDelayedTaskList2 could be moved to function scope but * doing so breaks some kernel aware debuggers and debuggers that rely on removing * the static qualifier. */ -PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */ -PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */ -PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ -PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */ -PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */ -PRIVILEGED_DATA static List_t xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */ +PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; /**< Prioritised ready tasks. */ +PRIVILEGED_DATA static List_t xDelayedTaskList1; /**< Delayed tasks. */ +PRIVILEGED_DATA static List_t xDelayedTaskList2; /**< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ +PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /**< Points to the delayed task list currently being used. */ +PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /**< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */ +PRIVILEGED_DATA static List_t xPendingReadyList; /**< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */ #if ( INCLUDE_vTaskDelete == 1 ) - PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */ + PRIVILEGED_DATA static List_t xTasksWaitingTermination; /**< Tasks that have been deleted - but their memory not yet freed. */ PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U; #endif #if ( INCLUDE_vTaskSuspend == 1 ) - PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */ + PRIVILEGED_DATA static List_t xSuspendedTaskList; /**< Tasks that are currently suspended. */ #endif @@ -371,28 +483,18 @@ PRIVILEGED_DATA static List_t xPendingReadyList; /*< Tas PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U; PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT; PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY; -#if ( ( ESP_PLATFORM == 1 ) && ( configNUM_CORES > 1 ) ) -/* -Workaround for non-thread safe multi-core OS startup (see IDF-4524) -*/ -PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunningPerCore[ configNUM_CORES ] = { pdFALSE }; -#define xSchedulerRunning xSchedulerRunningPerCore[ portGET_CORE_ID() ] -#else // ( ESP_PLATFORM == 1 ) && ( configNUM_CORES > 1 ) PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE; -#endif // ( ESP_PLATFORM == 1 ) && ( configNUM_CORES > 1 ) PRIVILEGED_DATA static volatile TickType_t xPendedTicks = ( TickType_t ) 0U; -PRIVILEGED_DATA static volatile BaseType_t xYieldPendings[ configNUM_CORES ] = { pdFALSE }; +PRIVILEGED_DATA static volatile BaseType_t xYieldPendings[ configNUMBER_OF_CORES ] = { pdFALSE }; PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0; PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U; PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */ -PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle[ configNUM_CORES ] = { NULL }; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */ - -#define xYieldPending prvGetCurrentYieldPending() +PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandles[ configNUMBER_OF_CORES ]; /**< Holds the handles of the idle tasks. The idle tasks are created automatically when the scheduler is started. */ /* Improve support for OpenOCD. The kernel tracks Ready tasks via priority lists. * For tracking the state of remote threads, OpenOCD uses uxTopUsedPriority * to determine the number of priority lists to read back from the remote target. */ -const volatile UBaseType_t uxTopUsedPriority = configMAX_PRIORITIES - 1U; +static const volatile UBaseType_t uxTopUsedPriority = configMAX_PRIORITIES - 1U; /* Context switches are held pending while the scheduler is suspended. Also, * interrupts must not manipulate the xStateListItem of a TCB, or any of the @@ -403,58 +505,54 @@ const volatile UBaseType_t uxTopUsedPriority = configMAX_PRIORITIES - 1U; * when the scheduler is unsuspended. The pending ready list itself can only be * accessed from a critical section. * - * Updates to uxSchedulerSuspended must be protected by both the task and ISR locks and - * must not be done by an ISR. Reads must be protected by either lock and may be done by - * either an ISR or a task. */ -PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE; + * Updates to uxSchedulerSuspended must be protected by both the task lock and the ISR lock + * and must not be done from an ISR. Reads must be protected by either lock and may be done + * from either an ISR or a task. */ +PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) 0U; #if ( configGENERATE_RUN_TIME_STATS == 1 ) /* Do not move these variables to function scope as doing so prevents the * code working with debuggers that need to remove the static qualifier. */ - PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */ - PRIVILEGED_DATA static volatile uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */ +PRIVILEGED_DATA static configRUN_TIME_COUNTER_TYPE ulTaskSwitchedInTime[ configNUMBER_OF_CORES ] = { 0U }; /**< Holds the value of a timer/counter the last time a task was switched in. */ +PRIVILEGED_DATA static volatile configRUN_TIME_COUNTER_TYPE ulTotalRunTime[ configNUMBER_OF_CORES ] = { 0U }; /**< Holds the total amount of execution time as defined by the run time counter clock. */ #endif -/*lint -restore */ - /*-----------------------------------------------------------*/ /* File private functions. --------------------------------*/ /* - * Creates the idle tasks during scheduler start + * Creates the idle tasks during scheduler start. */ static BaseType_t prvCreateIdleTasks( void ); -/* - * Returns the yield pending count for the calling core. - */ -static BaseType_t prvGetCurrentYieldPending( void ); +#if ( configNUMBER_OF_CORES > 1 ) /* * Checks to see if another task moved the current task out of the ready - * list while it was waiting to enter a critical section and yields if so. + * list while it was waiting to enter a critical section and yields, if so. */ -static void prvCheckForRunStateChange( void ); + static void prvCheckForRunStateChange( void ); +#endif /* #if ( configNUMBER_OF_CORES > 1 ) */ -/* - * Yields the given core. - */ -static void prvYieldCore( BaseType_t xCoreID ); +#if ( configNUMBER_OF_CORES > 1 ) /* * Yields a core, or cores if multiple priorities are not allowed to run * simultaneously, to allow the task pxTCB to run. */ -static void prvYieldForTask( TCB_t * pxTCB, - const BaseType_t xPreemptEqualPriority ); + static void prvYieldForTask( const TCB_t * pxTCB ); +#endif /* #if ( configNUMBER_OF_CORES > 1 ) */ + +#if ( configNUMBER_OF_CORES > 1 ) /* - * Selects the highest priority available task + * Selects the highest priority available task for the given core. */ -static BaseType_t prvSelectHighestPriorityTask( const BaseType_t xCoreID ); + static void prvSelectHighestPriorityTask( BaseType_t xCoreID ); +#endif /* #if ( configNUMBER_OF_CORES > 1 ) */ /** * Utility task that simply returns pdTRUE if the task referenced by xTask is @@ -478,10 +576,20 @@ static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION; * The idle task is automatically created and added to the ready lists upon * creation of the first user task. * + * In the FreeRTOS SMP, configNUMBER_OF_CORES - 1 passive idle tasks are also + * created to ensure that each core has an idle task to run when no other + * task is available to run. + * + * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific + * language extensions. The equivalent prototype for these functions are: + * + * void prvIdleTask( void *pvParameters ); + * void prvPassiveIdleTask( void *pvParameters ); + * */ static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ) PRIVILEGED_FUNCTION; -#if ( configNUM_CORES > 1 ) - static portTASK_FUNCTION_PROTO( prvMinimalIdleTask, pvParameters ) PRIVILEGED_FUNCTION; +#if ( configNUMBER_OF_CORES > 1 ) + static portTASK_FUNCTION_PROTO( prvPassiveIdleTask, pvParameters ) PRIVILEGED_FUNCTION; #endif /* @@ -570,7 +678,7 @@ static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, */ static void prvResetNextTaskUnblockTime( void ) PRIVILEGED_FUNCTION; -#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) +#if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) /* * Helper function used to pad task names with spaces when printing out @@ -586,7 +694,7 @@ static void prvResetNextTaskUnblockTime( void ) PRIVILEGED_FUNCTION; * dynamically to fill in the structure's members. */ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, - const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, @@ -600,6 +708,53 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, */ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION; +/* + * Create a task with static buffer for both TCB and stack. Returns a handle to + * the task if it is created successfully. Otherwise, returns NULL. + */ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + static TCB_t * prvCreateStaticTask( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + StackType_t * const puxStackBuffer, + StaticTask_t * const pxTaskBuffer, + TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION; +#endif /* #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ + +/* + * Create a restricted task with static buffer for both TCB and stack. Returns + * a handle to the task if it is created successfully. Otherwise, returns NULL. + */ +#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + static TCB_t * prvCreateRestrictedStaticTask( const TaskParameters_t * const pxTaskDefinition, + TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION; +#endif /* #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) */ + +/* + * Create a restricted task with static buffer for task stack and allocated buffer + * for TCB. Returns a handle to the task if it is created successfully. Otherwise, + * returns NULL. + */ +#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + static TCB_t * prvCreateRestrictedTask( const TaskParameters_t * const pxTaskDefinition, + TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION; +#endif /* #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */ + +/* + * Create a task with allocated buffer for both TCB and stack. Returns a handle to + * the task if it is created successfully. Otherwise, returns NULL. + */ +#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + static TCB_t * prvCreateTask( TaskFunction_t pxTaskCode, + const char * const pcName, + const configSTACK_DEPTH_TYPE usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION; +#endif /* #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) */ + /* * freertos_tasks_c_additions_init() should only be called if the user definable * macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is the only macro @@ -611,39 +766,52 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION; #endif +#if ( configUSE_PASSIVE_IDLE_HOOK == 1 ) + extern void vApplicationPassiveIdleHook( void ); +#endif /* #if ( configUSE_PASSIVE_IDLE_HOOK == 1 ) */ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) + +/* + * Convert the snprintf return value to the number of characters + * written. The following are the possible cases: + * + * 1. The buffer supplied to snprintf is large enough to hold the + * generated string. The return value in this case is the number + * of characters actually written, not counting the terminating + * null character. + * 2. The buffer supplied to snprintf is NOT large enough to hold + * the generated string. The return value in this case is the + * number of characters that would have been written if the + * buffer had been sufficiently large, not counting the + * terminating null character. + * 3. Encoding error. The return value in this case is a negative + * number. + * + * From 1 and 2 above ==> Only when the return value is non-negative + * and less than the supplied buffer length, the string has been + * completely written. + */ + static size_t prvSnprintfReturnValueToCharsWritten( int iSnprintfReturnValue, + size_t n ); + +#endif /* #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */ /*-----------------------------------------------------------*/ -static BaseType_t prvGetCurrentYieldPending( void ) -{ - BaseType_t xReturn; - UBaseType_t ulState; - - ulState = portDISABLE_INTERRUPTS(); - xReturn = xYieldPendings[ portGET_CORE_ID() ]; - portRESTORE_INTERRUPTS( ulState ); - - return xReturn; -} - -/*-----------------------------------------------------------*/ - -static void prvCheckForRunStateChange( void ) -{ - UBaseType_t uxPrevCriticalNesting; - UBaseType_t uxPrevSchedulerSuspended; - TCB_t * pxThisTCB; - - /* This should be skipped when entering a critical section within - * an ISR. If the task on the current core is no longer running, then - * vTaskSwitchContext() probably should be run before returning, but - * we don't have a way to force that to happen from here. */ - if( portCHECK_IF_IN_ISR() == pdFALSE ) +#if ( configNUMBER_OF_CORES > 1 ) + static void prvCheckForRunStateChange( void ) { + UBaseType_t uxPrevCriticalNesting; + const TCB_t * pxThisTCB; + + /* This must only be called from within a task. */ + portASSERT_IF_IN_ISR(); + /* This function is always called with interrupts disabled * so this is safe. */ pxThisTCB = pxCurrentTCBs[ portGET_CORE_ID() ]; - while( pxThisTCB->xTaskRunState == taskTASK_YIELDING ) + while( pxThisTCB->xTaskRunState == taskTASK_SCHEDULED_TO_YIELD ) { /* We are only here if we just entered a critical section * or if we just suspended the scheduler, and another task @@ -651,518 +819,569 @@ static void prvCheckForRunStateChange( void ) * * This is slightly complicated since we need to save and restore * the suspension and critical nesting counts, as well as release - * and reacquire the correct locks. And then do it all over again + * and reacquire the correct locks. And then, do it all over again * if our state changed again during the reacquisition. */ - - uxPrevCriticalNesting = pxThisTCB->uxCriticalNesting; - uxPrevSchedulerSuspended = uxSchedulerSuspended; - - /* this must only be called the first time we enter into a critical - * section, otherwise it could context switch in the middle of a - * critical section. */ - configASSERT( uxPrevCriticalNesting + uxPrevSchedulerSuspended == 1U ); - - uxSchedulerSuspended = 0U; + uxPrevCriticalNesting = portGET_CRITICAL_NESTING_COUNT(); if( uxPrevCriticalNesting > 0U ) { - pxThisTCB->uxCriticalNesting = 0U; + portSET_CRITICAL_NESTING_COUNT( 0U ); portRELEASE_ISR_LOCK(); - portRELEASE_TASK_LOCK(); } else { - /* uxPrevSchedulerSuspended must be 1 */ - portRELEASE_TASK_LOCK(); + /* The scheduler is suspended. uxSchedulerSuspended is updated + * only when the task is not requested to yield. */ + mtCOVERAGE_TEST_MARKER(); } + portRELEASE_TASK_LOCK(); portMEMORY_BARRIER(); - configASSERT( pxThisTCB->xTaskRunState == taskTASK_YIELDING ); + configASSERT( pxThisTCB->xTaskRunState == taskTASK_SCHEDULED_TO_YIELD ); portENABLE_INTERRUPTS(); /* Enabling interrupts should cause this core to immediately * service the pending interrupt and yield. If the run state is still * yielding here then that is a problem. */ - configASSERT( pxThisTCB->xTaskRunState != taskTASK_YIELDING ); + configASSERT( pxThisTCB->xTaskRunState != taskTASK_SCHEDULED_TO_YIELD ); portDISABLE_INTERRUPTS(); portGET_TASK_LOCK(); portGET_ISR_LOCK(); - pxCurrentTCB->uxCriticalNesting = uxPrevCriticalNesting; - uxSchedulerSuspended = uxPrevSchedulerSuspended; + + portSET_CRITICAL_NESTING_COUNT( uxPrevCriticalNesting ); if( uxPrevCriticalNesting == 0U ) { - /* uxPrevSchedulerSuspended must be 1 */ - configASSERT( uxPrevSchedulerSuspended != ( UBaseType_t ) pdFALSE ); portRELEASE_ISR_LOCK(); } } } -} +#endif /* #if ( configNUMBER_OF_CORES > 1 ) */ /*-----------------------------------------------------------*/ -static void prvYieldCore( BaseType_t xCoreID ) -{ - /* This must be called from a critical section and - * xCoreID must be valid. */ - - if( portCHECK_IF_IN_ISR() && ( xCoreID == portGET_CORE_ID() ) ) +#if ( configNUMBER_OF_CORES > 1 ) + static void prvYieldForTask( const TCB_t * pxTCB ) { - xYieldPendings[ xCoreID ] = pdTRUE; - } - else if( pxCurrentTCBs[ xCoreID ]->xTaskRunState != taskTASK_YIELDING ) - { - if( xCoreID == portGET_CORE_ID() ) - { - xYieldPendings[ xCoreID ] = pdTRUE; - } - #if ( configNUM_CORES > 1 ) - else - { - portYIELD_CORE( xCoreID ); - pxCurrentTCBs[ xCoreID ]->xTaskRunState = taskTASK_YIELDING; - } - #endif - } -} + BaseType_t xLowestPriorityToPreempt; + BaseType_t xCurrentCoreTaskPriority; + BaseType_t xLowestPriorityCore = ( BaseType_t ) -1; + BaseType_t xCoreID; -/*-----------------------------------------------------------*/ + #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) + BaseType_t xYieldCount = 0; + #endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */ -static void prvYieldForTask( TCB_t * pxTCB, - const BaseType_t xPreemptEqualPriority ) -{ - BaseType_t xLowestPriority; - BaseType_t xTaskPriority; - BaseType_t xLowestPriorityCore = -1; - BaseType_t xYieldCount = 0; - BaseType_t x; - TaskRunning_t xTaskRunState; + /* This must be called from a critical section. */ + configASSERT( portGET_CRITICAL_NESTING_COUNT() > 0U ); - /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION */ + #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) - configASSERT( pxCurrentTCB->uxCriticalNesting > 0U ); - - #if ( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configNUM_CORES > 1 ) ) - { /* No task should yield for this one if it is a lower priority * than priority level of currently ready tasks. */ - if( pxTCB->uxPriority < uxTopReadyPriority ) - { - return; - } - } - #endif - - xLowestPriority = ( BaseType_t ) pxTCB->uxPriority; - - if( xPreemptEqualPriority == pdFALSE ) - { - /* xLowestPriority will be decremented to -1 if the priority of pxTCB - * is 0. This is ok as we will give system idle tasks a priority of -1 below. */ - --xLowestPriority; - } - - for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configNUM_CORES; x++ ) - { - /* System idle tasks are being assigned a priority of tskIDLE_PRIORITY - 1 here */ - xTaskPriority = ( BaseType_t ) pxCurrentTCBs[ x ]->uxPriority - pxCurrentTCBs[ x ]->xIsIdle; - xTaskRunState = pxCurrentTCBs[ x ]->xTaskRunState; - - if( ( taskTASK_IS_RUNNING( xTaskRunState ) != pdFALSE ) && ( xYieldPendings[ x ] == pdFALSE ) ) + if( pxTCB->uxPriority >= uxTopReadyPriority ) + #else + /* Yield is not required for a task which is already running. */ + if( taskTASK_IS_RUNNING( pxTCB ) == pdFALSE ) + #endif { - if( xTaskPriority <= xLowestPriority ) + xLowestPriorityToPreempt = ( BaseType_t ) pxTCB->uxPriority; + + /* xLowestPriorityToPreempt will be decremented to -1 if the priority of pxTCB + * is 0. This is ok as we will give system idle tasks a priority of -1 below. */ + --xLowestPriorityToPreempt; + + for( xCoreID = ( BaseType_t ) 0; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES; xCoreID++ ) { - #if ( configNUM_CORES > 1 ) - #if ( configUSE_CORE_AFFINITY == 1 ) - if( ( pxTCB->uxCoreAffinityMask & ( 1 << x ) ) != 0 ) - #endif - #endif + xCurrentCoreTaskPriority = ( BaseType_t ) pxCurrentTCBs[ xCoreID ]->uxPriority; + + /* System idle tasks are being assigned a priority of tskIDLE_PRIORITY - 1 here. */ + if( ( pxCurrentTCBs[ xCoreID ]->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) != 0U ) { - #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - if( pxCurrentTCBs[ x ]->xPreemptionDisable == pdFALSE ) + xCurrentCoreTaskPriority = xCurrentCoreTaskPriority - 1; + } + + if( ( taskTASK_IS_RUNNING( pxCurrentTCBs[ xCoreID ] ) != pdFALSE ) && ( xYieldPendings[ xCoreID ] == pdFALSE ) ) + { + #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) + if( taskTASK_IS_RUNNING( pxTCB ) == pdFALSE ) #endif { - xLowestPriority = xTaskPriority; - xLowestPriorityCore = x; + if( xCurrentCoreTaskPriority <= xLowestPriorityToPreempt ) + { + #if ( configUSE_CORE_AFFINITY == 1 ) + if( ( pxTCB->uxCoreAffinityMask & ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ) ) != 0U ) + #endif + { + #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) + if( pxCurrentTCBs[ xCoreID ]->xPreemptionDisable == pdFALSE ) + #endif + { + xLowestPriorityToPreempt = xCurrentCoreTaskPriority; + xLowestPriorityCore = xCoreID; + } + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - #if ( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configNUM_CORES > 1 ) ) && 1 + #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) + { + /* Yield all currently running non-idle tasks with a priority lower than + * the task that needs to run. */ + if( ( xCurrentCoreTaskPriority > ( ( BaseType_t ) tskIDLE_PRIORITY - 1 ) ) && + ( xCurrentCoreTaskPriority < ( BaseType_t ) pxTCB->uxPriority ) ) + { + prvYieldCore( xCoreID ); + xYieldCount++; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */ + } + else { - /* Yield all currently running non-idle tasks with a priority lower than - * the task that needs to run. */ - if( ( ( BaseType_t ) tskIDLE_PRIORITY - 1 < xTaskPriority ) && ( xTaskPriority < ( BaseType_t ) pxTCB->uxPriority ) ) - { - prvYieldCore( x ); - xYieldCount++; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + mtCOVERAGE_TEST_MARKER(); } - #endif /* if ( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configNUM_CORES > 1 ) ) && 1 */ - } - else - { - mtCOVERAGE_TEST_MARKER(); + } + + #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) + if( ( xYieldCount == 0 ) && ( xLowestPriorityCore >= 0 ) ) + #else /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */ + if( xLowestPriorityCore >= 0 ) + #endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */ + { + prvYieldCore( xLowestPriorityCore ); + } + + #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) + /* Verify that the calling core always yields to higher priority tasks. */ + if( ( ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) == 0U ) && + ( pxTCB->uxPriority > pxCurrentTCBs[ portGET_CORE_ID() ]->uxPriority ) ) + { + configASSERT( ( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) || + ( taskTASK_IS_RUNNING( pxCurrentTCBs[ portGET_CORE_ID() ] ) == pdFALSE ) ); + } + #endif } } - - if( ( xYieldCount == 0 ) && taskVALID_CORE_ID( xLowestPriorityCore ) ) - { - prvYieldCore( xLowestPriorityCore ); - xYieldCount++; - } - - #if ( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configNUM_CORES > 1 ) ) - /* Verify that the calling core always yields to higher priority tasks */ - if( !pxCurrentTCBs[ portGET_CORE_ID() ]->xIsIdle && ( pxTCB->uxPriority > pxCurrentTCBs[ portGET_CORE_ID() ]->uxPriority ) ) - { - configASSERT( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE || taskTASK_IS_RUNNING( pxCurrentTCBs[ portGET_CORE_ID() ]->xTaskRunState ) == pdFALSE ); - } - #endif -} +#endif /* #if ( configNUMBER_OF_CORES > 1 ) */ /*-----------------------------------------------------------*/ -#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) - - static BaseType_t prvSelectHighestPriorityTask( const BaseType_t xCoreID ) +#if ( configNUMBER_OF_CORES > 1 ) + static void prvSelectHighestPriorityTask( BaseType_t xCoreID ) { UBaseType_t uxCurrentPriority = uxTopReadyPriority; BaseType_t xTaskScheduled = pdFALSE; BaseType_t xDecrementTopPriority = pdTRUE; - #if ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) - TCB_t * pxPreviousTCB = NULL; + #if ( configUSE_CORE_AFFINITY == 1 ) + const TCB_t * pxPreviousTCB = NULL; #endif - #if ( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configNUM_CORES > 1 ) ) + #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) BaseType_t xPriorityDropped = pdFALSE; #endif + /* This function should be called when scheduler is running. */ + configASSERT( xSchedulerRunning == pdTRUE ); + + /* A new task is created and a running task with the same priority yields + * itself to run the new task. When a running task yields itself, it is still + * in the ready list. This running task will be selected before the new task + * since the new task is always added to the end of the ready list. + * The other problem is that the running task still in the same position of + * the ready list when it yields itself. It is possible that it will be selected + * earlier then other tasks which waits longer than this task. + * + * To fix these problems, the running task should be put to the end of the + * ready list before searching for the ready task in the ready list. */ + if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxCurrentTCBs[ xCoreID ]->uxPriority ] ), + &pxCurrentTCBs[ xCoreID ]->xStateListItem ) == pdTRUE ) + { + ( void ) uxListRemove( &pxCurrentTCBs[ xCoreID ]->xStateListItem ); + vListInsertEnd( &( pxReadyTasksLists[ pxCurrentTCBs[ xCoreID ]->uxPriority ] ), + &pxCurrentTCBs[ xCoreID ]->xStateListItem ); + } + while( xTaskScheduled == pdFALSE ) { - #if ( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configNUM_CORES > 1 ) ) + #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) + { + if( uxCurrentPriority < uxTopReadyPriority ) { - if( uxCurrentPriority < uxTopReadyPriority ) - { - /* We can't schedule any tasks, other than idle, that have a - * priority lower than the priority of a task currently running - * on another core. */ - uxCurrentPriority = tskIDLE_PRIORITY; - } + /* We can't schedule any tasks, other than idle, that have a + * priority lower than the priority of a task currently running + * on another core. */ + uxCurrentPriority = tskIDLE_PRIORITY; } + } #endif if( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxCurrentPriority ] ) ) == pdFALSE ) { - List_t * const pxReadyList = &( pxReadyTasksLists[ uxCurrentPriority ] ); - ListItem_t * pxLastTaskItem = pxReadyList->pxIndex->pxPrevious; - ListItem_t * pxTaskItem = pxLastTaskItem; - - if( ( void * ) pxLastTaskItem == ( void * ) &( pxReadyList->xListEnd ) ) - { - pxLastTaskItem = pxLastTaskItem->pxPrevious; - } + const List_t * const pxReadyList = &( pxReadyTasksLists[ uxCurrentPriority ] ); + const ListItem_t * pxEndMarker = listGET_END_MARKER( pxReadyList ); + ListItem_t * pxIterator; /* The ready task list for uxCurrentPriority is not empty, so uxTopReadyPriority - * must not be decremented any further */ + * must not be decremented any further. */ xDecrementTopPriority = pdFALSE; - do + for( pxIterator = listGET_HEAD_ENTRY( pxReadyList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) ) { - TCB_t * pxTCB; + /* MISRA Ref 11.5.3 [Void pointer assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + TCB_t * pxTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxIterator ); - pxTaskItem = pxTaskItem->pxNext; - - if( ( void * ) pxTaskItem == ( void * ) &( pxReadyList->xListEnd ) ) + #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) { - pxTaskItem = pxTaskItem->pxNext; - } - - pxTCB = pxTaskItem->pvOwner; - - /*debug_printf("Attempting to schedule %s on core %d\n", pxTCB->pcTaskName, portGET_CORE_ID() ); */ - - #if ( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configNUM_CORES > 1 ) ) + /* When falling back to the idle priority because only one priority + * level is allowed to run at a time, we should ONLY schedule the true + * idle tasks, not user tasks at the idle priority. */ + if( uxCurrentPriority < uxTopReadyPriority ) { - /* When falling back to the idle priority because only one priority - * level is allowed to run at a time, we should ONLY schedule the true - * idle tasks, not user tasks at the idle priority. */ - if( uxCurrentPriority < uxTopReadyPriority ) + if( ( pxTCB->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) == 0U ) { - if( pxTCB->xIsIdle == pdFALSE ) - { - continue; - } + continue; } } - #endif /* if ( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configNUM_CORES > 1 ) ) */ + } + #endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */ if( pxTCB->xTaskRunState == taskTASK_NOT_RUNNING ) { - #if ( configNUM_CORES > 1 ) - #if ( configUSE_CORE_AFFINITY == 1 ) - if( ( pxTCB->uxCoreAffinityMask & ( 1 << xCoreID ) ) != 0 ) - #endif + #if ( configUSE_CORE_AFFINITY == 1 ) + if( ( pxTCB->uxCoreAffinityMask & ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ) ) != 0U ) #endif { - /* If the task is not being executed by any core swap it in */ + /* If the task is not being executed by any core swap it in. */ pxCurrentTCBs[ xCoreID ]->xTaskRunState = taskTASK_NOT_RUNNING; - #if ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) + #if ( configUSE_CORE_AFFINITY == 1 ) pxPreviousTCB = pxCurrentTCBs[ xCoreID ]; #endif - pxTCB->xTaskRunState = ( TaskRunning_t ) xCoreID; + pxTCB->xTaskRunState = xCoreID; pxCurrentTCBs[ xCoreID ] = pxTCB; xTaskScheduled = pdTRUE; } } else if( pxTCB == pxCurrentTCBs[ xCoreID ] ) { - configASSERT( ( pxTCB->xTaskRunState == xCoreID ) || ( pxTCB->xTaskRunState == taskTASK_YIELDING ) ); - #if ( configNUM_CORES > 1 ) - #if ( configUSE_CORE_AFFINITY == 1 ) - if( ( pxTCB->uxCoreAffinityMask & ( 1 << xCoreID ) ) != 0 ) - #endif + configASSERT( ( pxTCB->xTaskRunState == xCoreID ) || ( pxTCB->xTaskRunState == taskTASK_SCHEDULED_TO_YIELD ) ); + + #if ( configUSE_CORE_AFFINITY == 1 ) + if( ( pxTCB->uxCoreAffinityMask & ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ) ) != 0U ) #endif { - /* The task is already running on this core, mark it as scheduled */ - pxTCB->xTaskRunState = ( TaskRunning_t ) xCoreID; + /* The task is already running on this core, mark it as scheduled. */ + pxTCB->xTaskRunState = xCoreID; xTaskScheduled = pdTRUE; } } + else + { + /* This task is running on the core other than xCoreID. */ + mtCOVERAGE_TEST_MARKER(); + } if( xTaskScheduled != pdFALSE ) { - /* Once a task has been selected to run on this core, - * move it to the end of the ready task list. */ - uxListRemove( pxTaskItem ); - vListInsertEnd( pxReadyList, pxTaskItem ); + /* A task has been selected to run on this core. */ break; } - } while( pxTaskItem != pxLastTaskItem ); + } } else { if( xDecrementTopPriority != pdFALSE ) { uxTopReadyPriority--; - #if ( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configNUM_CORES > 1 ) ) - { - xPriorityDropped = pdTRUE; - } + #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) + { + xPriorityDropped = pdTRUE; + } #endif } } - /* This function can get called by vTaskSuspend() before the scheduler is started. - * In that case, since the idle tasks have not yet been created it is possible that we - * won't find a new task to schedule. Return pdFALSE in this case. */ - if( ( xSchedulerRunning == pdFALSE ) && ( uxCurrentPriority == tskIDLE_PRIORITY ) && ( xTaskScheduled == pdFALSE ) ) + /* There are configNUMBER_OF_CORES Idle tasks created when scheduler started. + * The scheduler should be able to select a task to run when uxCurrentPriority + * is tskIDLE_PRIORITY. uxCurrentPriority is never decreased to value blow + * tskIDLE_PRIORITY. */ + if( uxCurrentPriority > tskIDLE_PRIORITY ) { - return pdFALSE; + uxCurrentPriority--; + } + else + { + /* This function is called when idle task is not created. Break the + * loop to prevent uxCurrentPriority overrun. */ + break; } - - configASSERT( ( uxCurrentPriority > tskIDLE_PRIORITY ) || ( xTaskScheduled == pdTRUE ) ); - uxCurrentPriority--; } - configASSERT( taskTASK_IS_RUNNING( pxCurrentTCBs[ xCoreID ]->xTaskRunState ) ); - - #if ( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configNUM_CORES > 1 ) ) - if( xPriorityDropped != pdFALSE ) + #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) + { + if( xTaskScheduled == pdTRUE ) { - /* There may be several ready tasks that were being prevented from running because there was - * a higher priority task running. Now that the last of the higher priority tasks is no longer - * running, make sure all the other idle tasks yield. */ - UBaseType_t x; - - for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configNUM_CORES; x++ ) + if( xPriorityDropped != pdFALSE ) { - if( pxCurrentTCBs[ x ]->xIsIdle != pdFALSE ) + /* There may be several ready tasks that were being prevented from running because there was + * a higher priority task running. Now that the last of the higher priority tasks is no longer + * running, make sure all the other idle tasks yield. */ + BaseType_t x; + + for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configNUMBER_OF_CORES; x++ ) { - prvYieldCore( x ); + if( ( pxCurrentTCBs[ x ]->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) != 0U ) + { + prvYieldCore( x ); + } } } } - #endif /* if ( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configNUM_CORES > 1 ) ) */ + } + #endif /* #if ( configRUN_MULTIPLE_PRIORITIES == 0 ) */ - #if ( configNUM_CORES > 1 ) - #if ( configUSE_CORE_AFFINITY == 1 ) + #if ( configUSE_CORE_AFFINITY == 1 ) + { + if( xTaskScheduled == pdTRUE ) + { if( ( pxPreviousTCB != NULL ) && ( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxPreviousTCB->uxPriority ] ), &( pxPreviousTCB->xStateListItem ) ) != pdFALSE ) ) { - /* A ready task was just bumped off this core. Look at the cores it can run from - * from to see if it is able to run on any of them */ + /* A ready task was just evicted from this core. See if it can be + * scheduled on any other core. */ UBaseType_t uxCoreMap = pxPreviousTCB->uxCoreAffinityMask; - BaseType_t xLowestPriority = pxPreviousTCB->uxPriority - pxPreviousTCB->xIsIdle; + BaseType_t xLowestPriority = ( BaseType_t ) pxPreviousTCB->uxPriority; BaseType_t xLowestPriorityCore = -1; + BaseType_t x; - if( ( uxCoreMap & ( 1 << xCoreID ) ) != 0 ) + if( ( pxPreviousTCB->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) != 0U ) { - /* The ready task that was removed from this core is not excluded from it. - * Only look at the intersection of the cores the removed task is allowed to run - * on with the cores that the new task is excluded from. It is possible that the - * new task was only placed onto this core because it is excluded from another. - * Check to see if the previous task could run on one of those cores. */ + xLowestPriority = xLowestPriority - 1; + } + + if( ( uxCoreMap & ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ) ) != 0U ) + { + /* pxPreviousTCB was removed from this core and this core is not excluded + * from it's core affinity mask. + * + * pxPreviousTCB is preempted by the new higher priority task + * pxCurrentTCBs[ xCoreID ]. When searching a new core for pxPreviousTCB, + * we do not need to look at the cores on which pxCurrentTCBs[ xCoreID ] + * is allowed to run. The reason is - when more than one cores are + * eligible for an incoming task, we preempt the core with the minimum + * priority task. Because this core (i.e. xCoreID) was preempted for + * pxCurrentTCBs[ xCoreID ], this means that all the others cores + * where pxCurrentTCBs[ xCoreID ] can run, are running tasks with priority + * no lower than pxPreviousTCB's priority. Therefore, the only cores where + * which can be preempted for pxPreviousTCB are the ones where + * pxCurrentTCBs[ xCoreID ] is not allowed to run (and obviously, + * pxPreviousTCB is allowed to run). + * + * This is an optimization which reduces the number of cores needed to be + * searched for pxPreviousTCB to run. */ uxCoreMap &= ~( pxCurrentTCBs[ xCoreID ]->uxCoreAffinityMask ); } else { - /* The ready task that was removed from this core is excluded from it. */ + /* pxPreviousTCB's core affinity mask is changed and it is no longer + * allowed to run on this core. Searching all the cores in pxPreviousTCB's + * new core affinity mask to find a core on which it can run. */ } - uxCoreMap &= ( ( 1 << configNUM_CORES ) - 1 ); + uxCoreMap &= ( ( 1U << configNUMBER_OF_CORES ) - 1U ); - while( uxCoreMap != 0 ) + for( x = ( ( BaseType_t ) configNUMBER_OF_CORES - 1 ); x >= ( BaseType_t ) 0; x-- ) { - int uxCore = 31UL - ( uint32_t ) __builtin_clz( uxCoreMap ); + UBaseType_t uxCore = ( UBaseType_t ) x; + BaseType_t xTaskPriority; - configASSERT( taskVALID_CORE_ID( uxCore ) ); - - uxCoreMap &= ~( 1 << uxCore ); - - BaseType_t xTaskPriority = ( BaseType_t ) pxCurrentTCBs[ uxCore ]->uxPriority - pxCurrentTCBs[ uxCore ]->xIsIdle; - - if( ( xTaskPriority < xLowestPriority ) && ( taskTASK_IS_RUNNING( pxCurrentTCBs[ uxCore ]->xTaskRunState ) != pdFALSE ) && ( xYieldPendings[ uxCore ] == pdFALSE ) ) + if( ( uxCoreMap & ( ( UBaseType_t ) 1U << uxCore ) ) != 0U ) { - #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - if( pxCurrentTCBs[ uxCore ]->xPreemptionDisable == pdFALSE ) - #endif + xTaskPriority = ( BaseType_t ) pxCurrentTCBs[ uxCore ]->uxPriority; + + if( ( pxCurrentTCBs[ uxCore ]->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) != 0U ) { - xLowestPriority = xTaskPriority; - xLowestPriorityCore = uxCore; + xTaskPriority = xTaskPriority - ( BaseType_t ) 1; + } + + uxCoreMap &= ~( ( UBaseType_t ) 1U << uxCore ); + + if( ( xTaskPriority < xLowestPriority ) && + ( taskTASK_IS_RUNNING( pxCurrentTCBs[ uxCore ] ) != pdFALSE ) && + ( xYieldPendings[ uxCore ] == pdFALSE ) ) + { + #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) + if( pxCurrentTCBs[ uxCore ]->xPreemptionDisable == pdFALSE ) + #endif + { + xLowestPriority = xTaskPriority; + xLowestPriorityCore = ( BaseType_t ) uxCore; + } } } } - if( taskVALID_CORE_ID( xLowestPriorityCore ) ) + if( xLowestPriorityCore >= 0 ) { prvYieldCore( xLowestPriorityCore ); } } - #endif /* if ( configUSE_CORE_AFFINITY == 1 ) */ - #endif /* if ( configNUM_CORES > 1 ) */ - - return pdTRUE; + } + } + #endif /* #if ( configUSE_CORE_AFFINITY == 1 ) */ } -#else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +#endif /* ( configNUMBER_OF_CORES > 1 ) */ - static void prvSelectHighestPriorityTask( BaseType_t xCoreID ) - { - UBaseType_t uxTopPriority; - - /* Find the highest priority list that contains ready tasks. */ - portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); - configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); - listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); - } - -#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ /*-----------------------------------------------------------*/ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) - TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, - const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - const uint32_t ulStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - StackType_t * const puxStackBuffer, - StaticTask_t * const pxTaskBuffer ) - #if ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) - { - return xTaskCreateStaticAffinitySet(pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer, tskNO_AFFINITY); - } - - TaskHandle_t xTaskCreateStaticAffinitySet( TaskFunction_t pxTaskCode, - const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - const uint32_t ulStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - StackType_t * const puxStackBuffer, - StaticTask_t * const pxTaskBuffer, - UBaseType_t uxCoreAffinityMask ) - #endif /* ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) */ + static TCB_t * prvCreateStaticTask( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + StackType_t * const puxStackBuffer, + StaticTask_t * const pxTaskBuffer, + TaskHandle_t * const pxCreatedTask ) { TCB_t * pxNewTCB; - TaskHandle_t xReturn; configASSERT( puxStackBuffer != NULL ); configASSERT( pxTaskBuffer != NULL ); #if ( configASSERT_DEFINED == 1 ) - { - /* Sanity check that the size of the structure used to declare a - * variable of type StaticTask_t equals the size of the real task - * structure. */ - volatile size_t xSize = sizeof( StaticTask_t ); - configASSERT( xSize == sizeof( TCB_t ) ); - ( void ) xSize; /* Prevent lint warning when configASSERT() is not used. */ - } + { + /* Sanity check that the size of the structure used to declare a + * variable of type StaticTask_t equals the size of the real task + * structure. */ + volatile size_t xSize = sizeof( StaticTask_t ); + configASSERT( xSize == sizeof( TCB_t ) ); + ( void ) xSize; /* Prevent unused variable warning when configASSERT() is not used. */ + } #endif /* configASSERT_DEFINED */ if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) ) { /* The memory used for the task's TCB and stack are passed into this * function - use them. */ - pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */ + /* MISRA Ref 11.3.1 [Misaligned access] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */ + /* coverity[misra_c_2012_rule_11_3_violation] */ + pxNewTCB = ( TCB_t * ) pxTaskBuffer; + ( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) ); pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer; - #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */ - { - /* Tasks can be created statically or dynamically, so note this - * task was created statically in case the task is later deleted. */ - pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB; - } + #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) + { + /* Tasks can be created statically or dynamically, so note this + * task was created statically in case the task is later deleted. */ + pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB; + } #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ - prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL ); + prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL ); + } + else + { + pxNewTCB = NULL; + } - #if ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) - { - /* Set the task's affinity before scheduling it */ - pxNewTCB->uxCoreAffinityMask = uxCoreAffinityMask; - } + return pxNewTCB; + } +/*-----------------------------------------------------------*/ + + TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + StackType_t * const puxStackBuffer, + StaticTask_t * const pxTaskBuffer ) + { + TaskHandle_t xReturn = NULL; + TCB_t * pxNewTCB; + + traceENTER_xTaskCreateStatic( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer ); + + pxNewTCB = prvCreateStaticTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer, &xReturn ); + + if( pxNewTCB != NULL ) + { + #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) + { + /* Set the task's affinity before scheduling it. */ + pxNewTCB->uxCoreAffinityMask = tskNO_AFFINITY; + } #endif prvAddNewTaskToReadyList( pxNewTCB ); } else { - xReturn = NULL; + mtCOVERAGE_TEST_MARKER(); } + traceRETURN_xTaskCreateStatic( xReturn ); + return xReturn; } +/*-----------------------------------------------------------*/ + + #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) + TaskHandle_t xTaskCreateStaticAffinitySet( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + StackType_t * const puxStackBuffer, + StaticTask_t * const pxTaskBuffer, + UBaseType_t uxCoreAffinityMask ) + { + TaskHandle_t xReturn = NULL; + TCB_t * pxNewTCB; + + traceENTER_xTaskCreateStaticAffinitySet( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer, uxCoreAffinityMask ); + + pxNewTCB = prvCreateStaticTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer, &xReturn ); + + if( pxNewTCB != NULL ) + { + /* Set the task's affinity before scheduling it. */ + pxNewTCB->uxCoreAffinityMask = uxCoreAffinityMask; + + prvAddNewTaskToReadyList( pxNewTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceRETURN_xTaskCreateStaticAffinitySet( xReturn ); + + return xReturn; + } + #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ #endif /* SUPPORT_STATIC_ALLOCATION */ /*-----------------------------------------------------------*/ #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) - - BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, - TaskHandle_t * pxCreatedTask ) - #if ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) - { - return xTaskCreateRestrictedStaticAffinitySet( pxTaskDefinition, tskNO_AFFINITY, pxCreatedTask ); - } - - BaseType_t xTaskCreateRestrictedStaticAffinitySet( const TaskParameters_t * const pxTaskDefinition, - UBaseType_t uxCoreAffinityMask, - TaskHandle_t * pxCreatedTask ) - #endif /* ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) */ + static TCB_t * prvCreateRestrictedStaticTask( const TaskParameters_t * const pxTaskDefinition, + TaskHandle_t * const pxCreatedTask ) { TCB_t * pxNewTCB; - BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; configASSERT( pxTaskDefinition->puxStackBuffer != NULL ); configASSERT( pxTaskDefinition->pxTaskBuffer != NULL ); @@ -1173,16 +1392,17 @@ static void prvYieldForTask( TCB_t * pxTCB, * on the implementation of the port malloc function and whether or * not static allocation is being used. */ pxNewTCB = ( TCB_t * ) pxTaskDefinition->pxTaskBuffer; + ( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) ); /* Store the stack location in the TCB. */ pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer; #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) - { - /* Tasks can be created statically or dynamically, so note this - * task was created statically in case the task is later deleted. */ - pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB; - } + { + /* Tasks can be created statically or dynamically, so note this + * task was created statically in case the task is later deleted. */ + pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB; + } #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ prvInitialiseNewTask( pxTaskDefinition->pvTaskCode, @@ -1192,188 +1412,35 @@ static void prvYieldForTask( TCB_t * pxTCB, pxTaskDefinition->uxPriority, pxCreatedTask, pxNewTCB, pxTaskDefinition->xRegions ); - - #if ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) - { - /* Set the task's affinity before scheduling it */ - pxNewTCB->uxCoreAffinityMask = uxCoreAffinityMask; - } - #endif - - prvAddNewTaskToReadyList( pxNewTCB ); - xReturn = pdPASS; + } + else + { + pxNewTCB = NULL; } - return xReturn; + return pxNewTCB; } - -#endif /* ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /*-----------------------------------------------------------*/ -#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - - BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, - TaskHandle_t * pxCreatedTask ) - #if ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) - { - return xTaskCreateRestrictedAffinitySet( pxTaskDefinition, tskNO_AFFINITY, pxCreatedTask ); - } - - BaseType_t xTaskCreateRestrictedAffinitySet( const TaskParameters_t * const pxTaskDefinition, - UBaseType_t uxCoreAffinityMask, - TaskHandle_t * pxCreatedTask ) - #endif /* ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) */ - { - TCB_t * pxNewTCB; - BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; - - configASSERT( pxTaskDefinition->puxStackBuffer ); - - if( pxTaskDefinition->puxStackBuffer != NULL ) - { - /* Allocate space for the TCB. Where the memory comes from depends - * on the implementation of the port malloc function and whether or - * not static allocation is being used. */ - pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); - - if( pxNewTCB != NULL ) - { - /* Store the stack location in the TCB. */ - pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer; - - #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) - { - /* Tasks can be created statically or dynamically, so note - * this task had a statically allocated stack in case it is - * later deleted. The TCB was allocated dynamically. */ - pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY; - } - #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ - - prvInitialiseNewTask( pxTaskDefinition->pvTaskCode, - pxTaskDefinition->pcName, - ( uint32_t ) pxTaskDefinition->usStackDepth, - pxTaskDefinition->pvParameters, - pxTaskDefinition->uxPriority, - pxCreatedTask, pxNewTCB, - pxTaskDefinition->xRegions ); - - #if ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) - { - /* Set the task's affinity before scheduling it */ - pxNewTCB->uxCoreAffinityMask = uxCoreAffinityMask; - } - #endif - - prvAddNewTaskToReadyList( pxNewTCB ); - xReturn = pdPASS; - } - } - - return xReturn; - } - -#endif /* portUSING_MPU_WRAPPERS */ -/*-----------------------------------------------------------*/ - -#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - - BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, - const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - const configSTACK_DEPTH_TYPE usStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - TaskHandle_t * const pxCreatedTask ) - #if ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) - { - return xTaskCreateAffinitySet(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, tskNO_AFFINITY, pxCreatedTask); - } - - BaseType_t xTaskCreateAffinitySet( TaskFunction_t pxTaskCode, - const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - const configSTACK_DEPTH_TYPE usStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - UBaseType_t uxCoreAffinityMask, - TaskHandle_t * const pxCreatedTask ) - #endif /* ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) */ + BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, + TaskHandle_t * pxCreatedTask ) { TCB_t * pxNewTCB; BaseType_t xReturn; - /* If the stack grows down then allocate the stack then the TCB so the stack - * does not grow into the TCB. Likewise if the stack grows up then allocate - * the TCB then the stack. */ - #if ( portSTACK_GROWTH > 0 ) - { - /* Allocate space for the TCB. Where the memory comes from depends on - * the implementation of the port malloc function and whether or not static - * allocation is being used. */ - pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); + traceENTER_xTaskCreateRestrictedStatic( pxTaskDefinition, pxCreatedTask ); - if( pxNewTCB != NULL ) - { - /* Allocate space for the stack used by the task being created. - * The base of the stack memory stored in the TCB so the task can - * be deleted later if required. */ - pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + configASSERT( pxTaskDefinition != NULL ); - if( pxNewTCB->pxStack == NULL ) - { - /* Could not allocate the stack. Delete the allocated TCB. */ - vPortFree( pxNewTCB ); - pxNewTCB = NULL; - } - } - } - #else /* portSTACK_GROWTH */ - { - StackType_t * pxStack; - - /* Allocate space for the stack used by the task being created. */ - pxStack = pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */ - - if( pxStack != NULL ) - { - /* Allocate space for the TCB. */ - pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */ - - if( pxNewTCB != NULL ) - { - /* Store the stack location in the TCB. */ - pxNewTCB->pxStack = pxStack; - } - else - { - /* The stack cannot be used as the TCB was not created. Free - * it again. */ - vPortFreeStack( pxStack ); - } - } - else - { - pxNewTCB = NULL; - } - } - #endif /* portSTACK_GROWTH */ + pxNewTCB = prvCreateRestrictedStaticTask( pxTaskDefinition, pxCreatedTask ); if( pxNewTCB != NULL ) { - #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e9029 !e731 Macro has been consolidated for readability reasons. */ - { - /* Tasks can be created statically or dynamically, so note this - * task was created dynamically in case it is later deleted. */ - pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB; - } - #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ - - prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL ); - - #if ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) - { - /* Set the task's affinity before scheduling it */ - pxNewTCB->uxCoreAffinityMask = uxCoreAffinityMask; - } + #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) + { + /* Set the task's affinity before scheduling it. */ + pxNewTCB->uxCoreAffinityMask = tskNO_AFFINITY; + } #endif prvAddNewTaskToReadyList( pxNewTCB ); @@ -1384,14 +1451,343 @@ static void prvYieldForTask( TCB_t * pxTCB, xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; } + traceRETURN_xTaskCreateRestrictedStatic( xReturn ); + return xReturn; } +/*-----------------------------------------------------------*/ + + #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) + BaseType_t xTaskCreateRestrictedStaticAffinitySet( const TaskParameters_t * const pxTaskDefinition, + UBaseType_t uxCoreAffinityMask, + TaskHandle_t * pxCreatedTask ) + { + TCB_t * pxNewTCB; + BaseType_t xReturn; + + traceENTER_xTaskCreateRestrictedStaticAffinitySet( pxTaskDefinition, uxCoreAffinityMask, pxCreatedTask ); + + configASSERT( pxTaskDefinition != NULL ); + + pxNewTCB = prvCreateRestrictedStaticTask( pxTaskDefinition, pxCreatedTask ); + + if( pxNewTCB != NULL ) + { + /* Set the task's affinity before scheduling it. */ + pxNewTCB->uxCoreAffinityMask = uxCoreAffinityMask; + + prvAddNewTaskToReadyList( pxNewTCB ); + xReturn = pdPASS; + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + } + + traceRETURN_xTaskCreateRestrictedStaticAffinitySet( xReturn ); + + return xReturn; + } + #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ + +#endif /* ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ +/*-----------------------------------------------------------*/ + +#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + static TCB_t * prvCreateRestrictedTask( const TaskParameters_t * const pxTaskDefinition, + TaskHandle_t * const pxCreatedTask ) + { + TCB_t * pxNewTCB; + + configASSERT( pxTaskDefinition->puxStackBuffer ); + + if( pxTaskDefinition->puxStackBuffer != NULL ) + { + /* MISRA Ref 11.5.1 [Malloc memory assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); + + if( pxNewTCB != NULL ) + { + ( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) ); + + /* Store the stack location in the TCB. */ + pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer; + + #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) + { + /* Tasks can be created statically or dynamically, so note + * this task had a statically allocated stack in case it is + * later deleted. The TCB was allocated dynamically. */ + pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY; + } + #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ + + prvInitialiseNewTask( pxTaskDefinition->pvTaskCode, + pxTaskDefinition->pcName, + ( uint32_t ) pxTaskDefinition->usStackDepth, + pxTaskDefinition->pvParameters, + pxTaskDefinition->uxPriority, + pxCreatedTask, pxNewTCB, + pxTaskDefinition->xRegions ); + } + } + else + { + pxNewTCB = NULL; + } + + return pxNewTCB; + } +/*-----------------------------------------------------------*/ + + BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, + TaskHandle_t * pxCreatedTask ) + { + TCB_t * pxNewTCB; + BaseType_t xReturn; + + traceENTER_xTaskCreateRestricted( pxTaskDefinition, pxCreatedTask ); + + pxNewTCB = prvCreateRestrictedTask( pxTaskDefinition, pxCreatedTask ); + + if( pxNewTCB != NULL ) + { + #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) + { + /* Set the task's affinity before scheduling it. */ + pxNewTCB->uxCoreAffinityMask = tskNO_AFFINITY; + } + #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ + + prvAddNewTaskToReadyList( pxNewTCB ); + + xReturn = pdPASS; + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + } + + traceRETURN_xTaskCreateRestricted( xReturn ); + + return xReturn; + } +/*-----------------------------------------------------------*/ + + #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) + BaseType_t xTaskCreateRestrictedAffinitySet( const TaskParameters_t * const pxTaskDefinition, + UBaseType_t uxCoreAffinityMask, + TaskHandle_t * pxCreatedTask ) + { + TCB_t * pxNewTCB; + BaseType_t xReturn; + + traceENTER_xTaskCreateRestrictedAffinitySet( pxTaskDefinition, uxCoreAffinityMask, pxCreatedTask ); + + pxNewTCB = prvCreateRestrictedTask( pxTaskDefinition, pxCreatedTask ); + + if( pxNewTCB != NULL ) + { + /* Set the task's affinity before scheduling it. */ + pxNewTCB->uxCoreAffinityMask = uxCoreAffinityMask; + + prvAddNewTaskToReadyList( pxNewTCB ); + + xReturn = pdPASS; + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + } + + traceRETURN_xTaskCreateRestrictedAffinitySet( xReturn ); + + return xReturn; + } + #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ + + +#endif /* portUSING_MPU_WRAPPERS */ +/*-----------------------------------------------------------*/ + +#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + static TCB_t * prvCreateTask( TaskFunction_t pxTaskCode, + const char * const pcName, + const configSTACK_DEPTH_TYPE usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pxCreatedTask ) + { + TCB_t * pxNewTCB; + + /* If the stack grows down then allocate the stack then the TCB so the stack + * does not grow into the TCB. Likewise if the stack grows up then allocate + * the TCB then the stack. */ + #if ( portSTACK_GROWTH > 0 ) + { + /* Allocate space for the TCB. Where the memory comes from depends on + * the implementation of the port malloc function and whether or not static + * allocation is being used. */ + /* MISRA Ref 11.5.1 [Malloc memory assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); + + if( pxNewTCB != NULL ) + { + ( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) ); + + /* Allocate space for the stack used by the task being created. + * The base of the stack memory stored in the TCB so the task can + * be deleted later if required. */ + /* MISRA Ref 11.5.1 [Malloc memory assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); + + if( pxNewTCB->pxStack == NULL ) + { + /* Could not allocate the stack. Delete the allocated TCB. */ + vPortFree( pxNewTCB ); + pxNewTCB = NULL; + } + } + } + #else /* portSTACK_GROWTH */ + { + StackType_t * pxStack; + + /* Allocate space for the stack used by the task being created. */ + /* MISRA Ref 11.5.1 [Malloc memory assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + pxStack = pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); + + if( pxStack != NULL ) + { + /* Allocate space for the TCB. */ + /* MISRA Ref 11.5.1 [Malloc memory assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); + + if( pxNewTCB != NULL ) + { + ( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) ); + + /* Store the stack location in the TCB. */ + pxNewTCB->pxStack = pxStack; + } + else + { + /* The stack cannot be used as the TCB was not created. Free + * it again. */ + vPortFreeStack( pxStack ); + } + } + else + { + pxNewTCB = NULL; + } + } + #endif /* portSTACK_GROWTH */ + + if( pxNewTCB != NULL ) + { + #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) + { + /* Tasks can be created statically or dynamically, so note this + * task was created dynamically in case it is later deleted. */ + pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB; + } + #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ + + prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL ); + } + + return pxNewTCB; + } +/*-----------------------------------------------------------*/ + + BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, + const char * const pcName, + const configSTACK_DEPTH_TYPE usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pxCreatedTask ) + { + TCB_t * pxNewTCB; + BaseType_t xReturn; + + traceENTER_xTaskCreate( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ); + + pxNewTCB = prvCreateTask( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ); + + if( pxNewTCB != NULL ) + { + #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) + { + /* Set the task's affinity before scheduling it. */ + pxNewTCB->uxCoreAffinityMask = tskNO_AFFINITY; + } + #endif + + prvAddNewTaskToReadyList( pxNewTCB ); + xReturn = pdPASS; + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + } + + traceRETURN_xTaskCreate( xReturn ); + + return xReturn; + } +/*-----------------------------------------------------------*/ + + #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) + BaseType_t xTaskCreateAffinitySet( TaskFunction_t pxTaskCode, + const char * const pcName, + const configSTACK_DEPTH_TYPE usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + UBaseType_t uxCoreAffinityMask, + TaskHandle_t * const pxCreatedTask ) + { + TCB_t * pxNewTCB; + BaseType_t xReturn; + + traceENTER_xTaskCreateAffinitySet( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, uxCoreAffinityMask, pxCreatedTask ); + + pxNewTCB = prvCreateTask( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ); + + if( pxNewTCB != NULL ) + { + /* Set the task's affinity before scheduling it. */ + pxNewTCB->uxCoreAffinityMask = uxCoreAffinityMask; + + prvAddNewTaskToReadyList( pxNewTCB ); + xReturn = pdPASS; + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + } + + traceRETURN_xTaskCreateAffinitySet( xReturn ); + + return xReturn; + } + #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ /*-----------------------------------------------------------*/ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, - const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, @@ -1419,10 +1815,10 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, /* Avoid dependency on memset() if it is not required. */ #if ( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 ) - { - /* Fill the stack with a known value to assist debugging. */ - ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) ); - } + { + /* Fill the stack with a known value to assist debugging. */ + ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) ); + } #endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */ /* Calculate the top of stack address. This depends on whether the stack @@ -1430,32 +1826,33 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, * portSTACK_GROWTH is used to make the result positive or negative as required * by the port. */ #if ( portSTACK_GROWTH < 0 ) + { + pxTopOfStack = &( pxNewTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] ); + pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); + + /* Check the alignment of the calculated top of stack is correct. */ + configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + + #if ( configRECORD_STACK_HIGH_ADDRESS == 1 ) { - pxTopOfStack = &( pxNewTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] ); - pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 !e9033 !e9078 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. Checked by assert(). */ - - /* Check the alignment of the calculated top of stack is correct. */ - configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); - - #if ( configRECORD_STACK_HIGH_ADDRESS == 1 ) - { - /* Also record the stack's high address, which may assist - * debugging. */ - pxNewTCB->pxEndOfStack = pxTopOfStack; - } - #endif /* configRECORD_STACK_HIGH_ADDRESS */ + /* Also record the stack's high address, which may assist + * debugging. */ + pxNewTCB->pxEndOfStack = pxTopOfStack; } + #endif /* configRECORD_STACK_HIGH_ADDRESS */ + } #else /* portSTACK_GROWTH */ - { - pxTopOfStack = pxNewTCB->pxStack; + { + pxTopOfStack = pxNewTCB->pxStack; + pxTopOfStack = ( StackType_t * ) ( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) + portBYTE_ALIGNMENT_MASK ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); - /* Check the alignment of the stack buffer is correct. */ - configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + /* Check the alignment of the calculated top of stack is correct. */ + configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); - /* The other extreme of the stack space is required if stack checking is - * performed. */ - pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 ); - } + /* The other extreme of the stack space is required if stack checking is + * performed. */ + pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 ); + } #endif /* portSTACK_GROWTH */ /* Store the task name in the TCB. */ @@ -1480,17 +1877,16 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, /* Ensure the name string is terminated in the case that the string length * was greater or equal to configMAX_TASK_NAME_LEN. */ - pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0'; + pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1U ] = '\0'; } else { - /* The task has not been given a name, so just ensure there is a NULL - * terminator when it is read out. */ - pxNewTCB->pcTaskName[ 0 ] = 0x00; + mtCOVERAGE_TEST_MARKER(); } - /* This is used as an array index so must ensure it's not too large. First - * remove the privilege bit if one is present. */ + /* This is used as an array index so must ensure it's not too large. */ + configASSERT( uxPriority < configMAX_PRIORITIES ); + if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) { uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U; @@ -1502,10 +1898,9 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, pxNewTCB->uxPriority = uxPriority; #if ( configUSE_MUTEXES == 1 ) - { - pxNewTCB->uxBasePriority = uxPriority; - pxNewTCB->uxMutexesHeld = 0; - } + { + pxNewTCB->uxBasePriority = uxPriority; + } #endif /* configUSE_MUTEXES */ vListInitialiseItem( &( pxNewTCB->xStateListItem ) ); @@ -1516,77 +1911,25 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB ); /* Event lists are always in priority order. */ - listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB ); - #if ( portCRITICAL_NESTING_IN_TCB == 1 ) - { - pxNewTCB->uxCriticalNesting = ( UBaseType_t ) 0U; - } - #endif /* portCRITICAL_NESTING_IN_TCB */ - - #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - { - pxNewTCB->pxTaskTag = NULL; - } - #endif /* configUSE_APPLICATION_TASK_TAG */ - - #if ( configGENERATE_RUN_TIME_STATS == 1 ) - { - pxNewTCB->ulRunTimeCounter = 0UL; - } - #endif /* configGENERATE_RUN_TIME_STATS */ - #if ( portUSING_MPU_WRAPPERS == 1 ) - { - vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth ); - } + { + vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth ); + } #else - { - /* Avoid compiler warning about unreferenced parameter. */ - ( void ) xRegions; - } + { + /* Avoid compiler warning about unreferenced parameter. */ + ( void ) xRegions; + } #endif - #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) - { - memset( ( void * ) &( pxNewTCB->pvThreadLocalStoragePointers[ 0 ] ), 0x00, sizeof( pxNewTCB->pvThreadLocalStoragePointers ) ); - } - #endif - - #if ( configUSE_TASK_NOTIFICATIONS == 1 ) - { - memset( ( void * ) &( pxNewTCB->ulNotifiedValue[ 0 ] ), 0x00, sizeof( pxNewTCB->ulNotifiedValue ) ); - memset( ( void * ) &( pxNewTCB->ucNotifyState[ 0 ] ), 0x00, sizeof( pxNewTCB->ucNotifyState ) ); - } - #endif - - #if ( configUSE_NEWLIB_REENTRANT == 1 ) - { - /* Initialise this task's Newlib reent structure. - * See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html - * for additional information. */ - _REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) ); - } - #endif - - #if ( INCLUDE_xTaskAbortDelay == 1 ) - { - pxNewTCB->ucDelayAborted = pdFALSE; - } - #endif - - #if ( configNUM_CORES > 1 ) - #if ( configUSE_CORE_AFFINITY == 1 ) - { - pxNewTCB->uxCoreAffinityMask = tskNO_AFFINITY; - } - #endif - #endif - #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - { - pxNewTCB->xPreemptionDisable = 0; - } + #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) + { + /* Allocate and initialize memory for the task's TLS Block. */ + configINIT_TLS_BLOCK( pxNewTCB->xTLSBlock, pxTopOfStack ); + } #endif /* Initialize the TCB stack to look as if the task was already running, @@ -1594,72 +1937,65 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, * to the start of the task function. Once the stack has been initialised * the top of stack variable is updated. */ #if ( portUSING_MPU_WRAPPERS == 1 ) + { + /* If the port has capability to detect stack overflow, + * pass the stack end address to the stack initialization + * function as well. */ + #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) { - /* If the port has capability to detect stack overflow, - * pass the stack end address to the stack initialization - * function as well. */ - #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) - { - #if ( portSTACK_GROWTH < 0 ) - { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters, xRunPrivileged ); - } - #else /* portSTACK_GROWTH */ - { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters, xRunPrivileged ); - } - #endif /* portSTACK_GROWTH */ - } - #else /* portHAS_STACK_OVERFLOW_CHECKING */ - { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged ); - } - #endif /* portHAS_STACK_OVERFLOW_CHECKING */ + #if ( portSTACK_GROWTH < 0 ) + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters, xRunPrivileged, &( pxNewTCB->xMPUSettings ) ); + } + #else /* portSTACK_GROWTH */ + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters, xRunPrivileged, &( pxNewTCB->xMPUSettings ) ); + } + #endif /* portSTACK_GROWTH */ } + #else /* portHAS_STACK_OVERFLOW_CHECKING */ + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged, &( pxNewTCB->xMPUSettings ) ); + } + #endif /* portHAS_STACK_OVERFLOW_CHECKING */ + } #else /* portUSING_MPU_WRAPPERS */ + { + /* If the port has capability to detect stack overflow, + * pass the stack end address to the stack initialization + * function as well. */ + #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) { - /* If the port has capability to detect stack overflow, - * pass the stack end address to the stack initialization - * function as well. */ - #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) - { - #if ( portSTACK_GROWTH < 0 ) - { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters ); - } - #else /* portSTACK_GROWTH */ - { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters ); - } - #endif /* portSTACK_GROWTH */ - } - #else /* portHAS_STACK_OVERFLOW_CHECKING */ - { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); - } - #endif /* portHAS_STACK_OVERFLOW_CHECKING */ + #if ( portSTACK_GROWTH < 0 ) + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters ); + } + #else /* portSTACK_GROWTH */ + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters ); + } + #endif /* portSTACK_GROWTH */ } + #else /* portHAS_STACK_OVERFLOW_CHECKING */ + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); + } + #endif /* portHAS_STACK_OVERFLOW_CHECKING */ + } #endif /* portUSING_MPU_WRAPPERS */ - /* Initialize to not running */ - pxNewTCB->xTaskRunState = taskTASK_NOT_RUNNING; - - /* Is this an idle task? */ - if( pxTaskCode == prvIdleTask ) + /* Initialize task state and task attributes. */ + #if ( configNUMBER_OF_CORES > 1 ) { - pxNewTCB->xIsIdle = pdTRUE; - } + pxNewTCB->xTaskRunState = taskTASK_NOT_RUNNING; - #if ( configNUM_CORES > 1 ) - else if( pxTaskCode == prvMinimalIdleTask ) + /* Is this an idle task? */ + if( ( ( TaskFunction_t ) pxTaskCode == ( TaskFunction_t ) prvIdleTask ) || ( ( TaskFunction_t ) pxTaskCode == ( TaskFunction_t ) prvPassiveIdleTask ) ) { - pxNewTCB->xIsIdle = pdTRUE; + pxNewTCB->uxTaskAttributes |= taskATTRIBUTE_IS_IDLE; } - #endif - else - { - pxNewTCB->xIsIdle = pdFALSE; } + #endif /* #if ( configNUMBER_OF_CORES > 1 ) */ if( pxCreatedTask != NULL ) { @@ -1674,79 +2010,196 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, } /*-----------------------------------------------------------*/ -static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) -{ - /* Ensure interrupts don't access the task lists while the lists are being - * updated. */ - taskENTER_CRITICAL(); - { - uxCurrentNumberOfTasks++; +#if ( configNUMBER_OF_CORES == 1 ) - if( xSchedulerRunning == pdFALSE ) + static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) + { + /* Ensure interrupts don't access the task lists while the lists are being + * updated. */ + taskENTER_CRITICAL(); { - if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 ) + uxCurrentNumberOfTasks++; + + if( pxCurrentTCB == NULL ) { - /* This is the first task to be created so do the preliminary - * initialisation required. We will not recover if this call - * fails, but we will report the failure. */ - prvInitialiseTaskLists(); + /* There are no other tasks, or all the other tasks are in + * the suspended state - make this the current task. */ + pxCurrentTCB = pxNewTCB; + + if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 ) + { + /* This is the first task to be created so do the preliminary + * initialisation required. We will not recover if this call + * fails, but we will report the failure. */ + prvInitialiseTaskLists(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } else { - mtCOVERAGE_TEST_MARKER(); - } - - if( pxNewTCB->xIsIdle != pdFALSE ) - { - BaseType_t xCoreID; - - /* Check if a core is free. */ - for( xCoreID = ( UBaseType_t ) 0; xCoreID < ( UBaseType_t ) configNUM_CORES; xCoreID++ ) + /* If the scheduler is not already running, make this task the + * current task if it is the highest priority task to be created + * so far. */ + if( xSchedulerRunning == pdFALSE ) { - if( pxCurrentTCBs[ xCoreID ] == NULL ) + if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority ) { - pxNewTCB->xTaskRunState = xCoreID; - pxCurrentTCBs[ xCoreID ] = pxNewTCB; - break; + pxCurrentTCB = pxNewTCB; + } + else + { + mtCOVERAGE_TEST_MARKER(); } } + else + { + mtCOVERAGE_TEST_MARKER(); + } } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - uxTaskNumber++; + uxTaskNumber++; - #if ( configUSE_TRACE_FACILITY == 1 ) + #if ( configUSE_TRACE_FACILITY == 1 ) { /* Add a counter into the TCB for tracing only. */ pxNewTCB->uxTCBNumber = uxTaskNumber; } - #endif /* configUSE_TRACE_FACILITY */ - traceTASK_CREATE( pxNewTCB ); + #endif /* configUSE_TRACE_FACILITY */ + traceTASK_CREATE( pxNewTCB ); - prvAddTaskToReadyList( pxNewTCB ); + prvAddTaskToReadyList( pxNewTCB ); - portSETUP_TCB( pxNewTCB ); + portSETUP_TCB( pxNewTCB ); + } + taskEXIT_CRITICAL(); if( xSchedulerRunning != pdFALSE ) { - /* If the created task is of a higher priority than another - * currently running task and preemption is on then it should - * run now. */ - #if ( configUSE_PREEMPTION == 1 ) - prvYieldForTask( pxNewTCB, pdFALSE ); - #endif + /* If the created task is of a higher priority than the current task + * then it should run now. */ + taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxNewTCB ); } else { mtCOVERAGE_TEST_MARKER(); } } - taskEXIT_CRITICAL(); -} + +#else /* #if ( configNUMBER_OF_CORES == 1 ) */ + + static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) + { + /* Ensure interrupts don't access the task lists while the lists are being + * updated. */ + taskENTER_CRITICAL(); + { + uxCurrentNumberOfTasks++; + + if( xSchedulerRunning == pdFALSE ) + { + if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 ) + { + /* This is the first task to be created so do the preliminary + * initialisation required. We will not recover if this call + * fails, but we will report the failure. */ + prvInitialiseTaskLists(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( ( pxNewTCB->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) != 0U ) + { + BaseType_t xCoreID; + + /* Check if a core is free. */ + for( xCoreID = ( BaseType_t ) 0; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES; xCoreID++ ) + { + if( pxCurrentTCBs[ xCoreID ] == NULL ) + { + pxNewTCB->xTaskRunState = xCoreID; + pxCurrentTCBs[ xCoreID ] = pxNewTCB; + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + uxTaskNumber++; + + #if ( configUSE_TRACE_FACILITY == 1 ) + { + /* Add a counter into the TCB for tracing only. */ + pxNewTCB->uxTCBNumber = uxTaskNumber; + } + #endif /* configUSE_TRACE_FACILITY */ + traceTASK_CREATE( pxNewTCB ); + + prvAddTaskToReadyList( pxNewTCB ); + + portSETUP_TCB( pxNewTCB ); + + if( xSchedulerRunning != pdFALSE ) + { + /* If the created task is of a higher priority than another + * currently running task and preemption is on then it should + * run now. */ + taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxNewTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + } + +#endif /* #if ( configNUMBER_OF_CORES == 1 ) */ +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) + + static size_t prvSnprintfReturnValueToCharsWritten( int iSnprintfReturnValue, + size_t n ) + { + size_t uxCharsWritten; + + if( iSnprintfReturnValue < 0 ) + { + /* Encoding error - Return 0 to indicate that nothing + * was written to the buffer. */ + uxCharsWritten = 0; + } + else if( iSnprintfReturnValue >= ( int ) n ) + { + /* This is the case when the supplied buffer is not + * large to hold the generated string. Return the + * number of characters actually written without + * counting the terminating NULL character. */ + uxCharsWritten = n - 1U; + } + else + { + /* Complete string was written to the buffer. */ + uxCharsWritten = ( size_t ) iSnprintfReturnValue; + } + + return uxCharsWritten; + } + +#endif /* #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */ /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskDelete == 1 ) @@ -1754,7 +2207,8 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) void vTaskDelete( TaskHandle_t xTaskToDelete ) { TCB_t * pxTCB; - TaskRunning_t xTaskRunningOnCore; + + traceENTER_vTaskDelete( xTaskToDelete ); taskENTER_CRITICAL(); { @@ -1762,8 +2216,6 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) * being deleted. */ pxTCB = prvGetTCBFromHandle( xTaskToDelete ); - xTaskRunningOnCore = pxTCB->xTaskRunState; - /* Remove task from the ready/delayed list. */ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) { @@ -1793,13 +2245,14 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) /* If the task is running (or yielding), we must add it to the * termination list so that an idle task can delete it when it is * no longer running. */ - if( xTaskRunningOnCore != taskTASK_NOT_RUNNING ) + if( taskTASK_IS_RUNNING_OR_SCHEDULED_TO_YIELD( pxTCB ) != pdFALSE ) { - /* A running task is being deleted. This cannot complete within the - * task itself, as a context switch to another task is required. - * Place the task in the termination list. The idle task will - * check the termination list and free up any memory allocated by - * the scheduler for the TCB and stack of the deleted task. */ + /* A running task or a task which is scheduled to yield is being + * deleted. This cannot complete when the task is still running + * on a core, as a context switch to another task is required. + * Place the task in the termination list. The idle task will check + * the termination list and free up any memory allocated by the + * scheduler for the TCB and stack of the deleted task. */ vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) ); /* Increment the ucTasksDeleted variable so the idle task knows @@ -1816,38 +2269,79 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) * after which it is not possible to yield away from this task - * hence xYieldPending is used to latch that a context switch is * required. */ - portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPendings[ pxTCB->xTaskRunState ] ); + #if ( configNUMBER_OF_CORES == 1 ) + portPRE_TASK_DELETE_HOOK( pxTCB, &( xYieldPendings[ 0 ] ) ); + #else + portPRE_TASK_DELETE_HOOK( pxTCB, &( xYieldPendings[ pxTCB->xTaskRunState ] ) ); + #endif } else { --uxCurrentNumberOfTasks; traceTASK_DELETE( pxTCB ); - prvDeleteTCB( pxTCB ); /* Reset the next expected unblock time in case it referred to * the task that has just been deleted. */ prvResetNextTaskUnblockTime(); } + } + + #if ( configNUMBER_OF_CORES == 1 ) + { + taskEXIT_CRITICAL(); + + /* If the task is not deleting itself, call prvDeleteTCB from outside of + * critical section. If a task deletes itself, prvDeleteTCB is called + * from prvCheckTasksWaitingTermination which is called from Idle task. */ + if( pxTCB != pxCurrentTCB ) + { + prvDeleteTCB( pxTCB ); + } + + /* Force a reschedule if it is the currently running task that has just + * been deleted. */ + if( xSchedulerRunning != pdFALSE ) + { + if( pxTCB == pxCurrentTCB ) + { + configASSERT( uxSchedulerSuspended == 0 ); + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #else /* #if ( configNUMBER_OF_CORES == 1 ) */ + { + /* If a running task is not deleting itself, call prvDeleteTCB. If a running + * task deletes itself, prvDeleteTCB is called from prvCheckTasksWaitingTermination + * which is called from Idle task. */ + if( pxTCB->xTaskRunState == taskTASK_NOT_RUNNING ) + { + prvDeleteTCB( pxTCB ); + } /* Force a reschedule if the task that has just been deleted was running. */ - if( ( xSchedulerRunning != pdFALSE ) && ( taskTASK_IS_RUNNING( xTaskRunningOnCore ) ) ) + if( ( xSchedulerRunning != pdFALSE ) && ( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) ) { - BaseType_t xCoreID; - - xCoreID = portGET_CORE_ID(); - - if( xTaskRunningOnCore == xCoreID ) + if( pxTCB->xTaskRunState == ( BaseType_t ) portGET_CORE_ID() ) { configASSERT( uxSchedulerSuspended == 0 ); vTaskYieldWithinAPI(); } else { - prvYieldCore( xTaskRunningOnCore ); + prvYieldCore( pxTCB->xTaskRunState ); } } + + taskEXIT_CRITICAL(); } - taskEXIT_CRITICAL(); + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ + + traceRETURN_vTaskDelete(); } #endif /* INCLUDE_vTaskDelete */ @@ -1861,17 +2355,19 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) TickType_t xTimeToWake; BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE; + traceENTER_xTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ); + configASSERT( pxPreviousWakeTime ); configASSERT( ( xTimeIncrement > 0U ) ); vTaskSuspendAll(); { - configASSERT( uxSchedulerSuspended == 1 ); - /* Minor optimisation. The tick count cannot change in this * block. */ const TickType_t xConstTickCount = xTickCount; + configASSERT( uxSchedulerSuspended == 1U ); + /* Generate the tick time at which the task wants to wake. */ xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; @@ -1928,13 +2424,15 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) * have put ourselves to sleep. */ if( xAlreadyYielded == pdFALSE ) { - vTaskYieldWithinAPI(); + taskYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } + traceRETURN_xTaskDelayUntil( xShouldDelay ); + return xShouldDelay; } @@ -1947,12 +2445,15 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) { BaseType_t xAlreadyYielded = pdFALSE; + traceENTER_vTaskDelay( xTicksToDelay ); + /* A delay time of zero just forces a reschedule. */ if( xTicksToDelay > ( TickType_t ) 0U ) { vTaskSuspendAll(); { - configASSERT( uxSchedulerSuspended == 1 ); + configASSERT( uxSchedulerSuspended == 1U ); + traceTASK_DELAY(); /* A task that is removed from the event list while the @@ -1975,12 +2476,14 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) * have put ourselves to sleep. */ if( xAlreadyYielded == pdFALSE ) { - vTaskYieldWithinAPI(); + taskYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } + + traceRETURN_vTaskDelay(); } #endif /* INCLUDE_vTaskDelay */ @@ -1991,35 +2494,57 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) eTaskState eTaskGetState( TaskHandle_t xTask ) { eTaskState eReturn; - List_t const * pxStateList, * pxDelayedList, * pxOverflowedDelayedList; + List_t const * pxStateList; + List_t const * pxEventList; + List_t const * pxDelayedList; + List_t const * pxOverflowedDelayedList; const TCB_t * const pxTCB = xTask; + traceENTER_eTaskGetState( xTask ); + configASSERT( pxTCB ); - taskENTER_CRITICAL(); - { - pxStateList = listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) ); - pxDelayedList = pxDelayedTaskList; - pxOverflowedDelayedList = pxOverflowDelayedTaskList; - } - taskEXIT_CRITICAL(); - - if( ( pxStateList == pxDelayedList ) || ( pxStateList == pxOverflowedDelayedList ) ) - { - /* The task being queried is referenced from one of the Blocked - * lists. */ - eReturn = eBlocked; - } - - #if ( INCLUDE_vTaskSuspend == 1 ) - else if( pxStateList == &xSuspendedTaskList ) + #if ( configNUMBER_OF_CORES == 1 ) + if( pxTCB == pxCurrentTCB ) { - /* The task being queried is referenced from the suspended - * list. Is it genuinely suspended or is it blocked - * indefinitely? */ - if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ) + /* The task calling this function is querying its own state. */ + eReturn = eRunning; + } + else + #endif + { + taskENTER_CRITICAL(); + { + pxStateList = listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) ); + pxEventList = listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ); + pxDelayedList = pxDelayedTaskList; + pxOverflowedDelayedList = pxOverflowDelayedTaskList; + } + taskEXIT_CRITICAL(); + + if( pxEventList == &xPendingReadyList ) + { + /* The task has been placed on the pending ready list, so its + * state is eReady regardless of what list the task's state list + * item is currently placed on. */ + eReturn = eReady; + } + else if( ( pxStateList == pxDelayedList ) || ( pxStateList == pxOverflowedDelayedList ) ) + { + /* The task being queried is referenced from one of the Blocked + * lists. */ + eReturn = eBlocked; + } + + #if ( INCLUDE_vTaskSuspend == 1 ) + else if( pxStateList == &xSuspendedTaskList ) { - #if ( configUSE_TASK_NOTIFICATIONS == 1 ) + /* The task being queried is referenced from the suspended + * list. Is it genuinely suspended or is it blocked + * indefinitely? */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ) + { + #if ( configUSE_TASK_NOTIFICATIONS == 1 ) { BaseType_t x; @@ -2030,7 +2555,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) * suspended. */ eReturn = eSuspended; - for( x = 0; x < configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ ) + for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ ) { if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION ) { @@ -2039,46 +2564,59 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) } } } - #else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */ + #else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */ { eReturn = eSuspended; } - #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */ + #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */ + } + else + { + eReturn = eBlocked; + } } - else + #endif /* if ( INCLUDE_vTaskSuspend == 1 ) */ + + #if ( INCLUDE_vTaskDelete == 1 ) + else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) ) { - eReturn = eBlocked; + /* The task being queried is referenced from the deleted + * tasks list, or it is not referenced from any lists at + * all. */ + eReturn = eDeleted; } - } - #endif /* if ( INCLUDE_vTaskSuspend == 1 ) */ + #endif - #if ( INCLUDE_vTaskDelete == 1 ) - else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) ) - { - /* The task being queried is referenced from the deleted - * tasks list, or it is not referenced from any lists at - * all. */ - eReturn = eDeleted; - } - #endif - - else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */ - { - /* If the task is not in any other state, it must be in the - * Ready (including pending ready) state. */ - if( taskTASK_IS_RUNNING( pxTCB->xTaskRunState ) ) - { - /* Is it actively running on a core? */ - eReturn = eRunning; - } else { - eReturn = eReady; + #if ( configNUMBER_OF_CORES == 1 ) + { + /* If the task is not in any other state, it must be in the + * Ready (including pending ready) state. */ + eReturn = eReady; + } + #else /* #if ( configNUMBER_OF_CORES == 1 ) */ + { + if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + { + /* Is it actively running on a core? */ + eReturn = eRunning; + } + else + { + /* If the task is not in any other state, it must be in the + * Ready (including pending ready) state. */ + eReturn = eReady; + } + } + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ } } + traceRETURN_eTaskGetState( eReturn ); + return eReturn; - } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */ + } #endif /* INCLUDE_eTaskGetState */ /*-----------------------------------------------------------*/ @@ -2090,6 +2628,8 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) TCB_t const * pxTCB; UBaseType_t uxReturn; + traceENTER_uxTaskPriorityGet( xTask ); + taskENTER_CRITICAL(); { /* If null is passed in here then it is the priority of the task @@ -2099,6 +2639,8 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) } taskEXIT_CRITICAL(); + traceRETURN_uxTaskPriorityGet( uxReturn ); + return uxReturn; } @@ -2110,7 +2652,10 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) { TCB_t const * pxTCB; - UBaseType_t uxReturn, uxSavedInterruptState; + UBaseType_t uxReturn; + UBaseType_t uxSavedInterruptStatus; + + traceENTER_uxTaskPriorityGetFromISR( xTask ); /* RTOS ports that support interrupt nesting have the concept of a * maximum system call (or maximum API call) interrupt priority. @@ -2130,14 +2675,16 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - uxSavedInterruptState = portSET_INTERRUPT_MASK_FROM_ISR(); + uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); { /* If null is passed in here then it is the priority of the calling * task that is being queried. */ pxTCB = prvGetTCBFromHandle( xTask ); uxReturn = pxTCB->uxPriority; } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState ); + taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); + + traceRETURN_uxTaskPriorityGetFromISR( uxReturn ); return uxReturn; } @@ -2145,6 +2692,77 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) #endif /* INCLUDE_uxTaskPriorityGet */ /*-----------------------------------------------------------*/ +#if ( ( INCLUDE_uxTaskPriorityGet == 1 ) && ( configUSE_MUTEXES == 1 ) ) + + UBaseType_t uxTaskBasePriorityGet( const TaskHandle_t xTask ) + { + TCB_t const * pxTCB; + UBaseType_t uxReturn; + + traceENTER_uxTaskBasePriorityGet( xTask ); + + taskENTER_CRITICAL(); + { + /* If null is passed in here then it is the base priority of the task + * that called uxTaskBasePriorityGet() that is being queried. */ + pxTCB = prvGetTCBFromHandle( xTask ); + uxReturn = pxTCB->uxBasePriority; + } + taskEXIT_CRITICAL(); + + traceRETURN_uxTaskBasePriorityGet( uxReturn ); + + return uxReturn; + } + +#endif /* #if ( ( INCLUDE_uxTaskPriorityGet == 1 ) && ( configUSE_MUTEXES == 1 ) ) */ +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_uxTaskPriorityGet == 1 ) && ( configUSE_MUTEXES == 1 ) ) + + UBaseType_t uxTaskBasePriorityGetFromISR( const TaskHandle_t xTask ) + { + TCB_t const * pxTCB; + UBaseType_t uxReturn; + UBaseType_t uxSavedInterruptStatus; + + traceENTER_uxTaskBasePriorityGetFromISR( xTask ); + + /* RTOS ports that support interrupt nesting have the concept of a + * maximum system call (or maximum API call) interrupt priority. + * Interrupts that are above the maximum system call priority are keep + * permanently enabled, even when the RTOS kernel is in a critical section, + * but cannot make any calls to FreeRTOS API functions. If configASSERT() + * is defined in FreeRTOSConfig.h then + * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + * failure if a FreeRTOS API function is called from an interrupt that has + * been assigned a priority above the configured maximum system call + * priority. Only FreeRTOS functions that end in FromISR can be called + * from interrupts that have been assigned a priority at or (logically) + * below the maximum system call interrupt priority. FreeRTOS maintains a + * separate interrupt safe API to ensure interrupt entry is as fast and as + * simple as possible. More information (albeit Cortex-M specific) is + * provided on the following link: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); + { + /* If null is passed in here then it is the base priority of the calling + * task that is being queried. */ + pxTCB = prvGetTCBFromHandle( xTask ); + uxReturn = pxTCB->uxBasePriority; + } + taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); + + traceRETURN_uxTaskBasePriorityGetFromISR( uxReturn ); + + return uxReturn; + } + +#endif /* #if ( ( INCLUDE_uxTaskPriorityGet == 1 ) && ( configUSE_MUTEXES == 1 ) ) */ +/*-----------------------------------------------------------*/ + #if ( INCLUDE_vTaskPrioritySet == 1 ) void vTaskPrioritySet( TaskHandle_t xTask, @@ -2153,10 +2771,14 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) TCB_t * pxTCB; UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry; BaseType_t xYieldRequired = pdFALSE; - BaseType_t xYieldForTask = pdFALSE; - BaseType_t xCoreID; - configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) ); + #if ( configNUMBER_OF_CORES > 1 ) + BaseType_t xYieldForTask = pdFALSE; + #endif + + traceENTER_vTaskPrioritySet( xTask, uxNewPriority ); + + configASSERT( uxNewPriority < configMAX_PRIORITIES ); /* Ensure the new priority is valid. */ if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) @@ -2177,13 +2799,13 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) traceTASK_PRIORITY_SET( pxTCB, uxNewPriority ); #if ( configUSE_MUTEXES == 1 ) - { - uxCurrentBasePriority = pxTCB->uxBasePriority; - } + { + uxCurrentBasePriority = pxTCB->uxBasePriority; + } #else - { - uxCurrentBasePriority = pxTCB->uxPriority; - } + { + uxCurrentBasePriority = pxTCB->uxPriority; + } #endif if( uxCurrentBasePriority != uxNewPriority ) @@ -2192,11 +2814,38 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) * priority than a running task. */ if( uxNewPriority > uxCurrentBasePriority ) { - /* The priority of a task is being raised so - * perform a yield for this task later. */ - xYieldForTask = pdTRUE; + #if ( configNUMBER_OF_CORES == 1 ) + { + if( pxTCB != pxCurrentTCB ) + { + /* The priority of a task other than the currently + * running task is being raised. Is the priority being + * raised above that of the running task? */ + if( uxNewPriority > pxCurrentTCB->uxPriority ) + { + xYieldRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* The priority of the running task is being raised, + * but the running task must already be the highest + * priority task able to run so no yield is required. */ + } + } + #else /* #if ( configNUMBER_OF_CORES == 1 ) */ + { + /* The priority of a task is being raised so + * perform a yield for this task later. */ + xYieldForTask = pdTRUE; + } + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ } - else if( taskTASK_IS_RUNNING( pxTCB->xTaskRunState ) ) + else if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) { /* Setting the priority of a running task down means * there may now be another task of higher priority that @@ -2205,7 +2854,6 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) if( pxTCB->xPreemptionDisable == pdFALSE ) #endif { - xCoreID = ( BaseType_t ) pxTCB->xTaskRunState; xYieldRequired = pdTRUE; } } @@ -2222,32 +2870,33 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) uxPriorityUsedOnEntry = pxTCB->uxPriority; #if ( configUSE_MUTEXES == 1 ) - { - /* Only change the priority being used if the task is not - * currently using an inherited priority. */ - if( pxTCB->uxBasePriority == pxTCB->uxPriority ) - { - pxTCB->uxPriority = uxNewPriority; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - /* The base priority gets set whatever. */ - pxTCB->uxBasePriority = uxNewPriority; - } - #else /* if ( configUSE_MUTEXES == 1 ) */ + { + /* Only change the priority being used if the task is not + * currently using an inherited priority or the new priority + * is bigger than the inherited priority. */ + if( ( pxTCB->uxBasePriority == pxTCB->uxPriority ) || ( uxNewPriority > pxTCB->uxPriority ) ) { pxTCB->uxPriority = uxNewPriority; } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The base priority gets set whatever. */ + pxTCB->uxBasePriority = uxNewPriority; + } + #else /* if ( configUSE_MUTEXES == 1 ) */ + { + pxTCB->uxPriority = uxNewPriority; + } #endif /* if ( configUSE_MUTEXES == 1 ) */ /* Only reset the event list item value if the value is not * being used for anything else. */ - if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) + if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == ( ( TickType_t ) 0UL ) ) { - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); } else { @@ -2279,26 +2928,41 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) } else { - /* It's possible that xYieldForTask was already set to pdTRUE because - * its priority is being raised. However, since it is not in a ready list - * we don't actually need to yield for it. */ - xYieldForTask = pdFALSE; - } - - #if ( configUSE_PREEMPTION == 1 ) - if( xYieldRequired != pdFALSE ) - { - prvYieldCore( xCoreID ); - } - else if( xYieldForTask != pdFALSE ) - { - prvYieldForTask( pxTCB, pdTRUE ); - } - else + #if ( configNUMBER_OF_CORES == 1 ) { mtCOVERAGE_TEST_MARKER(); } - #endif /* if ( configUSE_PREEMPTION == 1 ) */ + #else + { + /* It's possible that xYieldForTask was already set to pdTRUE because + * its priority is being raised. However, since it is not in a ready list + * we don't actually need to yield for it. */ + xYieldForTask = pdFALSE; + } + #endif + } + + if( xYieldRequired != pdFALSE ) + { + /* The running task priority is set down. Request the task to yield. */ + taskYIELD_TASK_CORE_IF_USING_PREEMPTION( pxTCB ); + } + else + { + #if ( configNUMBER_OF_CORES > 1 ) + if( xYieldForTask != pdFALSE ) + { + /* The priority of the task is being raised. If a running + * task has priority lower than this task, it should yield + * for this task. */ + taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB ); + } + else + #endif /* if ( configNUMBER_OF_CORES > 1 ) */ + { + mtCOVERAGE_TEST_MARKER(); + } + } /* Remove compiler warning about unused variables when the port * optimised task selection is not being used. */ @@ -2306,66 +2970,98 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) } } taskEXIT_CRITICAL(); + + traceRETURN_vTaskPrioritySet(); } #endif /* INCLUDE_vTaskPrioritySet */ /*-----------------------------------------------------------*/ -#if ( configNUM_CORES > 1 ) - #if ( configUSE_CORE_AFFINITY == 1 ) +#if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) + void vTaskCoreAffinitySet( const TaskHandle_t xTask, + UBaseType_t uxCoreAffinityMask ) + { + TCB_t * pxTCB; + BaseType_t xCoreID; + UBaseType_t uxPrevCoreAffinityMask; - void vTaskCoreAffinitySet( const TaskHandle_t xTask, - UBaseType_t uxCoreAffinityMask ) + #if ( configUSE_PREEMPTION == 1 ) + UBaseType_t uxPrevNotAllowedCores; + #endif + + traceENTER_vTaskCoreAffinitySet( xTask, uxCoreAffinityMask ); + + taskENTER_CRITICAL(); { - TCB_t * pxTCB; - BaseType_t xCoreID; + pxTCB = prvGetTCBFromHandle( xTask ); - taskENTER_CRITICAL(); + uxPrevCoreAffinityMask = pxTCB->uxCoreAffinityMask; + pxTCB->uxCoreAffinityMask = uxCoreAffinityMask; + + if( xSchedulerRunning != pdFALSE ) { - pxTCB = prvGetTCBFromHandle( xTask ); - - pxTCB->uxCoreAffinityMask = uxCoreAffinityMask; - - if( xSchedulerRunning != pdFALSE ) + if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) { - if( taskTASK_IS_RUNNING( pxTCB->xTaskRunState ) ) - { - xCoreID = ( BaseType_t ) pxTCB->xTaskRunState; + xCoreID = ( BaseType_t ) pxTCB->xTaskRunState; - if( ( uxCoreAffinityMask & ( 1 << xCoreID ) ) == 0 ) - { - prvYieldCore( xCoreID ); - } + /* If the task can no longer run on the core it was running, + * request the core to yield. */ + if( ( uxCoreAffinityMask & ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ) ) == 0U ) + { + prvYieldCore( xCoreID ); } } - } - taskEXIT_CRITICAL(); - } + else + { + #if ( configUSE_PREEMPTION == 1 ) + { + /* Calculate the cores on which this task was not allowed to + * run previously. */ + uxPrevNotAllowedCores = ( ~uxPrevCoreAffinityMask ) & ( ( 1U << configNUMBER_OF_CORES ) - 1U ); - #endif /* configUSE_CORE_AFFINITY */ -#endif /* if ( configNUM_CORES > 1 ) */ + /* Does the new core mask enables this task to run on any of the + * previously not allowed cores? If yes, check if this task can be + * scheduled on any of those cores. */ + if( ( uxPrevNotAllowedCores & uxCoreAffinityMask ) != 0U ) + { + prvYieldForTask( pxTCB ); + } + } + #else /* #if( configUSE_PREEMPTION == 1 ) */ + { + mtCOVERAGE_TEST_MARKER(); + } + #endif /* #if( configUSE_PREEMPTION == 1 ) */ + } + } + } + taskEXIT_CRITICAL(); + + traceRETURN_vTaskCoreAffinitySet(); + } +#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ /*-----------------------------------------------------------*/ -#if ( configNUM_CORES > 1 ) - #if ( configUSE_CORE_AFFINITY == 1 ) +#if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) + UBaseType_t vTaskCoreAffinityGet( ConstTaskHandle_t xTask ) + { + const TCB_t * pxTCB; + UBaseType_t uxCoreAffinityMask; - UBaseType_t vTaskCoreAffinityGet( const TaskHandle_t xTask ) + traceENTER_vTaskCoreAffinityGet( xTask ); + + taskENTER_CRITICAL(); { - TCB_t * pxTCB; - UBaseType_t uxCoreAffinityMask; - - taskENTER_CRITICAL(); - { - pxTCB = prvGetTCBFromHandle( xTask ); - uxCoreAffinityMask = pxTCB->uxCoreAffinityMask; - } - taskEXIT_CRITICAL(); - - return uxCoreAffinityMask; + pxTCB = prvGetTCBFromHandle( xTask ); + uxCoreAffinityMask = pxTCB->uxCoreAffinityMask; } + taskEXIT_CRITICAL(); - #endif /* configUSE_CORE_AFFINITY */ -#endif /* if ( configNUM_CORES > 1 ) */ + traceRETURN_vTaskCoreAffinityGet( uxCoreAffinityMask ); + + return uxCoreAffinityMask; + } +#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ /*-----------------------------------------------------------*/ @@ -2375,6 +3071,8 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) { TCB_t * pxTCB; + traceENTER_vTaskPreemptionDisable( xTask ); + taskENTER_CRITICAL(); { pxTCB = prvGetTCBFromHandle( xTask ); @@ -2382,9 +3080,11 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) pxTCB->xPreemptionDisable = pdTRUE; } taskEXIT_CRITICAL(); + + traceRETURN_vTaskPreemptionDisable(); } -#endif /* configUSE_TASK_PREEMPTION_DISABLE */ +#endif /* #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */ /*-----------------------------------------------------------*/ #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) @@ -2394,6 +3094,8 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) TCB_t * pxTCB; BaseType_t xCoreID; + traceENTER_vTaskPreemptionEnable( xTask ); + taskENTER_CRITICAL(); { pxTCB = prvGetTCBFromHandle( xTask ); @@ -2402,7 +3104,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) if( xSchedulerRunning != pdFALSE ) { - if( taskTASK_IS_RUNNING( pxTCB->xTaskRunState ) ) + if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) { xCoreID = ( BaseType_t ) pxTCB->xTaskRunState; prvYieldCore( xCoreID ); @@ -2410,9 +3112,11 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) } } taskEXIT_CRITICAL(); + + traceRETURN_vTaskPreemptionEnable(); } -#endif /* configUSE_TASK_PREEMPTION_DISABLE */ +#endif /* #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */ /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskSuspend == 1 ) @@ -2420,7 +3124,12 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) void vTaskSuspend( TaskHandle_t xTaskToSuspend ) { TCB_t * pxTCB; - TaskRunning_t xTaskRunningOnCore; + + #if ( configNUMBER_OF_CORES > 1 ) + BaseType_t xTaskRunningOnCore; + #endif + + traceENTER_vTaskSuspend( xTaskToSuspend ); taskENTER_CRITICAL(); { @@ -2430,7 +3139,9 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) traceTASK_SUSPEND( pxTCB ); - xTaskRunningOnCore = pxTCB->xTaskRunState; + #if ( configNUMBER_OF_CORES > 1 ) + xTaskRunningOnCore = pxTCB->xTaskRunState; + #endif /* Remove task from the ready/delayed list and place in the * suspended list. */ @@ -2456,21 +3167,75 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ); #if ( configUSE_TASK_NOTIFICATIONS == 1 ) - { - BaseType_t x; + { + BaseType_t x; - for( x = 0; x < configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ ) + for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ ) + { + if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION ) { - if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION ) - { - /* The task was blocked to wait for a notification, but is - * now suspended, so no notification was received. */ - pxTCB->ucNotifyState[ x ] = taskNOT_WAITING_NOTIFICATION; - } + /* The task was blocked to wait for a notification, but is + * now suspended, so no notification was received. */ + pxTCB->ucNotifyState[ x ] = taskNOT_WAITING_NOTIFICATION; } } + } #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */ + } + #if ( configNUMBER_OF_CORES == 1 ) + { + taskEXIT_CRITICAL(); + + if( xSchedulerRunning != pdFALSE ) + { + /* Reset the next expected unblock time in case it referred to the + * task that is now in the Suspended state. */ + taskENTER_CRITICAL(); + { + prvResetNextTaskUnblockTime(); + } + taskEXIT_CRITICAL(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( pxTCB == pxCurrentTCB ) + { + if( xSchedulerRunning != pdFALSE ) + { + /* The current task has just been suspended. */ + configASSERT( uxSchedulerSuspended == 0 ); + portYIELD_WITHIN_API(); + } + else + { + /* The scheduler is not running, but the task that was pointed + * to by pxCurrentTCB has just been suspended and pxCurrentTCB + * must be adjusted to point to a different task. */ + if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) + { + /* No other tasks are ready, so set pxCurrentTCB back to + * NULL so when the next task is created pxCurrentTCB will + * be set to point to it no matter what its relative priority + * is. */ + pxCurrentTCB = NULL; + } + else + { + vTaskSwitchContext(); + } + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #else /* #if ( configNUMBER_OF_CORES == 1 ) */ + { if( xSchedulerRunning != pdFALSE ) { /* Reset the next expected unblock time in case it referred to the @@ -2482,11 +3247,11 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) mtCOVERAGE_TEST_MARKER(); } - if( taskTASK_IS_RUNNING( xTaskRunningOnCore ) ) + if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) { if( xSchedulerRunning != pdFALSE ) { - if( xTaskRunningOnCore == portGET_CORE_ID() ) + if( xTaskRunningOnCore == ( BaseType_t ) portGET_CORE_ID() ) { /* The current task has just been suspended. */ configASSERT( uxSchedulerSuspended == 0 ); @@ -2496,45 +3261,27 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) { prvYieldCore( xTaskRunningOnCore ); } - - taskEXIT_CRITICAL(); } else { - taskEXIT_CRITICAL(); - - configASSERT( pxTCB == pxCurrentTCBs[ xTaskRunningOnCore ] ); - - /* The scheduler is not running, but the task that was pointed - * to by pxCurrentTCB has just been suspended and pxCurrentTCB - * must be adjusted to point to a different task. */ - if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) /*lint !e931 Right has no side effect, just volatile. */ - { - /* No other tasks are ready, so set the core's TCB back to - * NULL so when the next task is created the core's TCB will - * be able to be set to point to it no matter what its relative - * priority is. */ - pxTCB->xTaskRunState = taskTASK_NOT_RUNNING; - pxCurrentTCBs[ xTaskRunningOnCore ] = NULL; - } - else - { - /* Attempt to switch in a new task. This could fail since the idle tasks - * haven't been created yet. If it does then set the core's TCB back to - * NULL. */ - if( prvSelectHighestPriorityTask( xTaskRunningOnCore ) == pdFALSE ) - { - pxTCB->xTaskRunState = taskTASK_NOT_RUNNING; - pxCurrentTCBs[ xTaskRunningOnCore ] = NULL; - } - } + /* This code path is not possible because only Idle tasks are + * assigned a core before the scheduler is started ( i.e. + * taskTASK_IS_RUNNING is only true for idle tasks before + * the scheduler is started ) and idle tasks cannot be + * suspended. */ + mtCOVERAGE_TEST_MARKER(); } } else { - taskEXIT_CRITICAL(); + mtCOVERAGE_TEST_MARKER(); } - } /* taskEXIT_CRITICAL() - already exited in one of three cases above */ + + taskEXIT_CRITICAL(); + } + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ + + traceRETURN_vTaskSuspend(); } #endif /* INCLUDE_vTaskSuspend */ @@ -2547,7 +3294,8 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) BaseType_t xReturn = pdFALSE; const TCB_t * const pxTCB = xTask; - /* Accesses xPendingReadyList so must be called from a critical section. */ + /* Accesses xPendingReadyList so must be called from a critical + * section. */ /* It does not make sense to check if the calling task is suspended. */ configASSERT( xTask ); @@ -2559,10 +3307,34 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE ) { /* Is it in the suspended list because it is in the Suspended - * state, or because is is blocked with no timeout? */ - if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) /*lint !e961. The cast is only redundant when NULL is used. */ + * state, or because it is blocked with no timeout? */ + if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) { - xReturn = pdTRUE; + #if ( configUSE_TASK_NOTIFICATIONS == 1 ) + { + BaseType_t x; + + /* The task does not appear on the event list item of + * and of the RTOS objects, but could still be in the + * blocked state if it is waiting on its notification + * rather than waiting on an object. If not, is + * suspended. */ + xReturn = pdTRUE; + + for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ ) + { + if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION ) + { + xReturn = pdFALSE; + break; + } + } + } + #else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */ + { + xReturn = pdTRUE; + } + #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */ } else { @@ -2580,7 +3352,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) } return xReturn; - } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */ + } #endif /* INCLUDE_vTaskSuspend */ /*-----------------------------------------------------------*/ @@ -2591,15 +3363,25 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) { TCB_t * const pxTCB = xTaskToResume; + traceENTER_vTaskResume( xTaskToResume ); + /* It does not make sense to resume the calling task. */ configASSERT( xTaskToResume ); - /* The parameter cannot be NULL as it is impossible to resume the - * currently executing task. It is also impossible to resume a task - * that is actively running on another core but it is too dangerous - * to check their run state here. Safer to get into a critical section - * and check if it is actually suspended or not below. */ - if( pxTCB != NULL ) + #if ( configNUMBER_OF_CORES == 1 ) + + /* The parameter cannot be NULL as it is impossible to resume the + * currently executing task. */ + if( ( pxTCB != pxCurrentTCB ) && ( pxTCB != NULL ) ) + #else + + /* The parameter cannot be NULL as it is impossible to resume the + * currently executing task. It is also impossible to resume a task + * that is actively running on another core but it is not safe + * to check their run state here. Therefore, we get into a critical + * section and check if the task is actually suspended or not. */ + if( pxTCB != NULL ) + #endif { taskENTER_CRITICAL(); { @@ -2612,12 +3394,10 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); prvAddTaskToReadyList( pxTCB ); - /* A higher priority task may have just been resumed. */ - #if ( configUSE_PREEMPTION == 1 ) - { - prvYieldForTask( pxTCB, pdTRUE ); - } - #endif + /* This yield may not cause the task just resumed to run, + * but will leave the lists in the correct state for the + * next yield. */ + taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB ); } else { @@ -2630,6 +3410,8 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) { mtCOVERAGE_TEST_MARKER(); } + + traceRETURN_vTaskResume(); } #endif /* INCLUDE_vTaskSuspend */ @@ -2644,6 +3426,8 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) TCB_t * const pxTCB = xTaskToResume; UBaseType_t uxSavedInterruptStatus; + traceENTER_xTaskResumeFromISR( xTaskToResume ); + configASSERT( xTaskToResume ); /* RTOS ports that support interrupt nesting have the concept of a @@ -2664,17 +3448,34 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); { if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ) { traceTASK_RESUME_FROM_ISR( pxTCB ); /* Check the ready lists can be accessed. */ - if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + if( uxSchedulerSuspended == ( UBaseType_t ) 0U ) { - /* Ready lists can be accessed so move the task from the - * suspended list to the ready list directly. */ + #if ( configNUMBER_OF_CORES == 1 ) + { + /* Ready lists can be accessed so move the task from the + * suspended list to the ready list directly. */ + if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) + { + xYieldRequired = pdTRUE; + + /* Mark that a yield is pending in case the user is not + * using the return value to initiate a context switch + * from the ISR using the port specific portYIELD_FROM_ISR(). */ + xYieldPendings[ 0 ] = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); prvAddTaskToReadyList( pxTCB ); @@ -2687,21 +3488,25 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); } - #if ( configUSE_PREEMPTION == 1 ) - prvYieldForTask( pxTCB, pdTRUE ); + #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PREEMPTION == 1 ) ) + { + prvYieldForTask( pxTCB ); if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE ) { xYieldRequired = pdTRUE; } - #endif + } + #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PREEMPTION == 1 ) ) */ } else { mtCOVERAGE_TEST_MARKER(); } } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); + + traceRETURN_xTaskResumeFromISR( xYieldRequired ); return xYieldRequired; } @@ -2714,12 +3519,130 @@ static BaseType_t prvCreateIdleTasks( void ) BaseType_t xReturn = pdPASS; BaseType_t xCoreID; char cIdleName[ configMAX_TASK_NAME_LEN ]; + TaskFunction_t pxIdleTaskFunction = NULL; + BaseType_t xIdleTaskNameIndex; + + for( xIdleTaskNameIndex = ( BaseType_t ) 0; xIdleTaskNameIndex < ( BaseType_t ) configMAX_TASK_NAME_LEN; xIdleTaskNameIndex++ ) + { + cIdleName[ xIdleTaskNameIndex ] = configIDLE_TASK_NAME[ xIdleTaskNameIndex ]; + + /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than + * configMAX_TASK_NAME_LEN characters just in case the memory after the + * string is not accessible (extremely unlikely). */ + if( cIdleName[ xIdleTaskNameIndex ] == ( char ) 0x00 ) + { + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } /* Add each idle task at the lowest priority. */ - for( xCoreID = ( BaseType_t ) 0; xCoreID < ( BaseType_t ) configNUM_CORES; xCoreID++ ) + for( xCoreID = ( BaseType_t ) 0; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES; xCoreID++ ) { - BaseType_t x; + #if ( configNUMBER_OF_CORES == 1 ) + { + pxIdleTaskFunction = prvIdleTask; + } + #else /* #if ( configNUMBER_OF_CORES == 1 ) */ + { + /* In the FreeRTOS SMP, configNUMBER_OF_CORES - 1 passive idle tasks + * are also created to ensure that each core has an idle task to + * run when no other task is available to run. */ + if( xCoreID == 0 ) + { + pxIdleTaskFunction = prvIdleTask; + } + else + { + pxIdleTaskFunction = prvPassiveIdleTask; + } + } + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ + /* Update the idle task name with suffix to differentiate the idle tasks. + * This function is not required in single core FreeRTOS since there is + * only one idle task. */ + #if ( configNUMBER_OF_CORES > 1 ) + { + /* Append the idle task number to the end of the name if there is space. */ + if( xIdleTaskNameIndex < ( BaseType_t ) configMAX_TASK_NAME_LEN ) + { + cIdleName[ xIdleTaskNameIndex ] = ( char ) ( xCoreID + '0' ); + + /* And append a null character if there is space. */ + if( ( xIdleTaskNameIndex + 1 ) < ( BaseType_t ) configMAX_TASK_NAME_LEN ) + { + cIdleName[ xIdleTaskNameIndex + 1 ] = '\0'; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* if ( configNUMBER_OF_CORES > 1 ) */ + + #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + { + StaticTask_t * pxIdleTaskTCBBuffer = NULL; + StackType_t * pxIdleTaskStackBuffer = NULL; + uint32_t ulIdleTaskStackSize; + + /* The Idle task is created using user provided RAM - obtain the + * address of the RAM then create the idle task. */ + #if ( configNUMBER_OF_CORES == 1 ) + { + vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize ); + } + #else + { + if( xCoreID == 0 ) + { + vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize ); + } + else + { + vApplicationGetPassiveIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize, xCoreID - 1 ); + } + } + #endif /* if ( configNUMBER_OF_CORES == 1 ) */ + xIdleTaskHandles[ xCoreID ] = xTaskCreateStatic( pxIdleTaskFunction, + cIdleName, + ulIdleTaskStackSize, + ( void * ) NULL, + portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */ + pxIdleTaskStackBuffer, + pxIdleTaskTCBBuffer ); + + if( xIdleTaskHandles[ xCoreID ] != NULL ) + { + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + } + #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ + { + /* The Idle task is being created using dynamically allocated RAM. */ + xReturn = xTaskCreate( pxIdleTaskFunction, + cIdleName, + configMINIMAL_STACK_SIZE, + ( void * ) NULL, + portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */ + &xIdleTaskHandles[ xCoreID ] ); + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ + + /* Break the loop if any of the idle task is failed to be created. */ if( xReturn == pdFAIL ) { break; @@ -2728,141 +3651,51 @@ static BaseType_t prvCreateIdleTasks( void ) { mtCOVERAGE_TEST_MARKER(); } - - for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configMAX_TASK_NAME_LEN; x++ ) - { - cIdleName[ x ] = configIDLE_TASK_NAME[ x ]; - - /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than - * configMAX_TASK_NAME_LEN characters just in case the memory after the - * string is not accessible (extremely unlikely). */ - if( cIdleName[ x ] == ( char ) 0x00 ) - { - break; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - - /* Append the idle task number to the end of the name if there is space */ - if( x < configMAX_TASK_NAME_LEN ) - { - cIdleName[ x++ ] = xCoreID + '0'; - - /* And append a null character if there is space */ - if( x < configMAX_TASK_NAME_LEN ) - { - cIdleName[ x ] = '\0'; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) - { - if( xCoreID == 0 ) - { - StaticTask_t * pxIdleTaskTCBBuffer = NULL; - StackType_t * pxIdleTaskStackBuffer = NULL; - uint32_t ulIdleTaskStackSize; - - /* The Idle task is created using user provided RAM - obtain the - * address of the RAM then create the idle task. */ - vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize ); - xIdleTaskHandle[ xCoreID ] = xTaskCreateStatic( prvIdleTask, - cIdleName, - ulIdleTaskStackSize, - ( void * ) NULL, /*lint !e961. The cast is not redundant for all compilers. */ - portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */ - pxIdleTaskStackBuffer, - pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ - } - - #if ( configNUM_CORES > 1 ) - else - { - static StaticTask_t xIdleTCBBuffers[ configNUM_CORES - 1 ]; - static StackType_t xIdleTaskStackBuffers[ configNUM_CORES - 1 ][ configMINIMAL_STACK_SIZE ]; - - xIdleTaskHandle[ xCoreID ] = xTaskCreateStatic( prvMinimalIdleTask, - cIdleName, - configMINIMAL_STACK_SIZE, - ( void * ) NULL, /*lint !e961. The cast is not redundant for all compilers. */ - portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */ - xIdleTaskStackBuffers[ xCoreID - 1 ], - &xIdleTCBBuffers[ xCoreID - 1 ] ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ - } - #endif /* if ( configNUM_CORES > 1 ) */ - - if( xIdleTaskHandle[ xCoreID ] != NULL ) - { - xReturn = pdPASS; - } - else - { - xReturn = pdFAIL; - } - } - #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ - { - if( xCoreID == 0 ) - { - /* The Idle task is being created using dynamically allocated RAM. */ - xReturn = xTaskCreate( prvIdleTask, - cIdleName, - configMINIMAL_STACK_SIZE, - ( void * ) NULL, - portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */ - &xIdleTaskHandle[ xCoreID ] ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ - } - - #if ( configNUM_CORES > 1 ) - else - { - xReturn = xTaskCreate( prvMinimalIdleTask, - cIdleName, - configMINIMAL_STACK_SIZE, - ( void * ) NULL, - portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */ - &xIdleTaskHandle[ xCoreID ] ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ - } - #endif - } - #endif /* configSUPPORT_STATIC_ALLOCATION */ } return xReturn; } +/*-----------------------------------------------------------*/ + void vTaskStartScheduler( void ) { BaseType_t xReturn; + traceENTER_vTaskStartScheduler(); + + #if ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) + { + /* Sanity check that the UBaseType_t must have greater than or equal to + * the number of bits as confNUMBER_OF_CORES. */ + configASSERT( ( sizeof( UBaseType_t ) * taskBITS_PER_BYTE ) >= configNUMBER_OF_CORES ); + } + #endif /* #if ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) */ + + xReturn = prvCreateIdleTasks(); + #if ( configUSE_TIMERS == 1 ) + { + if( xReturn == pdPASS ) { xReturn = xTimerCreateTimerTask(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } #endif /* configUSE_TIMERS */ - xReturn = prvCreateIdleTasks(); - if( xReturn == pdPASS ) { /* freertos_tasks_c_additions_init() should only be called if the user * definable macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is * the only macro called by the function. */ #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT - { - freertos_tasks_c_additions_init(); - } + { + freertos_tasks_c_additions_init(); + } #endif /* Interrupts are turned off here, to ensure a tick does not occur @@ -2872,18 +3705,13 @@ void vTaskStartScheduler( void ) * starts to run. */ portDISABLE_INTERRUPTS(); - #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) && ( configNEWLIB_REENTRANT_IS_DYNAMIC == 0 ) ) - { - /* Switch Newlib's _impure_ptr variable to point to the _reent - * structure specific to the task that will run first. - * See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html - * for additional information. - * - * Note: Updating the _impure_ptr is not required when Newlib is compiled with - * __DYNAMIC_REENT__ enabled. The port should provide __getreent() instead. */ - _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); - } - #endif /* ( configUSE_NEWLIB_REENTRANT == 1 ) && ( configNEWLIB_REENTRANT_IS_DYNAMIC == 0 ) */ + #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) + { + /* Switch C-Runtime's TLS Block to point to the TLS + * block specific to the task that will run first. */ + configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock ); + } + #endif xNextTaskUnblockTime = portMAX_DELAY; xSchedulerRunning = pdTRUE; @@ -2901,15 +3729,17 @@ void vTaskStartScheduler( void ) /* Setting up the timer tick is hardware specific and thus in the * portable interface. */ - if( xPortStartScheduler() != pdFALSE ) - { - /* Should not reach here as if the scheduler is running the - * function will not return. */ - } - else - { - /* Should only reach here if a task calls xTaskEndScheduler(). */ - } + + /* The return value for xPortStartScheduler is not required + * hence using a void datatype. */ + ( void ) xPortStartScheduler(); + + /* In most cases, xPortStartScheduler() will not return. If it + * returns pdTRUE then there was not enough heap memory available + * to create either the Idle or the Timer task. If it returned + * pdFALSE, then the application called xTaskEndScheduler(). + * Most ports don't implement xTaskEndScheduler() as there is + * nothing to return to. */ } else { @@ -2920,66 +3750,115 @@ void vTaskStartScheduler( void ) } /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0, - * meaning xIdleTaskHandle is not used anywhere else. */ - ( void ) xIdleTaskHandle; + * meaning xIdleTaskHandles are not used anywhere else. */ + ( void ) xIdleTaskHandles; /* OpenOCD makes use of uxTopUsedPriority for thread debugging. Prevent uxTopUsedPriority * from getting optimized out as it is no longer used by the kernel. */ ( void ) uxTopUsedPriority; + + traceRETURN_vTaskStartScheduler(); } /*-----------------------------------------------------------*/ void vTaskEndScheduler( void ) { + traceENTER_vTaskEndScheduler(); + /* Stop the scheduler interrupts and call the portable scheduler end * routine so the original ISRs can be restored if necessary. The port * layer must ensure interrupts enable bit is left in the correct state. */ portDISABLE_INTERRUPTS(); xSchedulerRunning = pdFALSE; vPortEndScheduler(); + + traceRETURN_vTaskEndScheduler(); } /*----------------------------------------------------------*/ void vTaskSuspendAll( void ) { - UBaseType_t ulState; + traceENTER_vTaskSuspendAll(); - /* This must only be called from within a task */ - portASSERT_IF_IN_ISR(); - - if( xSchedulerRunning != pdFALSE ) + #if ( configNUMBER_OF_CORES == 1 ) { - /* writes to uxSchedulerSuspended must be protected by both the task AND ISR locks. - * We must disable interrupts before we grab the locks in the event that this task is - * interrupted and switches context before incrementing uxSchedulerSuspended. - * It is safe to re-enable interrupts after releasing the ISR lock and incrementing - * uxSchedulerSuspended since that will prevent context switches. */ - ulState = portDISABLE_INTERRUPTS(); + /* A critical section is not required as the variable is of type + * BaseType_t. Please read Richard Barry's reply in the following link to a + * post in the FreeRTOS support forum before reporting this as a bug! - + * https://goo.gl/wu4acr */ - /* portSOFRWARE_BARRIER() is only implemented for emulated/simulated ports that + /* portSOFTWARE_BARRIER() is only implemented for emulated/simulated ports that * do not otherwise exhibit real time behaviour. */ portSOFTWARE_BARRIER(); - portGET_TASK_LOCK(); - portGET_ISR_LOCK(); - /* The scheduler is suspended if uxSchedulerSuspended is non-zero. An increment * is used to allow calls to vTaskSuspendAll() to nest. */ ++uxSchedulerSuspended; - portRELEASE_ISR_LOCK(); - if( ( uxSchedulerSuspended == 1U ) && ( pxCurrentTCB->uxCriticalNesting == 0U ) ) - { - prvCheckForRunStateChange(); - } - - portRESTORE_INTERRUPTS( ulState ); + /* Enforces ordering for ports and optimised compilers that may otherwise place + * the above increment elsewhere. */ + portMEMORY_BARRIER(); } - else + #else /* #if ( configNUMBER_OF_CORES == 1 ) */ { - mtCOVERAGE_TEST_MARKER(); + UBaseType_t ulState; + + /* This must only be called from within a task. */ + portASSERT_IF_IN_ISR(); + + if( xSchedulerRunning != pdFALSE ) + { + /* Writes to uxSchedulerSuspended must be protected by both the task AND ISR locks. + * We must disable interrupts before we grab the locks in the event that this task is + * interrupted and switches context before incrementing uxSchedulerSuspended. + * It is safe to re-enable interrupts after releasing the ISR lock and incrementing + * uxSchedulerSuspended since that will prevent context switches. */ + ulState = portSET_INTERRUPT_MASK(); + + /* portSOFRWARE_BARRIER() is only implemented for emulated/simulated ports that + * do not otherwise exhibit real time behaviour. */ + portSOFTWARE_BARRIER(); + + portGET_TASK_LOCK(); + + /* uxSchedulerSuspended is increased after prvCheckForRunStateChange. The + * purpose is to prevent altering the variable when fromISR APIs are readying + * it. */ + if( uxSchedulerSuspended == 0U ) + { + if( portGET_CRITICAL_NESTING_COUNT() == 0U ) + { + prvCheckForRunStateChange(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + portGET_ISR_LOCK(); + + /* The scheduler is suspended if uxSchedulerSuspended is non-zero. An increment + * is used to allow calls to vTaskSuspendAll() to nest. */ + ++uxSchedulerSuspended; + portRELEASE_ISR_LOCK(); + + portCLEAR_INTERRUPT_MASK( ulState ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ + + traceRETURN_vTaskSuspendAll(); } + /*----------------------------------------------------------*/ #if ( configUSE_TICKLESS_IDLE != 0 ) @@ -2994,33 +3873,33 @@ void vTaskSuspendAll( void ) * task that are in the Ready state, even though the idle task is * running. */ #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) + { + if( uxTopReadyPriority > tskIDLE_PRIORITY ) { - if( uxTopReadyPriority > tskIDLE_PRIORITY ) - { - uxHigherPriorityReadyTasks = pdTRUE; - } + uxHigherPriorityReadyTasks = pdTRUE; } + } #else - { - const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01; + { + const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01; - /* When port optimised task selection is used the uxTopReadyPriority - * variable is used as a bit map. If bits other than the least - * significant bit are set then there are tasks that have a priority - * above the idle priority that are in the Ready state. This takes - * care of the case where the co-operative scheduler is in use. */ - if( uxTopReadyPriority > uxLeastSignificantBit ) - { - uxHigherPriorityReadyTasks = pdTRUE; - } + /* When port optimised task selection is used the uxTopReadyPriority + * variable is used as a bit map. If bits other than the least + * significant bit are set then there are tasks that have a priority + * above the idle priority that are in the Ready state. This takes + * care of the case where the co-operative scheduler is in use. */ + if( uxTopReadyPriority > uxLeastSignificantBit ) + { + uxHigherPriorityReadyTasks = pdTRUE; } + } #endif /* if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) */ if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY ) { xReturn = 0; } - else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 ) + else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1U ) { /* There are other idle priority tasks in the ready state. If * time slicing is used then the very next tick interrupt must be @@ -3036,7 +3915,8 @@ void vTaskSuspendAll( void ) } else { - xReturn = xNextTaskUnblockTime - xTickCount; + xReturn = xNextTaskUnblockTime; + xReturn -= xTickCount; } return xReturn; @@ -3050,7 +3930,11 @@ BaseType_t xTaskResumeAll( void ) TCB_t * pxTCB = NULL; BaseType_t xAlreadyYielded = pdFALSE; - if( xSchedulerRunning != pdFALSE ) + traceENTER_xTaskResumeAll(); + + #if ( configNUMBER_OF_CORES > 1 ) + if( xSchedulerRunning != pdFALSE ) + #endif { /* It is possible that an ISR caused a task to be removed from an event * list while the scheduler was suspended. If this was the case then the @@ -3060,17 +3944,16 @@ BaseType_t xTaskResumeAll( void ) taskENTER_CRITICAL(); { BaseType_t xCoreID; - - xCoreID = portGET_CORE_ID(); + xCoreID = ( BaseType_t ) portGET_CORE_ID(); /* If uxSchedulerSuspended is zero then this function does not match a * previous call to vTaskSuspendAll(). */ - configASSERT( uxSchedulerSuspended ); + configASSERT( uxSchedulerSuspended != 0U ); --uxSchedulerSuspended; portRELEASE_TASK_LOCK(); - if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + if( uxSchedulerSuspended == ( UBaseType_t ) 0U ) { if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U ) { @@ -3078,14 +3961,35 @@ BaseType_t xTaskResumeAll( void ) * appropriate ready list. */ while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE ) { - pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ - ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); - ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + /* MISRA Ref 11.5.3 [Void pointer assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); + listREMOVE_ITEM( &( pxTCB->xEventListItem ) ); + portMEMORY_BARRIER(); + listREMOVE_ITEM( &( pxTCB->xStateListItem ) ); prvAddTaskToReadyList( pxTCB ); - /* All appropriate tasks yield at the moment a task is added to xPendingReadyList. - * If the current core yielded then vTaskSwitchContext() has already been called - * which sets xYieldPendings for the current core to pdTRUE. */ + #if ( configNUMBER_OF_CORES == 1 ) + { + /* If the moved task has a priority higher than the current + * task then a yield must be performed. */ + if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) + { + xYieldPendings[ xCoreID ] = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #else /* #if ( configNUMBER_OF_CORES == 1 ) */ + { + /* All appropriate tasks yield at the moment a task is added to xPendingReadyList. + * If the current core yielded then vTaskSwitchContext() has already been called + * which sets xYieldPendings for the current core to pdTRUE. */ + } + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ } if( pxTCB != NULL ) @@ -3101,13 +4005,13 @@ BaseType_t xTaskResumeAll( void ) /* If any ticks occurred while the scheduler was suspended then * they should be processed now. This ensures the tick count does - * not slip, and that any delayed tasks are resumed at the correct + * not slip, and that any delayed tasks are resumed at the correct * time. * * It should be safe to call xTaskIncrementTick here from any core * since we are in a critical section and xTaskIncrementTick itself * protects itself within a critical section. Suspending the scheduler - * from any core causes xTaskIncrementTick to increment uxPendedCounts.*/ + * from any core causes xTaskIncrementTick to increment uxPendedCounts. */ { TickType_t xPendedCounts = xPendedTicks; /* Non-volatile copy. */ @@ -3117,7 +4021,7 @@ BaseType_t xTaskResumeAll( void ) { if( xTaskIncrementTick() != pdFALSE ) { - /* other cores are interrupted from + /* Other cores are interrupted from * within xTaskIncrementTick(). */ xYieldPendings[ xCoreID ] = pdTRUE; } @@ -3139,10 +4043,21 @@ BaseType_t xTaskResumeAll( void ) if( xYieldPendings[ xCoreID ] != pdFALSE ) { - /* If xYieldPendings is true then taskEXIT_CRITICAL() - * will yield, so make sure we return true to let the - * caller know a yield has already happened. */ - xAlreadyYielded = pdTRUE; + #if ( configUSE_PREEMPTION != 0 ) + { + xAlreadyYielded = pdTRUE; + } + #endif /* #if ( configUSE_PREEMPTION != 0 ) */ + + #if ( configNUMBER_OF_CORES == 1 ) + { + taskYIELD_TASK_CORE_IF_USING_PREEMPTION( pxCurrentTCB ); + } + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ + } + else + { + mtCOVERAGE_TEST_MARKER(); } } } @@ -3153,10 +4068,8 @@ BaseType_t xTaskResumeAll( void ) } taskEXIT_CRITICAL(); } - else - { - mtCOVERAGE_TEST_MARKER(); - } + + traceRETURN_xTaskResumeAll( xAlreadyYielded ); return xAlreadyYielded; } @@ -3166,6 +4079,8 @@ TickType_t xTaskGetTickCount( void ) { TickType_t xTicks; + traceENTER_xTaskGetTickCount(); + /* Critical section required if running on a 16 bit processor. */ portTICK_TYPE_ENTER_CRITICAL(); { @@ -3173,6 +4088,8 @@ TickType_t xTaskGetTickCount( void ) } portTICK_TYPE_EXIT_CRITICAL(); + traceRETURN_xTaskGetTickCount( xTicks ); + return xTicks; } /*-----------------------------------------------------------*/ @@ -3182,6 +4099,8 @@ TickType_t xTaskGetTickCountFromISR( void ) TickType_t xReturn; UBaseType_t uxSavedInterruptStatus; + traceENTER_xTaskGetTickCountFromISR(); + /* RTOS ports that support interrupt nesting have the concept of a maximum * system call (or maximum API call) interrupt priority. Interrupts that are * above the maximum system call priority are kept permanently enabled, even @@ -3204,106 +4123,196 @@ TickType_t xTaskGetTickCountFromISR( void ) } portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + traceRETURN_xTaskGetTickCountFromISR( xReturn ); + return xReturn; } /*-----------------------------------------------------------*/ UBaseType_t uxTaskGetNumberOfTasks( void ) { + traceENTER_uxTaskGetNumberOfTasks(); + /* A critical section is not required because the variables are of type * BaseType_t. */ + traceRETURN_uxTaskGetNumberOfTasks( uxCurrentNumberOfTasks ); + return uxCurrentNumberOfTasks; } /*-----------------------------------------------------------*/ -char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +char * pcTaskGetName( TaskHandle_t xTaskToQuery ) { TCB_t * pxTCB; + traceENTER_pcTaskGetName( xTaskToQuery ); + /* If null is passed in here then the name of the calling task is being * queried. */ pxTCB = prvGetTCBFromHandle( xTaskToQuery ); configASSERT( pxTCB ); + + traceRETURN_pcTaskGetName( &( pxTCB->pcTaskName[ 0 ] ) ); + return &( pxTCB->pcTaskName[ 0 ] ); } /*-----------------------------------------------------------*/ #if ( INCLUDE_xTaskGetHandle == 1 ) - static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList, - const char pcNameToQuery[] ) - { - TCB_t * pxNextTCB, * pxFirstTCB, * pxReturn = NULL; - UBaseType_t x; - char cNextChar; - BaseType_t xBreakLoop; - - /* This function is called with the scheduler suspended. */ - - if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) + #if ( configNUMBER_OF_CORES == 1 ) + static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList, + const char pcNameToQuery[] ) { - listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ + TCB_t * pxNextTCB; + TCB_t * pxFirstTCB; + TCB_t * pxReturn = NULL; + UBaseType_t x; + char cNextChar; + BaseType_t xBreakLoop; - do + /* This function is called with the scheduler suspended. */ + + if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) { - listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ + /* MISRA Ref 11.5.3 [Void pointer assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); - /* Check each character in the name looking for a match or - * mismatch. */ - xBreakLoop = pdFALSE; - - for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ) + do { - cNextChar = pxNextTCB->pcTaskName[ x ]; + /* MISRA Ref 11.5.3 [Void pointer assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); - if( cNextChar != pcNameToQuery[ x ] ) + /* Check each character in the name looking for a match or + * mismatch. */ + xBreakLoop = pdFALSE; + + for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ) { - /* Characters didn't match. */ - xBreakLoop = pdTRUE; - } - else if( cNextChar == ( char ) 0x00 ) - { - /* Both strings terminated, a match must have been - * found. */ - pxReturn = pxNextTCB; - xBreakLoop = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); + cNextChar = pxNextTCB->pcTaskName[ x ]; + + if( cNextChar != pcNameToQuery[ x ] ) + { + /* Characters didn't match. */ + xBreakLoop = pdTRUE; + } + else if( cNextChar == ( char ) 0x00 ) + { + /* Both strings terminated, a match must have been + * found. */ + pxReturn = pxNextTCB; + xBreakLoop = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( xBreakLoop != pdFALSE ) + { + break; + } } - if( xBreakLoop != pdFALSE ) + if( pxReturn != NULL ) { + /* The handle has been found. */ + break; + } + } while( pxNextTCB != pxFirstTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return pxReturn; + } + #else /* if ( configNUMBER_OF_CORES == 1 ) */ + static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList, + const char pcNameToQuery[] ) + { + TCB_t * pxReturn = NULL; + UBaseType_t x; + char cNextChar; + BaseType_t xBreakLoop; + const ListItem_t * pxEndMarker = listGET_END_MARKER( pxList ); + ListItem_t * pxIterator; + + /* This function is called with the scheduler suspended. */ + + if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) + { + for( pxIterator = listGET_HEAD_ENTRY( pxList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) ) + { + /* MISRA Ref 11.5.3 [Void pointer assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + TCB_t * pxTCB = listGET_LIST_ITEM_OWNER( pxIterator ); + + /* Check each character in the name looking for a match or + * mismatch. */ + xBreakLoop = pdFALSE; + + for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ) + { + cNextChar = pxTCB->pcTaskName[ x ]; + + if( cNextChar != pcNameToQuery[ x ] ) + { + /* Characters didn't match. */ + xBreakLoop = pdTRUE; + } + else if( cNextChar == ( char ) 0x00 ) + { + /* Both strings terminated, a match must have been + * found. */ + pxReturn = pxTCB; + xBreakLoop = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( xBreakLoop != pdFALSE ) + { + break; + } + } + + if( pxReturn != NULL ) + { + /* The handle has been found. */ break; } } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - if( pxReturn != NULL ) - { - /* The handle has been found. */ - break; - } - } while( pxNextTCB != pxFirstTCB ); + return pxReturn; } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - return pxReturn; - } + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ #endif /* INCLUDE_xTaskGetHandle */ /*-----------------------------------------------------------*/ #if ( INCLUDE_xTaskGetHandle == 1 ) - TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) { UBaseType_t uxQueue = configMAX_PRIORITIES; TCB_t * pxTCB; + traceENTER_xTaskGetHandle( pcNameToQuery ); + /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */ configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN ); @@ -3320,7 +4329,7 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char /* Found the handle. */ break; } - } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /* Search the delayed lists. */ if( pxTCB == NULL ) @@ -3334,27 +4343,29 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char } #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( pxTCB == NULL ) { - if( pxTCB == NULL ) - { - /* Search the suspended list. */ - pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery ); - } + /* Search the suspended list. */ + pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery ); } + } #endif #if ( INCLUDE_vTaskDelete == 1 ) + { + if( pxTCB == NULL ) { - if( pxTCB == NULL ) - { - /* Search the deleted list. */ - pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery ); - } + /* Search the deleted list. */ + pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery ); } + } #endif } ( void ) xTaskResumeAll(); + traceRETURN_xTaskGetHandle( pxTCB ); + return pxTCB; } @@ -3370,6 +4381,8 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char BaseType_t xReturn; TCB_t * pxTCB; + traceENTER_xTaskGetStaticBuffers( xTask, ppuxStackBuffer, ppxTaskBuffer ); + configASSERT( ppuxStackBuffer != NULL ); configASSERT( ppxTaskBuffer != NULL ); @@ -3380,6 +4393,9 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB ) { *ppuxStackBuffer = pxTCB->pxStack; + /* MISRA Ref 11.3.1 [Misaligned access] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */ + /* coverity[misra_c_2012_rule_11_3_violation] */ *ppxTaskBuffer = ( StaticTask_t * ) pxTCB; xReturn = pdTRUE; } @@ -3402,6 +4418,8 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char } #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 */ + traceRETURN_xTaskGetStaticBuffers( xReturn ); + return xReturn; } @@ -3412,10 +4430,12 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, - uint32_t * const pulTotalRunTime ) + configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) { UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES; + traceENTER_uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, pulTotalRunTime ); + vTaskSuspendAll(); { /* Is there a space in the array for each task in the system? */ @@ -3426,48 +4446,48 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char do { uxQueue--; - uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady ); - } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady ) ); + } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /* Fill in an TaskStatus_t structure with information on each * task in the Blocked state. */ - uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked ); - uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked ); + uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked ) ); + uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked ) ); #if ( INCLUDE_vTaskDelete == 1 ) - { - /* Fill in an TaskStatus_t structure with information on - * each task that has been deleted but not yet cleaned up. */ - uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted ); - } + { + /* Fill in an TaskStatus_t structure with information on + * each task that has been deleted but not yet cleaned up. */ + uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted ) ); + } #endif #if ( INCLUDE_vTaskSuspend == 1 ) - { - /* Fill in an TaskStatus_t structure with information on - * each task in the Suspended state. */ - uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended ); - } + { + /* Fill in an TaskStatus_t structure with information on + * each task in the Suspended state. */ + uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended ) ); + } #endif #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + if( pulTotalRunTime != NULL ) { - if( pulTotalRunTime != NULL ) - { - #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE - portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) ); - #else - *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); - #endif - } + #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE + portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) ); + #else + *pulTotalRunTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE(); + #endif } + } #else /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */ + { + if( pulTotalRunTime != NULL ) { - if( pulTotalRunTime != NULL ) - { - *pulTotalRunTime = 0; - } + *pulTotalRunTime = 0; } + } #endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */ } else @@ -3477,6 +4497,8 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char } ( void ) xTaskResumeAll(); + traceRETURN_uxTaskGetSystemState( uxTask ); + return uxTask; } @@ -3485,12 +4507,35 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) - TaskHandle_t * xTaskGetIdleTaskHandle( void ) + #if ( configNUMBER_OF_CORES == 1 ) + TaskHandle_t xTaskGetIdleTaskHandle( void ) + { + traceENTER_xTaskGetIdleTaskHandle(); + + /* If xTaskGetIdleTaskHandle() is called before the scheduler has been + * started, then xIdleTaskHandles will be NULL. */ + configASSERT( ( xIdleTaskHandles[ 0 ] != NULL ) ); + + traceRETURN_xTaskGetIdleTaskHandle( xIdleTaskHandles[ 0 ] ); + + return xIdleTaskHandles[ 0 ]; + } + #endif /* if ( configNUMBER_OF_CORES == 1 ) */ + + TaskHandle_t xTaskGetIdleTaskHandleForCore( BaseType_t xCoreID ) { + traceENTER_xTaskGetIdleTaskHandleForCore( xCoreID ); + + /* Ensure the core ID is valid. */ + configASSERT( taskVALID_CORE_ID( xCoreID ) == pdTRUE ); + /* If xTaskGetIdleTaskHandle() is called before the scheduler has been - * started, then xIdleTaskHandle will be NULL. */ - configASSERT( ( xIdleTaskHandle != NULL ) ); - return &( xIdleTaskHandle[ 0 ] ); + * started, then xIdleTaskHandles will be NULL. */ + configASSERT( ( xIdleTaskHandles[ xCoreID ] != NULL ) ); + + traceRETURN_xTaskGetIdleTaskHandleForCore( xIdleTaskHandles[ xCoreID ] ); + + return xIdleTaskHandles[ xCoreID ]; } #endif /* INCLUDE_xTaskGetIdleTaskHandle */ @@ -3502,14 +4547,43 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char * 1. */ #if ( configUSE_TICKLESS_IDLE != 0 ) - void vTaskStepTick( const TickType_t xTicksToJump ) + void vTaskStepTick( TickType_t xTicksToJump ) { + TickType_t xUpdatedTickCount; + + traceENTER_vTaskStepTick( xTicksToJump ); + /* Correct the tick count value after a period during which the tick * was suppressed. Note this does *not* call the tick hook function for * each stepped tick. */ - configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime ); + xUpdatedTickCount = xTickCount + xTicksToJump; + configASSERT( xUpdatedTickCount <= xNextTaskUnblockTime ); + + if( xUpdatedTickCount == xNextTaskUnblockTime ) + { + /* Arrange for xTickCount to reach xNextTaskUnblockTime in + * xTaskIncrementTick() when the scheduler resumes. This ensures + * that any delayed tasks are resumed at the correct time. */ + configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U ); + configASSERT( xTicksToJump != ( TickType_t ) 0 ); + + /* Prevent the tick interrupt modifying xPendedTicks simultaneously. */ + taskENTER_CRITICAL(); + { + xPendedTicks++; + } + taskEXIT_CRITICAL(); + xTicksToJump--; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + xTickCount += xTicksToJump; + traceINCREASE_TICK_COUNT( xTicksToJump ); + traceRETURN_vTaskStepTick(); } #endif /* configUSE_TICKLESS_IDLE */ @@ -3519,16 +4593,26 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) { BaseType_t xYieldOccurred; + traceENTER_xTaskCatchUpTicks( xTicksToCatchUp ); + /* Must not be called with the scheduler suspended as the implementation * relies on xPendedTicks being wound down to 0 in xTaskResumeAll(). */ - configASSERT( uxSchedulerSuspended == 0 ); + configASSERT( uxSchedulerSuspended == ( UBaseType_t ) 0U ); /* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occurring when * the scheduler is suspended so the ticks are executed in xTaskResumeAll(). */ vTaskSuspendAll(); - xPendedTicks += xTicksToCatchUp; + + /* Prevent the tick interrupt modifying xPendedTicks simultaneously. */ + taskENTER_CRITICAL(); + { + xPendedTicks += xTicksToCatchUp; + } + taskEXIT_CRITICAL(); xYieldOccurred = xTaskResumeAll(); + traceRETURN_xTaskCatchUpTicks( xYieldOccurred ); + return xYieldOccurred; } /*----------------------------------------------------------*/ @@ -3540,6 +4624,8 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) TCB_t * pxTCB = xTask; BaseType_t xReturn; + traceENTER_xTaskAbortDelay( xTask ); + configASSERT( pxTCB ); vTaskSuspendAll(); @@ -3583,14 +4669,34 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) /* A task being unblocked cannot cause an immediate context * switch if preemption is turned off. */ #if ( configUSE_PREEMPTION == 1 ) + { + #if ( configNUMBER_OF_CORES == 1 ) + { + /* Preemption is on, but a context switch should only be + * performed if the unblocked task has a priority that is + * higher than the currently executing task. */ + if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) + { + /* Pend the yield to be performed when the scheduler + * is unsuspended. */ + xYieldPendings[ 0 ] = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #else /* #if ( configNUMBER_OF_CORES == 1 ) */ { taskENTER_CRITICAL(); { - prvYieldForTask( pxTCB, pdFALSE ); + prvYieldForTask( pxTCB ); } taskEXIT_CRITICAL(); } - #endif /* configUSE_PREEMPTION */ + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ + } + #endif /* #if ( configUSE_PREEMPTION == 1 ) */ } else { @@ -3599,6 +4705,8 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) } ( void ) xTaskResumeAll(); + traceRETURN_xTaskAbortDelay( xReturn ); + return xReturn; } @@ -3611,213 +4719,249 @@ BaseType_t xTaskIncrementTick( void ) TickType_t xItemValue; BaseType_t xSwitchRequired = pdFALSE; - #if ( configUSE_PREEMPTION == 1 ) - UBaseType_t x; - BaseType_t xCoreYieldList[ configNUM_CORES ] = { pdFALSE }; - #endif /* configUSE_PREEMPTION */ + #if ( configUSE_PREEMPTION == 1 ) && ( configNUMBER_OF_CORES > 1 ) + BaseType_t xYieldRequiredForCore[ configNUMBER_OF_CORES ] = { pdFALSE }; + #endif /* #if ( configUSE_PREEMPTION == 1 ) && ( configNUMBER_OF_CORES > 1 ) */ - taskENTER_CRITICAL(); + traceENTER_xTaskIncrementTick(); + + /* Called by the portable layer each time a tick interrupt occurs. + * Increments the tick then checks to see if the new tick value will cause any + * tasks to be unblocked. */ + traceTASK_INCREMENT_TICK( xTickCount ); + + /* Tick increment should occur on every kernel timer event. Core 0 has the + * responsibility to increment the tick, or increment the pended ticks if the + * scheduler is suspended. If pended ticks is greater than zero, the core that + * calls xTaskResumeAll has the responsibility to increment the tick. */ + if( uxSchedulerSuspended == ( UBaseType_t ) 0U ) { - /* Called by the portable layer each time a tick interrupt occurs. - * Increments the tick then checks to see if the new tick value will cause any - * tasks to be unblocked. */ - traceTASK_INCREMENT_TICK( xTickCount ); + /* Minor optimisation. The tick count cannot change in this + * block. */ + const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; - /* Tick increment should occur on every kernel timer event. Core 0 has the - * responsibility to increment the tick, or increment the pended ticks if the - * scheduler is suspended. If pended ticks is greater than zero, the core that - * calls xTaskResumeAll has the responsibility to increment the tick. */ - if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + /* Increment the RTOS tick, switching the delayed and overflowed + * delayed lists if it wraps to 0. */ + xTickCount = xConstTickCount; + + if( xConstTickCount == ( TickType_t ) 0U ) { - /* Minor optimisation. The tick count cannot change in this - * block. */ - const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; + taskSWITCH_DELAYED_LISTS(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* Increment the RTOS tick, switching the delayed and overflowed - * delayed lists if it wraps to 0. */ - xTickCount = xConstTickCount; - - if( xConstTickCount == ( TickType_t ) 0U ) /*lint !e774 'if' does not always evaluate to false as it is looking for an overflow. */ + /* See if this tick has made a timeout expire. Tasks are stored in + * the queue in the order of their wake time - meaning once one task + * has been found whose block time has not expired there is no need to + * look any further down the list. */ + if( xConstTickCount >= xNextTaskUnblockTime ) + { + for( ; ; ) { - taskSWITCH_DELAYED_LISTS(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - /* See if this tick has made a timeout expire. Tasks are stored in - * the queue in the order of their wake time - meaning once one task - * has been found whose block time has not expired there is no need to - * look any further down the list. */ - if( xConstTickCount >= xNextTaskUnblockTime ) - { - for( ; ; ) + if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) { - if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) + /* The delayed list is empty. Set xNextTaskUnblockTime + * to the maximum possible value so it is extremely + * unlikely that the + * if( xTickCount >= xNextTaskUnblockTime ) test will pass + * next time through. */ + xNextTaskUnblockTime = portMAX_DELAY; + break; + } + else + { + /* The delayed list is not empty, get the value of the + * item at the head of the delayed list. This is the time + * at which the task at the head of the delayed list must + * be removed from the Blocked state. */ + /* MISRA Ref 11.5.3 [Void pointer assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + pxTCB = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); + xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) ); + + if( xConstTickCount < xItemValue ) { - /* The delayed list is empty. Set xNextTaskUnblockTime - * to the maximum possible value so it is extremely - * unlikely that the - * if( xTickCount >= xNextTaskUnblockTime ) test will pass - * next time through. */ - xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + /* It is not time to unblock this item yet, but the + * item value is the time at which the task at the head + * of the blocked list must be removed from the Blocked + * state - so record the item value in + * xNextTaskUnblockTime. */ + xNextTaskUnblockTime = xItemValue; break; } else - { - /* The delayed list is not empty, get the value of the - * item at the head of the delayed list. This is the time - * at which the task at the head of the delayed list must - * be removed from the Blocked state. */ - pxTCB = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ - xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) ); - - if( xConstTickCount < xItemValue ) - { - /* It is not time to unblock this item yet, but the - * item value is the time at which the task at the head - * of the blocked list must be removed from the Blocked - * state - so record the item value in - * xNextTaskUnblockTime. */ - xNextTaskUnblockTime = xItemValue; - break; /*lint !e9011 Code structure here is deemed easier to understand with multiple breaks. */ - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - /* It is time to remove the item from the Blocked state. */ - ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); - - /* Is the task waiting on an event also? If so remove - * it from the event list. */ - if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) - { - ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - /* Place the unblocked task into the appropriate ready - * list. */ - prvAddTaskToReadyList( pxTCB ); - - /* A task being unblocked cannot cause an immediate - * context switch if preemption is turned off. */ - #if ( configUSE_PREEMPTION == 1 ) - { - prvYieldForTask( pxTCB, pdTRUE ); - } - #endif /* configUSE_PREEMPTION */ - } - } - } - - /* Tasks of equal priority to the currently running task will share - * processing time (time slice) if preemption is on, and the application - * writer has not explicitly turned time slicing off. */ - #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) - { - /* TODO: If there are fewer "non-IDLE" READY tasks than cores, do not - * force a context switch that would just shuffle tasks around cores */ - /* TODO: There are certainly better ways of doing this that would reduce - * the number of interrupts and also potentially help prevent tasks from - * moving between cores as often. This, however, works for now. */ - for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configNUM_CORES; x++ ) - { - if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCBs[ x ]->uxPriority ] ) ) > ( UBaseType_t ) 1 ) - { - xCoreYieldList[ x ] = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } - #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */ - - #if ( configUSE_TICK_HOOK == 1 ) - { - /* Guard against the tick hook being called when the pended tick - * count is being unwound (when the scheduler is being unlocked). */ - if( xPendedTicks == ( TickType_t ) 0 ) - { - vApplicationTickHook(); - } - else { mtCOVERAGE_TEST_MARKER(); } - } - #endif /* configUSE_TICK_HOOK */ - #if ( configUSE_PREEMPTION == 1 ) - { - for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configNUM_CORES; x++ ) + /* It is time to remove the item from the Blocked state. */ + listREMOVE_ITEM( &( pxTCB->xStateListItem ) ); + + /* Is the task waiting on an event also? If so remove + * it from the event list. */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) { - if( xYieldPendings[ x ] != pdFALSE ) - { - xCoreYieldList[ x ] = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + listREMOVE_ITEM( &( pxTCB->xEventListItem ) ); } - } - #endif /* configUSE_PREEMPTION */ - - #if ( configUSE_PREEMPTION == 1 ) - { - BaseType_t xCoreID; - - xCoreID = portGET_CORE_ID(); - - for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configNUM_CORES; x++ ) + else { - #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - if( pxCurrentTCBs[ x ]->xPreemptionDisable == pdFALSE ) - #endif + mtCOVERAGE_TEST_MARKER(); + } + + /* Place the unblocked task into the appropriate ready + * list. */ + prvAddTaskToReadyList( pxTCB ); + + /* A task being unblocked cannot cause an immediate + * context switch if preemption is turned off. */ + #if ( configUSE_PREEMPTION == 1 ) + { + #if ( configNUMBER_OF_CORES == 1 ) { - if( xCoreYieldList[ x ] != pdFALSE ) + /* Preemption is on, but a context switch should + * only be performed if the unblocked task's + * priority is higher than the currently executing + * task. + * The case of equal priority tasks sharing + * processing time (which happens when both + * preemption and time slicing are on) is + * handled below.*/ + if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) { - if( x == xCoreID ) - { - xSwitchRequired = pdTRUE; - } - else - { - prvYieldCore( x ); - } + xSwitchRequired = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } + #else /* #if( configNUMBER_OF_CORES == 1 ) */ + { + prvYieldForTask( pxTCB ); + } + #endif /* #if( configNUMBER_OF_CORES == 1 ) */ + } + #endif /* #if ( configUSE_PREEMPTION == 1 ) */ + } + } + } + + /* Tasks of equal priority to the currently running task will share + * processing time (time slice) if preemption is on, and the application + * writer has not explicitly turned time slicing off. */ + #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) + { + #if ( configNUMBER_OF_CORES == 1 ) + { + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > 1U ) + { + xSwitchRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #else /* #if ( configNUMBER_OF_CORES == 1 ) */ + { + BaseType_t xCoreID; + + for( xCoreID = 0; xCoreID < ( ( BaseType_t ) configNUMBER_OF_CORES ); xCoreID++ ) + { + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCBs[ xCoreID ]->uxPriority ] ) ) > 1U ) + { + xYieldRequiredForCore[ xCoreID ] = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); } } - #endif /* configUSE_PREEMPTION */ + } + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ } - else - { - ++xPendedTicks; + #endif /* #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */ - /* The tick hook gets called at regular intervals, even if the - * scheduler is locked. */ - #if ( configUSE_TICK_HOOK == 1 ) - { - vApplicationTickHook(); - } - #endif + #if ( configUSE_TICK_HOOK == 1 ) + { + /* Guard against the tick hook being called when the pended tick + * count is being unwound (when the scheduler is being unlocked). */ + if( xPendedTicks == ( TickType_t ) 0 ) + { + vApplicationTickHook(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } + #endif /* configUSE_TICK_HOOK */ + + #if ( configUSE_PREEMPTION == 1 ) + { + #if ( configNUMBER_OF_CORES == 1 ) + { + /* For single core the core ID is always 0. */ + if( xYieldPendings[ 0 ] != pdFALSE ) + { + xSwitchRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #else /* #if ( configNUMBER_OF_CORES == 1 ) */ + { + BaseType_t xCoreID, xCurrentCoreID; + xCurrentCoreID = ( BaseType_t ) portGET_CORE_ID(); + + for( xCoreID = 0; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES; xCoreID++ ) + { + #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) + if( pxCurrentTCBs[ xCoreID ]->xPreemptionDisable == pdFALSE ) + #endif + { + if( ( xYieldRequiredForCore[ xCoreID ] != pdFALSE ) || ( xYieldPendings[ xCoreID ] != pdFALSE ) ) + { + if( xCoreID == xCurrentCoreID ) + { + xSwitchRequired = pdTRUE; + } + else + { + prvYieldCore( xCoreID ); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + } + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ + } + #endif /* #if ( configUSE_PREEMPTION == 1 ) */ } - taskEXIT_CRITICAL(); + else + { + ++xPendedTicks; + + /* The tick hook gets called at regular intervals, even if the + * scheduler is locked. */ + #if ( configUSE_TICK_HOOK == 1 ) + { + vApplicationTickHook(); + } + #endif + } + + traceRETURN_xTaskIncrementTick( xSwitchRequired ); return xSwitchRequired; } @@ -3830,6 +4974,8 @@ BaseType_t xTaskIncrementTick( void ) { TCB_t * xTCB; + traceENTER_vTaskSetApplicationTaskTag( xTask, pxHookFunction ); + /* If xTask is NULL then it is the task hook of the calling task that is * getting set. */ if( xTask == NULL ) @@ -3848,6 +4994,8 @@ BaseType_t xTaskIncrementTick( void ) xTCB->pxTaskTag = pxHookFunction; } taskEXIT_CRITICAL(); + + traceRETURN_vTaskSetApplicationTaskTag(); } #endif /* configUSE_APPLICATION_TASK_TAG */ @@ -3860,6 +5008,8 @@ BaseType_t xTaskIncrementTick( void ) TCB_t * pxTCB; TaskHookFunction_t xReturn; + traceENTER_xTaskGetApplicationTaskTag( xTask ); + /* If xTask is NULL then set the calling task's hook. */ pxTCB = prvGetTCBFromHandle( xTask ); @@ -3871,6 +5021,8 @@ BaseType_t xTaskIncrementTick( void ) } taskEXIT_CRITICAL(); + traceRETURN_xTaskGetApplicationTaskTag( xReturn ); + return xReturn; } @@ -3885,16 +5037,20 @@ BaseType_t xTaskIncrementTick( void ) TaskHookFunction_t xReturn; UBaseType_t uxSavedInterruptStatus; + traceENTER_xTaskGetApplicationTaskTagFromISR( xTask ); + /* If xTask is NULL then set the calling task's hook. */ pxTCB = prvGetTCBFromHandle( xTask ); /* Save the hook function in the TCB. A critical section is required as * the value can be accessed from an interrupt. */ - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); { xReturn = pxTCB->pxTaskTag; } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); + + traceRETURN_xTaskGetApplicationTaskTagFromISR( xReturn ); return xReturn; } @@ -3910,6 +5066,8 @@ BaseType_t xTaskIncrementTick( void ) TCB_t * xTCB; BaseType_t xReturn; + traceENTER_xTaskCallApplicationTaskHook( xTask, pvParameter ); + /* If xTask is NULL then we are calling our own task hook. */ if( xTask == NULL ) { @@ -3929,46 +5087,137 @@ BaseType_t xTaskIncrementTick( void ) xReturn = pdFAIL; } + traceRETURN_xTaskCallApplicationTaskHook( xReturn ); + return xReturn; } #endif /* configUSE_APPLICATION_TASK_TAG */ /*-----------------------------------------------------------*/ -void vTaskSwitchContext( BaseType_t xCoreID ) -{ - /* Acquire both locks: - * - The ISR lock protects the ready list from simultaneous access by - * both other ISRs and tasks. - * - We also take the task lock to pause here in case another core has - * suspended the scheduler. We don't want to simply set xYieldPending - * and move on if another core suspended the scheduler. We should only - * do that if the current core has suspended the scheduler. */ - - portGET_TASK_LOCK(); /* Must always acquire the task lock first */ - portGET_ISR_LOCK(); +#if ( configNUMBER_OF_CORES == 1 ) + void vTaskSwitchContext( void ) { - /* vTaskSwitchContext() must never be called from within a critical section. - * This is not necessarily true for vanilla FreeRTOS, but it is for this SMP port. */ - configASSERT( pxCurrentTCB->uxCriticalNesting == 0 ); + traceENTER_vTaskSwitchContext(); - if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE ) + if( uxSchedulerSuspended != ( UBaseType_t ) 0U ) { /* The scheduler is currently suspended - do not allow a context * switch. */ - xYieldPendings[ xCoreID ] = pdTRUE; + xYieldPendings[ 0 ] = pdTRUE; } else { - xYieldPendings[ xCoreID ] = pdFALSE; + xYieldPendings[ 0 ] = pdFALSE; traceTASK_SWITCHED_OUT(); #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE + portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime[ 0 ] ); + #else + ulTotalRunTime[ 0 ] = portGET_RUN_TIME_COUNTER_VALUE(); + #endif + + /* Add the amount of time the task has been running to the + * accumulated time so far. The time the task started running was + * stored in ulTaskSwitchedInTime. Note that there is no overflow + * protection here so count values are only valid until the timer + * overflows. The guard against negative values is to protect + * against suspect run time stat counter implementations - which + * are provided by the application, not the kernel. */ + if( ulTotalRunTime[ 0 ] > ulTaskSwitchedInTime[ 0 ] ) + { + pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime[ 0 ] - ulTaskSwitchedInTime[ 0 ] ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + ulTaskSwitchedInTime[ 0 ] = ulTotalRunTime[ 0 ]; + } + #endif /* configGENERATE_RUN_TIME_STATS */ + + /* Check for stack overflow, if configured. */ + taskCHECK_FOR_STACK_OVERFLOW(); + + /* Before the currently running task is switched out, save its errno. */ + #if ( configUSE_POSIX_ERRNO == 1 ) + { + pxCurrentTCB->iTaskErrno = FreeRTOS_errno; + } + #endif + + /* Select a new task to run using either the generic C or port + * optimised asm code. */ + /* MISRA Ref 11.5.3 [Void pointer assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + taskSELECT_HIGHEST_PRIORITY_TASK(); + traceTASK_SWITCHED_IN(); + + /* Macro to inject port specific behaviour immediately after + * switching tasks, such as setting an end of stack watchpoint + * or reconfiguring the MPU. */ + portTASK_SWITCH_HOOK( pxCurrentTCB ); + + /* After the new task is switched in, update the global errno. */ + #if ( configUSE_POSIX_ERRNO == 1 ) + { + FreeRTOS_errno = pxCurrentTCB->iTaskErrno; + } + #endif + + #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) + { + /* Switch C-Runtime's TLS Block to point to the TLS + * Block specific to this task. */ + configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock ); + } + #endif + } + + traceRETURN_vTaskSwitchContext(); + } +#else /* if ( configNUMBER_OF_CORES == 1 ) */ + void vTaskSwitchContext( BaseType_t xCoreID ) + { + traceENTER_vTaskSwitchContext(); + + /* Acquire both locks: + * - The ISR lock protects the ready list from simultaneous access by + * both other ISRs and tasks. + * - We also take the task lock to pause here in case another core has + * suspended the scheduler. We don't want to simply set xYieldPending + * and move on if another core suspended the scheduler. We should only + * do that if the current core has suspended the scheduler. */ + + portGET_TASK_LOCK(); /* Must always acquire the task lock first. */ + portGET_ISR_LOCK(); + { + /* vTaskSwitchContext() must never be called from within a critical section. + * This is not necessarily true for single core FreeRTOS, but it is for this + * SMP port. */ + configASSERT( portGET_CRITICAL_NESTING_COUNT() == 0 ); + + if( uxSchedulerSuspended != ( UBaseType_t ) 0U ) + { + /* The scheduler is currently suspended - do not allow a context + * switch. */ + xYieldPendings[ xCoreID ] = pdTRUE; + } + else + { + xYieldPendings[ xCoreID ] = pdFALSE; + traceTASK_SWITCHED_OUT(); + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) { #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE - portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime ); + portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime[ xCoreID ] ); #else - ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); + ulTotalRunTime[ xCoreID ] = portGET_RUN_TIME_COUNTER_VALUE(); #endif /* Add the amount of time the task has been running to the @@ -3978,75 +5227,88 @@ void vTaskSwitchContext( BaseType_t xCoreID ) * overflows. The guard against negative values is to protect * against suspect run time stat counter implementations - which * are provided by the application, not the kernel. */ - if( ulTotalRunTime > ulTaskSwitchedInTime ) + if( ulTotalRunTime[ xCoreID ] > ulTaskSwitchedInTime[ xCoreID ] ) { - pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime ); + pxCurrentTCBs[ xCoreID ]->ulRunTimeCounter += ( ulTotalRunTime[ xCoreID ] - ulTaskSwitchedInTime[ xCoreID ] ); } else { mtCOVERAGE_TEST_MARKER(); } - ulTaskSwitchedInTime = ulTotalRunTime; + ulTaskSwitchedInTime[ xCoreID ] = ulTotalRunTime[ xCoreID ]; } - #endif /* configGENERATE_RUN_TIME_STATS */ + #endif /* configGENERATE_RUN_TIME_STATS */ - /* Check for stack overflow, if configured. */ - taskCHECK_FOR_STACK_OVERFLOW(); + /* Check for stack overflow, if configured. */ + taskCHECK_FOR_STACK_OVERFLOW(); - /* Before the currently running task is switched out, save its errno. */ - #if ( configUSE_POSIX_ERRNO == 1 ) + /* Before the currently running task is switched out, save its errno. */ + #if ( configUSE_POSIX_ERRNO == 1 ) { - pxCurrentTCB->iTaskErrno = FreeRTOS_errno; + pxCurrentTCBs[ xCoreID ]->iTaskErrno = FreeRTOS_errno; } - #endif + #endif - /* Select a new task to run using either the generic C or port - * optimised asm code. */ - ( void ) prvSelectHighestPriorityTask( xCoreID ); - traceTASK_SWITCHED_IN(); + /* Select a new task to run. */ + taskSELECT_HIGHEST_PRIORITY_TASK( xCoreID ); + traceTASK_SWITCHED_IN(); - /* After the new task is switched in, update the global errno. */ - #if ( configUSE_POSIX_ERRNO == 1 ) + /* Macro to inject port specific behaviour immediately after + * switching tasks, such as setting an end of stack watchpoint + * or reconfiguring the MPU. */ + portTASK_SWITCH_HOOK( pxCurrentTCBs[ portGET_CORE_ID() ] ); + + /* After the new task is switched in, update the global errno. */ + #if ( configUSE_POSIX_ERRNO == 1 ) { - FreeRTOS_errno = pxCurrentTCB->iTaskErrno; + FreeRTOS_errno = pxCurrentTCBs[ xCoreID ]->iTaskErrno; } - #endif + #endif - #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) && ( configNEWLIB_REENTRANT_IS_DYNAMIC == 0 ) ) + #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) { - /* Switch Newlib's _impure_ptr variable to point to the _reent - * structure specific to this task. - * See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html - * for additional information. - * - * Note: Updating the _impure_ptr is not required when Newlib is compiled with - * __DYNAMIC_REENT__ enabled. The the port should provide __getreent() instead. */ - _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); + /* Switch C-Runtime's TLS Block to point to the TLS + * Block specific to this task. */ + configSET_TLS_BLOCK( pxCurrentTCBs[ xCoreID ]->xTLSBlock ); } - #endif /* ( configUSE_NEWLIB_REENTRANT == 1 ) && ( configNEWLIB_REENTRANT_IS_DYNAMIC == 0 ) */ + #endif + } } + portRELEASE_ISR_LOCK(); + portRELEASE_TASK_LOCK(); + + traceRETURN_vTaskSwitchContext(); } - portRELEASE_ISR_LOCK(); - portRELEASE_TASK_LOCK(); -} +#endif /* if ( configNUMBER_OF_CORES > 1 ) */ /*-----------------------------------------------------------*/ void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) { + traceENTER_vTaskPlaceOnEventList( pxEventList, xTicksToWait ); + configASSERT( pxEventList ); - /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE + /* THIS FUNCTION MUST BE CALLED WITH THE * SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */ /* Place the event list item of the TCB in the appropriate event list. * This is placed in the list in priority order so the highest priority task - * is the first to be woken by the event. The queue that contains the event - * list is locked, preventing simultaneous access from interrupts. */ + * is the first to be woken by the event. + * + * Note: Lists are sorted in ascending order by ListItem_t.xItemValue. + * Normally, the xItemValue of a TCB's ListItem_t members is: + * xItemValue = ( configMAX_PRIORITIES - uxPriority ) + * Therefore, the event list is sorted in descending priority order. + * + * The queue that contains the event list is locked, preventing + * simultaneous access from interrupts. */ vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) ); prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); + + traceRETURN_vTaskPlaceOnEventList(); } /*-----------------------------------------------------------*/ @@ -4054,11 +5316,13 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait ) { + traceENTER_vTaskPlaceOnUnorderedEventList( pxEventList, xItemValue, xTicksToWait ); + configASSERT( pxEventList ); /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by * the event groups implementation. */ - configASSERT( uxSchedulerSuspended != 0 ); + configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U ); /* Store the item value in the event list item. It is safe to access the * event list item here as interrupts won't access the event list item of a @@ -4070,9 +5334,11 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, * event group implementation - and interrupts don't access event groups * directly (instead they access them indirectly by pending function calls to * the task level). */ - vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) ); + listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) ); prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); + + traceRETURN_vTaskPlaceOnUnorderedEventList(); } /*-----------------------------------------------------------*/ @@ -4082,6 +5348,8 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) { + traceENTER_vTaskPlaceOnEventListRestricted( pxEventList, xTicksToWait, xWaitIndefinitely ); + configASSERT( pxEventList ); /* This function should not be called by application code hence the @@ -4094,7 +5362,7 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, * In this case it is assume that this is the only task that is going to * be waiting on this event list, so the faster vListInsertEnd() function * can be used in place of vListInsert. */ - vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) ); + listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) ); /* If the task should block indefinitely then set the block time to a * value that will be recognised as an indefinite delay inside the @@ -4106,6 +5374,8 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) ); prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely ); + + traceRETURN_vTaskPlaceOnEventListRestricted(); } #endif /* configUSE_TIMERS */ @@ -4116,6 +5386,8 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) TCB_t * pxUnblockedTCB; BaseType_t xReturn; + traceENTER_xTaskRemoveFromEventList( pxEventList ); + /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be * called from a critical section within an ISR. */ @@ -4129,69 +5401,19 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) * * This function assumes that a check has already been made to ensure that * pxEventList is not empty. */ - pxUnblockedTCB = listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ + /* MISRA Ref 11.5.3 [Void pointer assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + pxUnblockedTCB = listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); configASSERT( pxUnblockedTCB ); - ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) ); + listREMOVE_ITEM( &( pxUnblockedTCB->xEventListItem ) ); - if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + if( uxSchedulerSuspended == ( UBaseType_t ) 0U ) { - ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) ); + listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) ); prvAddTaskToReadyList( pxUnblockedTCB ); #if ( configUSE_TICKLESS_IDLE != 0 ) - { - /* If a task is blocked on a kernel object then xNextTaskUnblockTime - * might be set to the blocked task's time out time. If the task is - * unblocked for a reason other than a timeout xNextTaskUnblockTime is - * normally left unchanged, because it is automatically reset to a new - * value when the tick count equals xNextTaskUnblockTime. However if - * tickless idling is used it might be more important to enter sleep mode - * at the earliest possible time - so reset xNextTaskUnblockTime here to - * ensure it is updated at the earliest possible time. */ - prvResetNextTaskUnblockTime(); - } - #endif - } - else - { - /* The delayed and ready lists cannot be accessed, so hold this task - * pending until the scheduler is resumed. */ - vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) ); - } - - xReturn = pdFALSE; - #if ( configUSE_PREEMPTION == 1 ) - prvYieldForTask( pxUnblockedTCB, pdFALSE ); - - if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE ) - { - xReturn = pdTRUE; - } - #endif - - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, - const TickType_t xItemValue ) -{ - TCB_t * pxUnblockedTCB; - - /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by - * the event flags implementation. */ - configASSERT( uxSchedulerSuspended != pdFALSE ); - - /* Store the new item value in the event list. */ - listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); - - /* Remove the event list form the event flag. Interrupts do not access - * event flags. */ - pxUnblockedTCB = listGET_LIST_ITEM_OWNER( pxEventListItem ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ - configASSERT( pxUnblockedTCB ); - ( void ) uxListRemove( pxEventListItem ); - - #if ( configUSE_TICKLESS_IDLE != 0 ) { /* If a task is blocked on a kernel object then xNextTaskUnblockTime * might be set to the blocked task's time out time. If the task is @@ -4203,26 +5425,131 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, * ensure it is updated at the earliest possible time. */ prvResetNextTaskUnblockTime(); } + #endif + } + else + { + /* The delayed and ready lists cannot be accessed, so hold this task + * pending until the scheduler is resumed. */ + listINSERT_END( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) ); + } + + #if ( configNUMBER_OF_CORES == 1 ) + { + if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority ) + { + /* Return true if the task removed from the event list has a higher + * priority than the calling task. This allows the calling task to know if + * it should force a context switch now. */ + xReturn = pdTRUE; + + /* Mark that a yield is pending in case the user is not using the + * "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ + xYieldPendings[ 0 ] = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + #else /* #if ( configNUMBER_OF_CORES == 1 ) */ + { + xReturn = pdFALSE; + + #if ( configUSE_PREEMPTION == 1 ) + { + prvYieldForTask( pxUnblockedTCB ); + + if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE ) + { + xReturn = pdTRUE; + } + } + #endif /* #if ( configUSE_PREEMPTION == 1 ) */ + } + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ + + traceRETURN_xTaskRemoveFromEventList( xReturn ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, + const TickType_t xItemValue ) +{ + TCB_t * pxUnblockedTCB; + + traceENTER_vTaskRemoveFromUnorderedEventList( pxEventListItem, xItemValue ); + + /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by + * the event flags implementation. */ + configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U ); + + /* Store the new item value in the event list. */ + listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); + + /* Remove the event list form the event flag. Interrupts do not access + * event flags. */ + /* MISRA Ref 11.5.3 [Void pointer assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + pxUnblockedTCB = listGET_LIST_ITEM_OWNER( pxEventListItem ); + configASSERT( pxUnblockedTCB ); + listREMOVE_ITEM( pxEventListItem ); + + #if ( configUSE_TICKLESS_IDLE != 0 ) + { + /* If a task is blocked on a kernel object then xNextTaskUnblockTime + * might be set to the blocked task's time out time. If the task is + * unblocked for a reason other than a timeout xNextTaskUnblockTime is + * normally left unchanged, because it is automatically reset to a new + * value when the tick count equals xNextTaskUnblockTime. However if + * tickless idling is used it might be more important to enter sleep mode + * at the earliest possible time - so reset xNextTaskUnblockTime here to + * ensure it is updated at the earliest possible time. */ + prvResetNextTaskUnblockTime(); + } #endif /* Remove the task from the delayed list and add it to the ready list. The * scheduler is suspended so interrupts will not be accessing the ready * lists. */ - ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) ); + listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) ); prvAddTaskToReadyList( pxUnblockedTCB ); - #if ( configUSE_PREEMPTION == 1 ) - taskENTER_CRITICAL(); + #if ( configNUMBER_OF_CORES == 1 ) + { + if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority ) { - prvYieldForTask( pxUnblockedTCB, pdFALSE ); + /* The unblocked task has a priority above that of the calling task, so + * a context switch is required. This function is called with the + * scheduler suspended so xYieldPending is set so the context switch + * occurs immediately that the scheduler is resumed (unsuspended). */ + xYieldPendings[ 0 ] = pdTRUE; } - taskEXIT_CRITICAL(); - #endif + } + #else /* #if ( configNUMBER_OF_CORES == 1 ) */ + { + #if ( configUSE_PREEMPTION == 1 ) + { + taskENTER_CRITICAL(); + { + prvYieldForTask( pxUnblockedTCB ); + } + taskEXIT_CRITICAL(); + } + #endif + } + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ + + traceRETURN_vTaskRemoveFromUnorderedEventList(); } /*-----------------------------------------------------------*/ void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) { + traceENTER_vTaskSetTimeOutState( pxTimeOut ); + configASSERT( pxTimeOut ); taskENTER_CRITICAL(); { @@ -4230,14 +5557,20 @@ void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) pxTimeOut->xTimeOnEntering = xTickCount; } taskEXIT_CRITICAL(); + + traceRETURN_vTaskSetTimeOutState(); } /*-----------------------------------------------------------*/ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) { + traceENTER_vTaskInternalSetTimeOutState( pxTimeOut ); + /* For internal use only as it does not use a critical section. */ pxTimeOut->xOverflowCount = xNumOfOverflows; pxTimeOut->xTimeOnEntering = xTickCount; + + traceRETURN_vTaskInternalSetTimeOutState(); } /*-----------------------------------------------------------*/ @@ -4246,6 +5579,8 @@ BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, { BaseType_t xReturn; + traceENTER_xTaskCheckForTimeOut( pxTimeOut, pxTicksToWait ); + configASSERT( pxTimeOut ); configASSERT( pxTicksToWait ); @@ -4277,7 +5612,7 @@ BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, else #endif - if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */ + if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) { /* The tick count is greater than the time at which * vTaskSetTimeout() was called, but has also overflowed since @@ -4287,7 +5622,7 @@ BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, xReturn = pdTRUE; *pxTicksToWait = ( TickType_t ) 0; } - else if( xElapsedTime < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */ + else if( xElapsedTime < *pxTicksToWait ) { /* Not a genuine timeout. Adjust parameters for time remaining. */ *pxTicksToWait -= xElapsedTime; @@ -4302,14 +5637,20 @@ BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, } taskEXIT_CRITICAL(); + traceRETURN_xTaskCheckForTimeOut( xReturn ); + return xReturn; } /*-----------------------------------------------------------*/ void vTaskMissedYield( void ) { - /* Must be called from within a critical section */ + traceENTER_vTaskMissedYield(); + + /* Must be called from within a critical section. */ xYieldPendings[ portGET_CORE_ID() ] = pdTRUE; + + traceRETURN_vTaskMissedYield(); } /*-----------------------------------------------------------*/ @@ -4320,6 +5661,8 @@ void vTaskMissedYield( void ) UBaseType_t uxReturn; TCB_t const * pxTCB; + traceENTER_uxTaskGetTaskNumber( xTask ); + if( xTask != NULL ) { pxTCB = xTask; @@ -4330,6 +5673,8 @@ void vTaskMissedYield( void ) uxReturn = 0U; } + traceRETURN_uxTaskGetTaskNumber( uxReturn ); + return uxReturn; } @@ -4343,92 +5688,106 @@ void vTaskMissedYield( void ) { TCB_t * pxTCB; + traceENTER_vTaskSetTaskNumber( xTask, uxHandle ); + if( xTask != NULL ) { pxTCB = xTask; pxTCB->uxTaskNumber = uxHandle; } + + traceRETURN_vTaskSetTaskNumber(); } #endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ /* * ----------------------------------------------------------- - * The MinimalIdle task. + * The passive idle task. * ---------------------------------------------------------- * - * The minimal idle task is used for all the additional Cores in a SMP system. - * There must be only 1 idle task and the rest are minimal idle tasks. + * The passive idle task is used for all the additional cores in a SMP + * system. There must be only 1 active idle task and the rest are passive + * idle tasks. * - * @todo additional conditional compiles to remove this function. + * The portTASK_FUNCTION() macro is used to allow port/compiler specific + * language extensions. The equivalent prototype for this function is: + * + * void prvPassiveIdleTask( void *pvParameters ); */ -#if ( configNUM_CORES > 1 ) - static portTASK_FUNCTION( prvMinimalIdleTask, pvParameters ) +#if ( configNUMBER_OF_CORES > 1 ) + static portTASK_FUNCTION( prvPassiveIdleTask, pvParameters ) { + ( void ) pvParameters; + taskYIELD(); - for( ; ; ) + for( ; configCONTROL_INFINITE_LOOP(); ) { #if ( configUSE_PREEMPTION == 0 ) - { - /* If we are not using preemption we keep forcing a task switch to - * see if any other task has become available. If we are using - * preemption we don't need to do this as any task becoming available - * will automatically get the processor anyway. */ - taskYIELD(); - } + { + /* If we are not using preemption we keep forcing a task switch to + * see if any other task has become available. If we are using + * preemption we don't need to do this as any task becoming available + * will automatically get the processor anyway. */ + taskYIELD(); + } #endif /* configUSE_PREEMPTION */ #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) + { + /* When using preemption tasks of equal priority will be + * timesliced. If a task that is sharing the idle priority is ready + * to run then the idle task should yield before the end of the + * timeslice. + * + * A critical region is not required here as we are just reading from + * the list, and an occasional incorrect value will not matter. If + * the ready list at the idle priority contains one more task than the + * number of idle tasks, which is equal to the configured numbers of cores + * then a task other than the idle task is ready to execute. */ + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES ) { - /* When using preemption tasks of equal priority will be - * timesliced. If a task that is sharing the idle priority is ready - * to run then the idle task should yield before the end of the - * timeslice. - * - * A critical region is not required here as we are just reading from - * the list, and an occasional incorrect value will not matter. If - * the ready list at the idle priority contains one more task than the - * number of idle tasks, which is equal to the configured numbers of cores - * then a task other than the idle task is ready to execute. */ - if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUM_CORES ) - { - taskYIELD(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + taskYIELD(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */ - #if ( configUSE_MINIMAL_IDLE_HOOK == 1 ) - { - extern void vApplicationMinimalIdleHook( void ); - - /* Call the user defined function from within the idle task. This - * allows the application designer to add background functionality - * without the overhead of a separate task. - * - * This hook is intended to manage core activity such as disabling cores that go idle. - * - * NOTE: vApplicationMinimalIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, - * CALL A FUNCTION THAT MIGHT BLOCK. */ - vApplicationMinimalIdleHook(); - } - #endif /* configUSE_MINIMAL_IDLE_HOOK */ + #if ( configUSE_PASSIVE_IDLE_HOOK == 1 ) + { + /* Call the user defined function from within the idle task. This + * allows the application designer to add background functionality + * without the overhead of a separate task. + * + * This hook is intended to manage core activity such as disabling cores that go idle. + * + * NOTE: vApplicationPassiveIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, + * CALL A FUNCTION THAT MIGHT BLOCK. */ + vApplicationPassiveIdleHook(); + } + #endif /* configUSE_PASSIVE_IDLE_HOOK */ } } -#endif /* if ( configNUM_CORES > 1 ) */ +#endif /* #if ( configNUMBER_OF_CORES > 1 ) */ /* * ----------------------------------------------------------- - * The Idle task. + * The idle task. * ---------------------------------------------------------- * + * The portTASK_FUNCTION() macro is used to allow port/compiler specific + * language extensions. The equivalent prototype for this function is: + * + * void prvIdleTask( void *pvParameters ); * */ + static portTASK_FUNCTION( prvIdleTask, pvParameters ) { /* Stop warnings. */ @@ -4442,61 +5801,58 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) * any. */ portALLOCATE_SECURE_CONTEXT( configMINIMAL_SECURE_STACK_SIZE ); - /* All cores start up in the idle task. This initial yield gets the application - * tasks started. */ - taskYIELD(); + #if ( configNUMBER_OF_CORES > 1 ) + { + /* SMP all cores start up in the idle task. This initial yield gets the application + * tasks started. */ + taskYIELD(); + } + #endif /* #if ( configNUMBER_OF_CORES > 1 ) */ - for( ; ; ) + for( ; configCONTROL_INFINITE_LOOP(); ) { /* See if any tasks have deleted themselves - if so then the idle task * is responsible for freeing the deleted task's TCB and stack. */ prvCheckTasksWaitingTermination(); #if ( configUSE_PREEMPTION == 0 ) - { - /* If we are not using preemption we keep forcing a task switch to - * see if any other task has become available. If we are using - * preemption we don't need to do this as any task becoming available - * will automatically get the processor anyway. */ - taskYIELD(); - } + { + /* If we are not using preemption we keep forcing a task switch to + * see if any other task has become available. If we are using + * preemption we don't need to do this as any task becoming available + * will automatically get the processor anyway. */ + taskYIELD(); + } #endif /* configUSE_PREEMPTION */ #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) + { + /* When using preemption tasks of equal priority will be + * timesliced. If a task that is sharing the idle priority is ready + * to run then the idle task should yield before the end of the + * timeslice. + * + * A critical region is not required here as we are just reading from + * the list, and an occasional incorrect value will not matter. If + * the ready list at the idle priority contains one more task than the + * number of idle tasks, which is equal to the configured numbers of cores + * then a task other than the idle task is ready to execute. */ + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES ) { - /* When using preemption tasks of equal priority will be - * timesliced. If a task that is sharing the idle priority is ready - * to run then the idle task should yield before the end of the - * timeslice. - * - * A critical region is not required here as we are just reading from - * the list, and an occasional incorrect value will not matter. If - * the ready list at the idle priority contains one more task than the - * number of idle tasks, which is equal to the configured numbers of cores - * then a task other than the idle task is ready to execute. */ - if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUM_CORES ) - { - taskYIELD(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + taskYIELD(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */ #if ( configUSE_IDLE_HOOK == 1 ) - { - extern void vApplicationIdleHook( void ); - - /* Call the user defined function from within 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. */ - vApplicationIdleHook(); - } + { + /* Call the user defined function from within the idle task. */ + vApplicationIdleHook(); + } #endif /* configUSE_IDLE_HOOK */ /* This conditional compilation should use inequality to 0, not equality @@ -4504,66 +5860,64 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) * user defined low power mode implementations require * configUSE_TICKLESS_IDLE to be set to a value other than 1. */ #if ( configUSE_TICKLESS_IDLE != 0 ) + { + TickType_t xExpectedIdleTime; + + /* It is not desirable to suspend then resume the scheduler on + * each iteration of the idle task. Therefore, a preliminary + * test of the expected idle time is performed without the + * scheduler suspended. The result here is not necessarily + * valid. */ + xExpectedIdleTime = prvGetExpectedIdleTime(); + + if( xExpectedIdleTime >= ( TickType_t ) configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) { - TickType_t xExpectedIdleTime; - - /* It is not desirable to suspend then resume the scheduler on - * each iteration of the idle task. Therefore, a preliminary - * test of the expected idle time is performed without the - * scheduler suspended. The result here is not necessarily - * valid. */ - xExpectedIdleTime = prvGetExpectedIdleTime(); - - if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) + vTaskSuspendAll(); { - vTaskSuspendAll(); + /* Now the scheduler is suspended, the expected idle + * time can be sampled again, and this time its value can + * be used. */ + configASSERT( xNextTaskUnblockTime >= xTickCount ); + xExpectedIdleTime = prvGetExpectedIdleTime(); + + /* Define the following macro to set xExpectedIdleTime to 0 + * if the application does not want + * portSUPPRESS_TICKS_AND_SLEEP() to be called. */ + configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime ); + + if( xExpectedIdleTime >= ( TickType_t ) configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) { - /* Now the scheduler is suspended, the expected idle - * time can be sampled again, and this time its value can - * be used. */ - configASSERT( xNextTaskUnblockTime >= xTickCount ); - xExpectedIdleTime = prvGetExpectedIdleTime(); - - /* Define the following macro to set xExpectedIdleTime to 0 - * if the application does not want - * portSUPPRESS_TICKS_AND_SLEEP() to be called. */ - configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime ); - - if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) - { - traceLOW_POWER_IDLE_BEGIN(); - portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); - traceLOW_POWER_IDLE_END(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + traceLOW_POWER_IDLE_BEGIN(); + portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); + traceLOW_POWER_IDLE_END(); + } + else + { + mtCOVERAGE_TEST_MARKER(); } - ( void ) xTaskResumeAll(); - } - else - { - mtCOVERAGE_TEST_MARKER(); } + ( void ) xTaskResumeAll(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } #endif /* configUSE_TICKLESS_IDLE */ - #if ( configUSE_MINIMAL_IDLE_HOOK == 1 ) - { - extern void vApplicationMinimalIdleHook( void ); - - /* Call the user defined function from within the idle task. This - * allows the application designer to add background functionality - * without the overhead of a separate task. - * - * This hook is intended to manage core activity such as disabling cores that go idle. - * - * NOTE: vApplicationMinimalIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, - * CALL A FUNCTION THAT MIGHT BLOCK. */ - vApplicationMinimalIdleHook(); - } - #endif /* configUSE_MINIMAL_IDLE_HOOK */ + #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PASSIVE_IDLE_HOOK == 1 ) ) + { + /* Call the user defined function from within the idle task. This + * allows the application designer to add background functionality + * without the overhead of a separate task. + * + * This hook is intended to manage core activity such as disabling cores that go idle. + * + * NOTE: vApplicationPassiveIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, + * CALL A FUNCTION THAT MIGHT BLOCK. */ + vApplicationPassiveIdleHook(); + } + #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PASSIVE_IDLE_HOOK == 1 ) ) */ } } /*-----------------------------------------------------------*/ @@ -4572,44 +5926,51 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) eSleepModeStatus eTaskConfirmSleepModeStatus( void ) { - /* The idle task exists in addition to the application tasks. */ - const UBaseType_t uxNonApplicationTasks = 1; + #if ( INCLUDE_vTaskSuspend == 1 ) + /* The idle task exists in addition to the application tasks. */ + const UBaseType_t uxNonApplicationTasks = configNUMBER_OF_CORES; + #endif /* INCLUDE_vTaskSuspend */ + eSleepModeStatus eReturn = eStandardSleep; + traceENTER_eTaskConfirmSleepModeStatus(); + /* This function must be called from a critical section. */ - if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 ) + if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0U ) { /* A task was made ready while the scheduler was suspended. */ eReturn = eAbortSleep; } - else if( xYieldPending != pdFALSE ) + else if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE ) { /* A yield was pended while the scheduler was suspended. */ eReturn = eAbortSleep; } - else if( xPendedTicks != 0 ) + else if( xPendedTicks != 0U ) { /* A tick interrupt has already occurred but was held pending * because the scheduler is suspended. */ eReturn = eAbortSleep; } - else - { - /* If all the tasks are in the suspended list (which might mean they - * have an infinite block time rather than actually being suspended) - * then it is safe to turn all clocks off and just wait for external - * interrupts. */ - if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) ) + + #if ( INCLUDE_vTaskSuspend == 1 ) + else if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) ) { + /* If all the tasks are in the suspended list (which might mean they + * have an infinite block time rather than actually being suspended) + * then it is safe to turn all clocks off and just wait for external + * interrupts. */ eReturn = eNoTasksWaitingTimeout; } - else - { - mtCOVERAGE_TEST_MARKER(); - } + #endif /* INCLUDE_vTaskSuspend */ + else + { + mtCOVERAGE_TEST_MARKER(); } + traceRETURN_eTaskConfirmSleepModeStatus( eReturn ); + return eReturn; } @@ -4624,12 +5985,17 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) { TCB_t * pxTCB; - if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) + traceENTER_vTaskSetThreadLocalStoragePointer( xTaskToSet, xIndex, pvValue ); + + if( ( xIndex >= 0 ) && + ( xIndex < ( BaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS ) ) { pxTCB = prvGetTCBFromHandle( xTaskToSet ); configASSERT( pxTCB != NULL ); pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue; } + + traceRETURN_vTaskSetThreadLocalStoragePointer(); } #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */ @@ -4643,7 +6009,10 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) void * pvReturn = NULL; TCB_t * pxTCB; - if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) + traceENTER_pvTaskGetThreadLocalStoragePointer( xTaskToQuery, xIndex ); + + if( ( xIndex >= 0 ) && + ( xIndex < ( BaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS ) ) { pxTCB = prvGetTCBFromHandle( xTaskToQuery ); pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ]; @@ -4653,6 +6022,8 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) pvReturn = NULL; } + traceRETURN_pvTaskGetThreadLocalStoragePointer( pvReturn ); + return pvReturn; } @@ -4662,15 +6033,19 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) #if ( portUSING_MPU_WRAPPERS == 1 ) void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, - const MemoryRegion_t * const xRegions ) + const MemoryRegion_t * const pxRegions ) { TCB_t * pxTCB; + traceENTER_vTaskAllocateMPURegions( xTaskToModify, pxRegions ); + /* If null is passed in here then we are modifying the MPU settings of * the calling task. */ pxTCB = prvGetTCBFromHandle( xTaskToModify ); - vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 ); + vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), pxRegions, NULL, 0 ); + + traceRETURN_vTaskAllocateMPURegions(); } #endif /* portUSING_MPU_WRAPPERS */ @@ -4690,15 +6065,15 @@ static void prvInitialiseTaskLists( void ) vListInitialise( &xPendingReadyList ); #if ( INCLUDE_vTaskDelete == 1 ) - { - vListInitialise( &xTasksWaitingTermination ); - } + { + vListInitialise( &xTasksWaitingTermination ); + } #endif /* INCLUDE_vTaskDelete */ #if ( INCLUDE_vTaskSuspend == 1 ) - { - vListInitialise( &xSuspendedTaskList ); - } + { + vListInitialise( &xSuspendedTaskList ); + } #endif /* INCLUDE_vTaskSuspend */ /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList @@ -4713,28 +6088,52 @@ static void prvCheckTasksWaitingTermination( void ) /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/ #if ( INCLUDE_vTaskDelete == 1 ) - { - TCB_t * pxTCB; + { + TCB_t * pxTCB; - /* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL() - * being called too often in the idle task. */ - while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) + /* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL() + * being called too often in the idle task. */ + while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) + { + #if ( configNUMBER_OF_CORES == 1 ) { taskENTER_CRITICAL(); { - /* Since we are SMP, multiple idles can be running simultaneously + { + /* MISRA Ref 11.5.3 [Void pointer assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + --uxCurrentNumberOfTasks; + --uxDeletedTasksWaitingCleanUp; + } + } + taskEXIT_CRITICAL(); + + prvDeleteTCB( pxTCB ); + } + #else /* #if( configNUMBER_OF_CORES == 1 ) */ + { + pxTCB = NULL; + + taskENTER_CRITICAL(); + { + /* For SMP, multiple idles can be running simultaneously * and we need to check that other idles did not cleanup while we were - * waiting to enter the critical section */ + * waiting to enter the critical section. */ if( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) { - pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ + /* MISRA Ref 11.5.3 [Void pointer assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); if( pxTCB->xTaskRunState == taskTASK_NOT_RUNNING ) { ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); --uxCurrentNumberOfTasks; --uxDeletedTasksWaitingCleanUp; - prvDeleteTCB( pxTCB ); } else { @@ -4747,8 +6146,15 @@ static void prvCheckTasksWaitingTermination( void ) } } taskEXIT_CRITICAL(); + + if( pxTCB != NULL ) + { + prvDeleteTCB( pxTCB ); + } } + #endif /* #if( configNUMBER_OF_CORES == 1 ) */ } + } #endif /* INCLUDE_vTaskDelete */ } /*-----------------------------------------------------------*/ @@ -4762,39 +6168,45 @@ static void prvCheckTasksWaitingTermination( void ) { TCB_t * pxTCB; + traceENTER_vTaskGetInfo( xTask, pxTaskStatus, xGetFreeStackSpace, eState ); + /* xTask is NULL then get the state of the calling task. */ pxTCB = prvGetTCBFromHandle( xTask ); - pxTaskStatus->xHandle = ( TaskHandle_t ) pxTCB; + pxTaskStatus->xHandle = pxTCB; pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName[ 0 ] ); pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority; pxTaskStatus->pxStackBase = pxTCB->pxStack; + #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) + pxTaskStatus->pxTopOfStack = ( StackType_t * ) pxTCB->pxTopOfStack; + pxTaskStatus->pxEndOfStack = pxTCB->pxEndOfStack; + #endif pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber; - #if ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUM_CORES > 1 ) ) - { - pxTaskStatus->uxCoreAffinityMask = pxTCB->uxCoreAffinityMask; - } + #if ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) + { + pxTaskStatus->uxCoreAffinityMask = pxTCB->uxCoreAffinityMask; + } #endif #if ( configUSE_MUTEXES == 1 ) - { - pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority; - } + { + pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority; + } #else - { - pxTaskStatus->uxBasePriority = 0; - } + { + pxTaskStatus->uxBasePriority = 0; + } #endif #if ( configGENERATE_RUN_TIME_STATS == 1 ) - { - pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter; - } + { + pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter; + } #else - { - pxTaskStatus->ulRunTimeCounter = 0; - } + { + pxTaskStatus->ulRunTimeCounter = ( configRUN_TIME_COUNTER_TYPE ) 0; + } #endif /* Obtaining the task state is a little fiddly, so is only done if the @@ -4802,7 +6214,7 @@ static void prvCheckTasksWaitingTermination( void ) * state is just set to whatever is passed in. */ if( eState != eInvalid ) { - if( taskTASK_IS_RUNNING( pxTCB->xTaskRunState ) ) + if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) { pxTaskStatus->eCurrentState = eRunning; } @@ -4811,23 +6223,53 @@ static void prvCheckTasksWaitingTermination( void ) pxTaskStatus->eCurrentState = eState; #if ( INCLUDE_vTaskSuspend == 1 ) + { + /* If the task is in the suspended list then there is a + * chance it is actually just blocked indefinitely - so really + * it should be reported as being in the Blocked state. */ + if( eState == eSuspended ) { - /* If the task is in the suspended list then there is a - * chance it is actually just blocked indefinitely - so really - * it should be reported as being in the Blocked state. */ - if( eState == eSuspended ) + vTaskSuspendAll(); { - vTaskSuspendAll(); + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) { - if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + pxTaskStatus->eCurrentState = eBlocked; + } + else + { + BaseType_t x; + + /* The task does not appear on the event list item of + * and of the RTOS objects, but could still be in the + * blocked state if it is waiting on its notification + * rather than waiting on an object. If not, is + * suspended. */ + for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ ) { - pxTaskStatus->eCurrentState = eBlocked; + if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION ) + { + pxTaskStatus->eCurrentState = eBlocked; + break; + } } } - ( void ) xTaskResumeAll(); } + ( void ) xTaskResumeAll(); } + } #endif /* INCLUDE_vTaskSuspend */ + + /* Tasks can be in pending ready list and other state list at the + * same time. These tasks are in ready state no matter what state + * list the task is in. */ + taskENTER_CRITICAL(); + { + if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdFALSE ) + { + pxTaskStatus->eCurrentState = eReady; + } + } + taskEXIT_CRITICAL(); } } else @@ -4840,19 +6282,21 @@ static void prvCheckTasksWaitingTermination( void ) if( xGetFreeStackSpace != pdFALSE ) { #if ( portSTACK_GROWTH > 0 ) - { - pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack ); - } + { + pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack ); + } #else - { - pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack ); - } + { + pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack ); + } #endif } else { pxTaskStatus->usStackHighWaterMark = 0; } + + traceRETURN_vTaskGetInfo(); } #endif /* configUSE_TRACE_FACILITY */ @@ -4864,12 +6308,16 @@ static void prvCheckTasksWaitingTermination( void ) List_t * pxList, eTaskState eState ) { - configLIST_VOLATILE TCB_t * pxNextTCB, * pxFirstTCB; + configLIST_VOLATILE TCB_t * pxNextTCB; + configLIST_VOLATILE TCB_t * pxFirstTCB; UBaseType_t uxTask = 0; if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) { - listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ + /* MISRA Ref 11.5.3 [Void pointer assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /* Populate an TaskStatus_t structure within the * pxTaskStatusArray array for each task that is referenced from @@ -4877,7 +6325,10 @@ static void prvCheckTasksWaitingTermination( void ) * meaning of each TaskStatus_t structure member. */ do { - listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ + /* MISRA Ref 11.5.3 [Void pointer assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); vTaskGetInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState ); uxTask++; } while( pxNextTCB != pxFirstTCB ); @@ -4905,7 +6356,7 @@ static void prvCheckTasksWaitingTermination( void ) ulCount++; } - ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */ + ulCount /= ( uint32_t ) sizeof( StackType_t ); return ( configSTACK_DEPTH_TYPE ) ulCount; } @@ -4926,6 +6377,8 @@ static void prvCheckTasksWaitingTermination( void ) uint8_t * pucEndOfStack; configSTACK_DEPTH_TYPE uxReturn; + traceENTER_uxTaskGetStackHighWaterMark2( xTask ); + /* 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 @@ -4936,17 +6389,19 @@ static void prvCheckTasksWaitingTermination( void ) pxTCB = prvGetTCBFromHandle( xTask ); #if portSTACK_GROWTH < 0 - { - pucEndOfStack = ( uint8_t * ) pxTCB->pxStack; - } + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxStack; + } #else - { - pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack; - } + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack; + } #endif uxReturn = prvTaskCheckFreeStackSpace( pucEndOfStack ); + traceRETURN_uxTaskGetStackHighWaterMark2( uxReturn ); + return uxReturn; } @@ -4961,20 +6416,24 @@ static void prvCheckTasksWaitingTermination( void ) uint8_t * pucEndOfStack; UBaseType_t uxReturn; + traceENTER_uxTaskGetStackHighWaterMark( xTask ); + pxTCB = prvGetTCBFromHandle( xTask ); #if portSTACK_GROWTH < 0 - { - pucEndOfStack = ( uint8_t * ) pxTCB->pxStack; - } + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxStack; + } #else - { - pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack; - } + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack; + } #endif uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack ); + traceRETURN_uxTaskGetStackHighWaterMark( uxReturn ); + return uxReturn; } @@ -4990,49 +6449,46 @@ static void prvCheckTasksWaitingTermination( void ) * want to allocate and clean RAM statically. */ portCLEAN_UP_TCB( pxTCB ); - /* Free up the memory allocated by the scheduler for the task. It is up - * to the task to free any memory allocated at the application level. - * See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html - * for additional information. */ - #if ( configUSE_NEWLIB_REENTRANT == 1 ) - { - _reclaim_reent( &( pxTCB->xNewLib_reent ) ); - } - #endif /* configUSE_NEWLIB_REENTRANT */ + #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) + { + /* Free up the memory allocated for the task's TLS Block. */ + configDEINIT_TLS_BLOCK( pxTCB->xTLSBlock ); + } + #endif #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) ) + { + /* The task can only have been allocated dynamically - free both + * the stack and TCB. */ + vPortFreeStack( pxTCB->pxStack ); + vPortFree( pxTCB ); + } + #elif ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) + { + /* The task could have been allocated statically or dynamically, so + * check what was statically allocated before trying to free the + * memory. */ + if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ) { - /* The task can only have been allocated dynamically - free both - * the stack and TCB. */ + /* Both the stack and TCB were allocated dynamically, so both + * must be freed. */ vPortFreeStack( pxTCB->pxStack ); vPortFree( pxTCB ); } - #elif ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */ + else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY ) { - /* The task could have been allocated statically or dynamically, so - * check what was statically allocated before trying to free the - * memory. */ - if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ) - { - /* Both the stack and TCB were allocated dynamically, so both - * must be freed. */ - vPortFreeStack( pxTCB->pxStack ); - vPortFree( pxTCB ); - } - else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY ) - { - /* Only the stack was statically allocated, so the TCB is the - * only memory that must be freed. */ - vPortFree( pxTCB ); - } - else - { - /* Neither the stack nor the TCB were allocated dynamically, so - * nothing needs to be freed. */ - configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB ); - mtCOVERAGE_TEST_MARKER(); - } + /* Only the stack was statically allocated, so the TCB is the + * only memory that must be freed. */ + vPortFree( pxTCB ); } + else + { + /* Neither the stack nor the TCB were allocated dynamically, so + * nothing needs to be freed. */ + configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB ); + mtCOVERAGE_TEST_MARKER(); + } + } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ } @@ -5060,31 +6516,59 @@ static void prvResetNextTaskUnblockTime( void ) } /*-----------------------------------------------------------*/ -#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) +#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) || ( configNUMBER_OF_CORES > 1 ) - TaskHandle_t xTaskGetCurrentTaskHandle( void ) - { - TaskHandle_t xReturn; - uint32_t ulState; - - ulState = portDISABLE_INTERRUPTS(); - xReturn = pxCurrentTCBs[ portGET_CORE_ID() ]; - portRESTORE_INTERRUPTS( ulState ); - - return xReturn; - } - - TaskHandle_t xTaskGetCurrentTaskHandleCPU( UBaseType_t xCoreID ) - { - TaskHandle_t xReturn = NULL; - - if( taskVALID_CORE_ID( xCoreID ) != pdFALSE ) + #if ( configNUMBER_OF_CORES == 1 ) + TaskHandle_t xTaskGetCurrentTaskHandle( void ) { - xReturn = pxCurrentTCBs[ xCoreID ]; + TaskHandle_t xReturn; + + traceENTER_xTaskGetCurrentTaskHandle(); + + /* A critical section is not required as this is not called from + * an interrupt and the current TCB will always be the same for any + * individual execution thread. */ + xReturn = pxCurrentTCB; + + traceRETURN_xTaskGetCurrentTaskHandle( xReturn ); + + return xReturn; + } + #else /* #if ( configNUMBER_OF_CORES == 1 ) */ + TaskHandle_t xTaskGetCurrentTaskHandle( void ) + { + TaskHandle_t xReturn; + UBaseType_t uxSavedInterruptStatus; + + traceENTER_xTaskGetCurrentTaskHandle(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK(); + { + xReturn = pxCurrentTCBs[ portGET_CORE_ID() ]; + } + portCLEAR_INTERRUPT_MASK( uxSavedInterruptStatus ); + + traceRETURN_xTaskGetCurrentTaskHandle( xReturn ); + + return xReturn; } - return xReturn; - } + TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID ) + { + TaskHandle_t xReturn = NULL; + + traceENTER_xTaskGetCurrentTaskHandleForCore( xCoreID ); + + if( taskVALID_CORE_ID( xCoreID ) != pdFALSE ) + { + xReturn = pxCurrentTCBs[ xCoreID ]; + } + + traceRETURN_xTaskGetCurrentTaskHandleForCore( xReturn ); + + return xReturn; + } + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */ /*-----------------------------------------------------------*/ @@ -5095,15 +6579,19 @@ static void prvResetNextTaskUnblockTime( void ) { BaseType_t xReturn; + traceENTER_xTaskGetSchedulerState(); + if( xSchedulerRunning == pdFALSE ) { xReturn = taskSCHEDULER_NOT_STARTED; } else { - taskENTER_CRITICAL(); + #if ( configNUMBER_OF_CORES > 1 ) + taskENTER_CRITICAL(); + #endif { - if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + if( uxSchedulerSuspended == ( UBaseType_t ) 0U ) { xReturn = taskSCHEDULER_RUNNING; } @@ -5112,9 +6600,13 @@ static void prvResetNextTaskUnblockTime( void ) xReturn = taskSCHEDULER_SUSPENDED; } } - taskEXIT_CRITICAL(); + #if ( configNUMBER_OF_CORES > 1 ) + taskEXIT_CRITICAL(); + #endif } + traceRETURN_xTaskGetSchedulerState( xReturn ); + return xReturn; } @@ -5128,9 +6620,10 @@ static void prvResetNextTaskUnblockTime( void ) TCB_t * const pxMutexHolderTCB = pxMutexHolder; BaseType_t xReturn = pdFALSE; - /* If the mutex was given back by an interrupt while the queue was - * locked then the mutex holder might now be NULL. _RB_ Is this still - * needed as interrupts can no longer use mutexes? */ + traceENTER_xTaskPriorityInherit( pxMutexHolder ); + + /* If the mutex is taken by an interrupt, the mutex holder is NULL. Priority + * inheritance is not applied in this scenario. */ if( pxMutexHolder != NULL ) { /* If the holder of the mutex has a priority below the priority of @@ -5141,9 +6634,9 @@ static void prvResetNextTaskUnblockTime( void ) /* Adjust the mutex holder state to account for its new * priority. Only reset the event list item value if the value is * not being used for anything else. */ - if( ( listGET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) + if( ( listGET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == ( ( TickType_t ) 0UL ) ) { - listSET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + listSET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); } else { @@ -5169,6 +6662,16 @@ static void prvResetNextTaskUnblockTime( void ) /* Inherit the priority before being moved into the new list. */ pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority; prvAddTaskToReadyList( pxMutexHolderTCB ); + #if ( configNUMBER_OF_CORES > 1 ) + { + /* The priority of the task is raised. Yield for this task + * if it is not running. */ + if( taskTASK_IS_RUNNING( pxMutexHolderTCB ) != pdTRUE ) + { + prvYieldForTask( pxMutexHolderTCB ); + } + } + #endif /* if ( configNUMBER_OF_CORES > 1 ) */ } else { @@ -5205,6 +6708,8 @@ static void prvResetNextTaskUnblockTime( void ) mtCOVERAGE_TEST_MARKER(); } + traceRETURN_xTaskPriorityInherit( xReturn ); + return xReturn; } @@ -5218,6 +6723,8 @@ static void prvResetNextTaskUnblockTime( void ) TCB_t * const pxTCB = pxMutexHolder; BaseType_t xReturn = pdFALSE; + traceENTER_xTaskPriorityDisinherit( pxMutexHolder ); + if( pxMutexHolder != NULL ) { /* A task can only have an inherited priority if it holds the mutex. @@ -5257,8 +6764,18 @@ static void prvResetNextTaskUnblockTime( void ) /* Reset the event list item value. It cannot be in use for * any other purpose if this task is running, and it must be * running to give back the mutex. */ - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); prvAddTaskToReadyList( pxTCB ); + #if ( configNUMBER_OF_CORES > 1 ) + { + /* The priority of the task is dropped. Yield the core on + * which the task is running. */ + if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + { + prvYieldCore( pxTCB->xTaskRunState ); + } + } + #endif /* if ( configNUMBER_OF_CORES > 1 ) */ /* Return true to indicate that a context switch is required. * This is only actually required in the corner case whereby @@ -5285,6 +6802,8 @@ static void prvResetNextTaskUnblockTime( void ) mtCOVERAGE_TEST_MARKER(); } + traceRETURN_xTaskPriorityDisinherit( xReturn ); + return xReturn; } @@ -5300,6 +6819,8 @@ static void prvResetNextTaskUnblockTime( void ) UBaseType_t uxPriorityUsedOnEntry, uxPriorityToUse; const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1; + traceENTER_vTaskPriorityDisinheritAfterTimeout( pxMutexHolder, uxHighestPriorityWaitingTask ); + if( pxMutexHolder != NULL ) { /* If pxMutexHolder is not NULL then the holder must hold at least @@ -5342,9 +6863,9 @@ static void prvResetNextTaskUnblockTime( void ) /* Only reset the event list item value if the value is not * being used for anything else. */ - if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) + if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == ( ( TickType_t ) 0UL ) ) { - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriorityToUse ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriorityToUse ); } else { @@ -5372,6 +6893,16 @@ static void prvResetNextTaskUnblockTime( void ) } prvAddTaskToReadyList( pxTCB ); + #if ( configNUMBER_OF_CORES > 1 ) + { + /* The priority of the task is dropped. Yield the core on + * which the task is running. */ + if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + { + prvYieldCore( pxTCB->xTaskRunState ); + } + } + #endif /* if ( configNUMBER_OF_CORES > 1 ) */ } else { @@ -5392,106 +6923,237 @@ static void prvResetNextTaskUnblockTime( void ) { mtCOVERAGE_TEST_MARKER(); } + + traceRETURN_vTaskPriorityDisinheritAfterTimeout(); } #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ -/* - * If not in a critical section then yield immediately. - * Otherwise set xYieldPending to true to wait to +#if ( configNUMBER_OF_CORES > 1 ) + +/* If not in a critical section then yield immediately. + * Otherwise set xYieldPendings to true to wait to * yield until exiting the critical section. */ -void vTaskYieldWithinAPI( void ) -{ - if( pxCurrentTCB->uxCriticalNesting == 0U ) + void vTaskYieldWithinAPI( void ) { - portYIELD(); + traceENTER_vTaskYieldWithinAPI(); + + if( portGET_CRITICAL_NESTING_COUNT() == 0U ) + { + portYIELD(); + } + else + { + xYieldPendings[ portGET_CORE_ID() ] = pdTRUE; + } + + traceRETURN_vTaskYieldWithinAPI(); } - else - { - xYieldPendings[ portGET_CORE_ID() ] = pdTRUE; - } -} +#endif /* #if ( configNUMBER_OF_CORES > 1 ) */ + /*-----------------------------------------------------------*/ -#if ( portCRITICAL_NESTING_IN_TCB == 1 ) +#if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) ) void vTaskEnterCritical( void ) { + traceENTER_vTaskEnterCritical(); + portDISABLE_INTERRUPTS(); if( xSchedulerRunning != pdFALSE ) { - if( pxCurrentTCB->uxCriticalNesting == 0U ) - { - if( portCHECK_IF_IN_ISR() == pdFALSE ) - { - portGET_TASK_LOCK(); - } - - portGET_ISR_LOCK(); - } - ( pxCurrentTCB->uxCriticalNesting )++; - /* This should now be interrupt safe. The only time there would be - * a problem is if this is called before a context switch and - * vTaskExitCritical() is called after pxCurrentTCB changes. Therefore - * this should not be used within vTaskSwitchContext(). */ - - if( ( uxSchedulerSuspended == 0U ) && ( pxCurrentTCB->uxCriticalNesting == 1U ) ) + /* This is not the interrupt safe version of the enter critical + * function so assert() if it is being called from an interrupt + * context. Only API functions that end in "FromISR" can be used in an + * interrupt. Only assert if the critical nesting count is 1 to + * protect against recursive calls if the assert function also uses a + * critical section. */ + if( pxCurrentTCB->uxCriticalNesting == 1U ) { - prvCheckForRunStateChange(); + portASSERT_IF_IN_ISR(); } } else { mtCOVERAGE_TEST_MARKER(); } + + traceRETURN_vTaskEnterCritical(); } -#endif /* portCRITICAL_NESTING_IN_TCB */ +#endif /* #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) ) */ /*-----------------------------------------------------------*/ -#if ( portCRITICAL_NESTING_IN_TCB == 1 ) +#if ( configNUMBER_OF_CORES > 1 ) + + void vTaskEnterCritical( void ) + { + traceENTER_vTaskEnterCritical(); + + portDISABLE_INTERRUPTS(); + + if( xSchedulerRunning != pdFALSE ) + { + if( portGET_CRITICAL_NESTING_COUNT() == 0U ) + { + portGET_TASK_LOCK(); + portGET_ISR_LOCK(); + } + + portINCREMENT_CRITICAL_NESTING_COUNT(); + + /* This is not the interrupt safe version of the enter critical + * function so assert() if it is being called from an interrupt + * context. Only API functions that end in "FromISR" can be used in an + * interrupt. Only assert if the critical nesting count is 1 to + * protect against recursive calls if the assert function also uses a + * critical section. */ + if( portGET_CRITICAL_NESTING_COUNT() == 1U ) + { + portASSERT_IF_IN_ISR(); + + if( uxSchedulerSuspended == 0U ) + { + /* The only time there would be a problem is if this is called + * before a context switch and vTaskExitCritical() is called + * after pxCurrentTCB changes. Therefore this should not be + * used within vTaskSwitchContext(). */ + prvCheckForRunStateChange(); + } + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceRETURN_vTaskEnterCritical(); + } + +#endif /* #if ( configNUMBER_OF_CORES > 1 ) */ + +/*-----------------------------------------------------------*/ + +#if ( configNUMBER_OF_CORES > 1 ) + + UBaseType_t vTaskEnterCriticalFromISR( void ) + { + UBaseType_t uxSavedInterruptStatus = 0; + + traceENTER_vTaskEnterCriticalFromISR(); + + if( xSchedulerRunning != pdFALSE ) + { + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + + if( portGET_CRITICAL_NESTING_COUNT() == 0U ) + { + portGET_ISR_LOCK(); + } + + portINCREMENT_CRITICAL_NESTING_COUNT(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceRETURN_vTaskEnterCriticalFromISR( uxSavedInterruptStatus ); + + return uxSavedInterruptStatus; + } + +#endif /* #if ( configNUMBER_OF_CORES > 1 ) */ +/*-----------------------------------------------------------*/ + +#if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) ) void vTaskExitCritical( void ) { + traceENTER_vTaskExitCritical(); + if( xSchedulerRunning != pdFALSE ) { /* If pxCurrentTCB->uxCriticalNesting is zero then this function * does not match a previous call to vTaskEnterCritical(). */ configASSERT( pxCurrentTCB->uxCriticalNesting > 0U ); + /* This function should not be called in ISR. Use vTaskExitCriticalFromISR + * to exit critical section from ISR. */ + portASSERT_IF_IN_ISR(); + if( pxCurrentTCB->uxCriticalNesting > 0U ) { ( pxCurrentTCB->uxCriticalNesting )--; if( pxCurrentTCB->uxCriticalNesting == 0U ) { + portENABLE_INTERRUPTS(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceRETURN_vTaskExitCritical(); + } + +#endif /* #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) ) */ +/*-----------------------------------------------------------*/ + +#if ( configNUMBER_OF_CORES > 1 ) + + void vTaskExitCritical( void ) + { + traceENTER_vTaskExitCritical(); + + if( xSchedulerRunning != pdFALSE ) + { + /* If critical nesting count is zero then this function + * does not match a previous call to vTaskEnterCritical(). */ + configASSERT( portGET_CRITICAL_NESTING_COUNT() > 0U ); + + /* This function should not be called in ISR. Use vTaskExitCriticalFromISR + * to exit critical section from ISR. */ + portASSERT_IF_IN_ISR(); + + if( portGET_CRITICAL_NESTING_COUNT() > 0U ) + { + portDECREMENT_CRITICAL_NESTING_COUNT(); + + if( portGET_CRITICAL_NESTING_COUNT() == 0U ) + { + BaseType_t xYieldCurrentTask; + + /* Get the xYieldPending stats inside the critical section. */ + xYieldCurrentTask = xYieldPendings[ portGET_CORE_ID() ]; + portRELEASE_ISR_LOCK(); + portRELEASE_TASK_LOCK(); + portENABLE_INTERRUPTS(); - if( portCHECK_IF_IN_ISR() == pdFALSE ) + /* When a task yields in a critical section it just sets + * xYieldPending to true. So now that we have exited the + * critical section check if xYieldPending is true, and + * if so yield. */ + if( xYieldCurrentTask != pdFALSE ) { - portRELEASE_TASK_LOCK(); - portENABLE_INTERRUPTS(); - - /* When a task yields in a critical section it just sets - * xYieldPending to true. So now that we have exited the - * critical section check if xYieldPending is true, and - * if so yield. */ - if( xYieldPending != pdFALSE ) - { - portYIELD(); - } - } - else - { - /* In an ISR we don't hold the task lock and don't - * need to yield. Yield will happen if necessary when - * the application ISR calls portEND_SWITCHING_ISR() */ - mtCOVERAGE_TEST_MARKER(); + portYIELD(); } } else @@ -5508,12 +7170,56 @@ void vTaskYieldWithinAPI( void ) { mtCOVERAGE_TEST_MARKER(); } + + traceRETURN_vTaskExitCritical(); } -#endif /* portCRITICAL_NESTING_IN_TCB */ +#endif /* #if ( configNUMBER_OF_CORES > 1 ) */ /*-----------------------------------------------------------*/ -#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) +#if ( configNUMBER_OF_CORES > 1 ) + + void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus ) + { + traceENTER_vTaskExitCriticalFromISR( uxSavedInterruptStatus ); + + if( xSchedulerRunning != pdFALSE ) + { + /* If critical nesting count is zero then this function + * does not match a previous call to vTaskEnterCritical(). */ + configASSERT( portGET_CRITICAL_NESTING_COUNT() > 0U ); + + if( portGET_CRITICAL_NESTING_COUNT() > 0U ) + { + portDECREMENT_CRITICAL_NESTING_COUNT(); + + if( portGET_CRITICAL_NESTING_COUNT() == 0U ) + { + portRELEASE_ISR_LOCK(); + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceRETURN_vTaskExitCriticalFromISR(); + } + +#endif /* #if ( configNUMBER_OF_CORES > 1 ) */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) static char * prvWriteNameToBuffer( char * pcBuffer, const char * pcTaskName ) @@ -5521,11 +7227,11 @@ void vTaskYieldWithinAPI( void ) size_t x; /* Start by copying the entire string. */ - strcpy( pcBuffer, pcTaskName ); + ( void ) strcpy( pcBuffer, pcTaskName ); /* Pad the end of the string with spaces to ensure columns line up when * printed out. */ - for( x = strlen( pcBuffer ); x < ( size_t ) ( configMAX_TASK_NAME_LEN - 1 ); x++ ) + for( x = strlen( pcBuffer ); x < ( size_t ) ( ( size_t ) configMAX_TASK_NAME_LEN - 1U ); x++ ) { pcBuffer[ x ] = ' '; } @@ -5537,17 +7243,24 @@ void vTaskYieldWithinAPI( void ) return &( pcBuffer[ x ] ); } -#endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */ +#endif /* ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */ /*-----------------------------------------------------------*/ -#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) - void vTaskList( char * pcWriteBuffer ) + void vTaskListTasks( char * pcWriteBuffer, + size_t uxBufferLength ) { TaskStatus_t * pxTaskStatusArray; + size_t uxConsumedBufferLength = 0; + size_t uxCharsWrittenBySnprintf; + int iSnprintfReturnValue; + BaseType_t xOutputBufferFull = pdFALSE; UBaseType_t uxArraySize, x; char cStatus; + traceENTER_vTaskListTasks( pcWriteBuffer, uxBufferLength ); + /* * PLEASE NOTE: * @@ -5555,23 +7268,23 @@ void vTaskYieldWithinAPI( void ) * of the demo applications. Do not consider it to be part of the * scheduler. * - * vTaskList() calls uxTaskGetSystemState(), then formats part of the + * vTaskListTasks() calls uxTaskGetSystemState(), then formats part of the * uxTaskGetSystemState() output into a human readable table that * displays task: names, states, priority, stack usage and task number. * 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 sprintf() C library function that + * 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 sprintf() is provided in + * 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(). + * through a call to vTaskListTasks(). */ @@ -5585,7 +7298,10 @@ void vTaskYieldWithinAPI( void ) /* Allocate an array index for each task. NOTE! if * configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will * equate to NULL. */ - pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation allocates a struct that has the alignment requirements of a pointer. */ + /* MISRA Ref 11.5.1 [Malloc memory assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); if( pxTaskStatusArray != NULL ) { @@ -5624,13 +7340,65 @@ void vTaskYieldWithinAPI( void ) break; } - /* Write the task name to the string, padding with spaces so it - * can be printed in tabular form more easily. */ - pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName ); + /* Is there enough space in the buffer to hold task name? */ + if( ( uxConsumedBufferLength + configMAX_TASK_NAME_LEN ) <= uxBufferLength ) + { + /* Write the task name to the string, padding with spaces so it + * can be printed in tabular form more easily. */ + pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName ); + /* Do not count the terminating null character. */ + uxConsumedBufferLength = uxConsumedBufferLength + ( configMAX_TASK_NAME_LEN - 1U ); - /* Write the rest of the string. */ - sprintf( pcWriteBuffer, "\t%c\t%u\t%u\t%u\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */ - pcWriteBuffer += strlen( pcWriteBuffer ); /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */ + /* Is there space left in the buffer? -1 is done because snprintf + * writes a terminating null character. So we are essentially + * checking if the buffer has space to write at least one non-null + * character. */ + if( uxConsumedBufferLength < ( uxBufferLength - 1U ) ) + { + /* Write the rest of the string. */ + #if ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) + /* MISRA Ref 21.6.1 [snprintf for utility] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-216 */ + /* coverity[misra_c_2012_rule_21_6_violation] */ + iSnprintfReturnValue = snprintf( pcWriteBuffer, + uxBufferLength - uxConsumedBufferLength, + "\t%c\t%u\t%u\t%u\t0x%x\r\n", + cStatus, + ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, + ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, + ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber, + ( unsigned int ) pxTaskStatusArray[ x ].uxCoreAffinityMask ); + #else /* ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ + /* MISRA Ref 21.6.1 [snprintf for utility] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-216 */ + /* coverity[misra_c_2012_rule_21_6_violation] */ + iSnprintfReturnValue = snprintf( pcWriteBuffer, + uxBufferLength - uxConsumedBufferLength, + "\t%c\t%u\t%u\t%u\r\n", + cStatus, + ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, + ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, + ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber ); + #endif /* ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ + uxCharsWrittenBySnprintf = prvSnprintfReturnValueToCharsWritten( iSnprintfReturnValue, uxBufferLength - uxConsumedBufferLength ); + + uxConsumedBufferLength += uxCharsWrittenBySnprintf; + pcWriteBuffer += uxCharsWrittenBySnprintf; + } + else + { + xOutputBufferFull = pdTRUE; + } + } + else + { + xOutputBufferFull = pdTRUE; + } + + if( xOutputBufferFull == pdTRUE ) + { + break; + } } /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION @@ -5641,24 +7409,28 @@ void vTaskYieldWithinAPI( void ) { mtCOVERAGE_TEST_MARKER(); } + + traceRETURN_vTaskListTasks(); } -#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */ +#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */ /*----------------------------------------------------------*/ -#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) +#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configUSE_TRACE_FACILITY == 1 ) ) - void vTaskGetRunTimeStats( char * pcWriteBuffer ) + void vTaskGetRunTimeStatistics( char * pcWriteBuffer, + size_t uxBufferLength ) { TaskStatus_t * pxTaskStatusArray; + size_t uxConsumedBufferLength = 0; + size_t uxCharsWrittenBySnprintf; + int iSnprintfReturnValue; + BaseType_t xOutputBufferFull = pdFALSE; UBaseType_t uxArraySize, x; - uint32_t ulTotalTime, ulStatsAsPercentage; + configRUN_TIME_COUNTER_TYPE ulTotalTime = 0; + configRUN_TIME_COUNTER_TYPE ulStatsAsPercentage; - #if ( configUSE_TRACE_FACILITY != 1 ) - { - #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats(). - } - #endif + traceENTER_vTaskGetRunTimeStatistics( pcWriteBuffer, uxBufferLength ); /* * PLEASE NOTE: @@ -5667,22 +7439,22 @@ void vTaskYieldWithinAPI( void ) * of the demo applications. Do not consider it to be part of the * scheduler. * - * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part + * 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. * - * vTaskGetRunTimeStats() has a dependency on the sprintf() C library + * 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 - * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in + * 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(). + * through a call to vTaskGetRunTimeStatistics(). */ /* Make sure the write buffer does not contain a string. */ @@ -5695,7 +7467,10 @@ void vTaskYieldWithinAPI( void ) /* Allocate an array index for each task. NOTE! If * configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will * equate to NULL. */ - pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation allocates a struct that has the alignment requirements of a pointer. */ + /* MISRA Ref 11.5.1 [Malloc memory assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); if( pxTaskStatusArray != NULL ) { @@ -5703,7 +7478,7 @@ void vTaskYieldWithinAPI( void ) uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime ); /* For percentage calculations. */ - ulTotalTime /= 100UL; + ulTotalTime /= ( ( configRUN_TIME_COUNTER_TYPE ) 100UL ); /* Avoid divide by zero errors. */ if( ulTotalTime > 0UL ) @@ -5713,46 +7488,100 @@ void vTaskYieldWithinAPI( void ) { /* 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. */ + * ulTotalRunTime has already been divided by 100. */ ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime; - /* Write the task name to the string, padding with - * spaces so it can be printed in tabular form more - * easily. */ - pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName ); - - if( ulStatsAsPercentage > 0UL ) + /* Is there enough space in the buffer to hold task name? */ + if( ( uxConsumedBufferLength + configMAX_TASK_NAME_LEN ) <= uxBufferLength ) { - #ifdef portLU_PRINTF_SPECIFIER_REQUIRED + /* Write the task name to the string, padding with + * spaces so it can be printed in tabular form more + * easily. */ + pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName ); + /* Do not count the terminating null character. */ + uxConsumedBufferLength = uxConsumedBufferLength + ( configMAX_TASK_NAME_LEN - 1U ); + + /* Is there space left in the buffer? -1 is done because snprintf + * writes a terminating null character. So we are essentially + * checking if the buffer has space to write at least one non-null + * character. */ + if( uxConsumedBufferLength < ( uxBufferLength - 1U ) ) + { + if( ulStatsAsPercentage > 0UL ) { - sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); + #ifdef portLU_PRINTF_SPECIFIER_REQUIRED + { + /* MISRA Ref 21.6.1 [snprintf for utility] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-216 */ + /* coverity[misra_c_2012_rule_21_6_violation] */ + iSnprintfReturnValue = snprintf( pcWriteBuffer, + uxBufferLength - uxConsumedBufferLength, + "\t%lu\t\t%lu%%\r\n", + pxTaskStatusArray[ x ].ulRunTimeCounter, + ulStatsAsPercentage ); + } + #else /* ifdef portLU_PRINTF_SPECIFIER_REQUIRED */ + { + /* sizeof( int ) == sizeof( long ) so a smaller + * printf() library can be used. */ + /* MISRA Ref 21.6.1 [snprintf for utility] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-216 */ + /* coverity[misra_c_2012_rule_21_6_violation] */ + iSnprintfReturnValue = snprintf( pcWriteBuffer, + uxBufferLength - uxConsumedBufferLength, + "\t%u\t\t%u%%\r\n", + ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, + ( unsigned int ) ulStatsAsPercentage ); + } + #endif /* ifdef portLU_PRINTF_SPECIFIER_REQUIRED */ } - #else + else { - /* sizeof( int ) == sizeof( long ) so a smaller - * printf() library can be used. */ - sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */ + /* If the percentage is zero here then the task has + * consumed less than 1% of the total run time. */ + #ifdef portLU_PRINTF_SPECIFIER_REQUIRED + { + /* MISRA Ref 21.6.1 [snprintf for utility] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-216 */ + /* coverity[misra_c_2012_rule_21_6_violation] */ + iSnprintfReturnValue = snprintf( pcWriteBuffer, + uxBufferLength - uxConsumedBufferLength, + "\t%lu\t\t<1%%\r\n", + pxTaskStatusArray[ x ].ulRunTimeCounter ); + } + #else + { + /* sizeof( int ) == sizeof( long ) so a smaller + * printf() library can be used. */ + /* MISRA Ref 21.6.1 [snprintf for utility] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-216 */ + /* coverity[misra_c_2012_rule_21_6_violation] */ + iSnprintfReturnValue = snprintf( pcWriteBuffer, + uxBufferLength - uxConsumedBufferLength, + "\t%u\t\t<1%%\r\n", + ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); + } + #endif /* ifdef portLU_PRINTF_SPECIFIER_REQUIRED */ } - #endif + + uxCharsWrittenBySnprintf = prvSnprintfReturnValueToCharsWritten( iSnprintfReturnValue, uxBufferLength - uxConsumedBufferLength ); + uxConsumedBufferLength += uxCharsWrittenBySnprintf; + pcWriteBuffer += uxCharsWrittenBySnprintf; + } + else + { + xOutputBufferFull = pdTRUE; + } } else { - /* If the percentage is zero here then the task has - * consumed less than 1% of the total run time. */ - #ifdef portLU_PRINTF_SPECIFIER_REQUIRED - { - sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter ); - } - #else - { - /* sizeof( int ) == sizeof( long ) so a smaller - * printf() library can be used. */ - sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */ - } - #endif + xOutputBufferFull = pdTRUE; } - pcWriteBuffer += strlen( pcWriteBuffer ); /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */ + if( xOutputBufferFull == pdTRUE ) + { + break; + } } } else @@ -5768,20 +7597,26 @@ void vTaskYieldWithinAPI( void ) { mtCOVERAGE_TEST_MARKER(); } + + traceRETURN_vTaskGetRunTimeStatistics(); } -#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) */ +#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */ /*-----------------------------------------------------------*/ TickType_t uxTaskResetEventItemValue( void ) { TickType_t uxReturn; + traceENTER_uxTaskResetEventItemValue(); + uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) ); /* Reset the event list item to its normal value - so it can be used with * queues and semaphores. */ - listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ) ); + + traceRETURN_uxTaskResetEventItemValue( uxReturn ); return uxReturn; } @@ -5791,14 +7626,22 @@ TickType_t uxTaskResetEventItemValue( void ) TaskHandle_t pvTaskIncrementMutexHeldCount( void ) { + TCB_t * pxTCB; + + traceENTER_pvTaskIncrementMutexHeldCount(); + + pxTCB = pxCurrentTCB; + /* If xSemaphoreCreateMutex() is called before any tasks have been created * then pxCurrentTCB will be NULL. */ - if( pxCurrentTCB != NULL ) + if( pxTCB != NULL ) { - ( pxCurrentTCB->uxMutexesHeld )++; + ( pxTCB->uxMutexesHeld )++; } - return pxCurrentTCB; + traceRETURN_pvTaskIncrementMutexHeldCount( pxTCB ); + + return pxTCB; } #endif /* configUSE_MUTEXES */ @@ -5806,32 +7649,74 @@ TickType_t uxTaskResetEventItemValue( void ) #if ( configUSE_TASK_NOTIFICATIONS == 1 ) - uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWait, + uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) { uint32_t ulReturn; + BaseType_t xAlreadyYielded; - configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES ); + traceENTER_ulTaskGenericNotifyTake( uxIndexToWaitOn, xClearCountOnExit, xTicksToWait ); + + configASSERT( uxIndexToWaitOn < configTASK_NOTIFICATION_ARRAY_ENTRIES ); taskENTER_CRITICAL(); + + /* Only block if the notification count is not already non-zero. */ + if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] == 0UL ) { - /* Only block if the notification count is not already non-zero. */ - if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] == 0UL ) + /* Mark this task as waiting for a notification. */ + pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskWAITING_NOTIFICATION; + + if( xTicksToWait > ( TickType_t ) 0 ) { - /* Mark this task as waiting for a notification. */ - pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION; + traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWaitOn ); - if( xTicksToWait > ( TickType_t ) 0 ) + /* We MUST suspend the scheduler before exiting the critical + * section (i.e. before enabling interrupts). + * + * If we do not do so, a notification sent from an ISR, which + * happens after exiting the critical section and before + * suspending the scheduler, will get lost. The sequence of + * events will be: + * 1. Exit critical section. + * 2. Interrupt - ISR calls xTaskNotifyFromISR which adds the + * task to the Ready list. + * 3. Suspend scheduler. + * 4. prvAddCurrentTaskToDelayedList moves the task to the + * delayed or suspended list. + * 5. Resume scheduler does not touch the task (because it is + * not on the pendingReady list), effectively losing the + * notification from the ISR. + * + * The same does not happen when we suspend the scheduler before + * exiting the critical section. The sequence of events in this + * case will be: + * 1. Suspend scheduler. + * 2. Exit critical section. + * 3. Interrupt - ISR calls xTaskNotifyFromISR which adds the + * task to the pendingReady list as the scheduler is + * suspended. + * 4. prvAddCurrentTaskToDelayedList adds the task to delayed or + * suspended list. Note that this operation does not nullify + * the add to pendingReady list done in the above step because + * a different list item, namely xEventListItem, is used for + * adding the task to the pendingReady list. In other words, + * the task still remains on the pendingReady list. + * 5. Resume scheduler moves the task from pendingReady list to + * the Ready list. + */ + vTaskSuspendAll(); { - prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); - traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWait ); + taskEXIT_CRITICAL(); - /* All ports are written to allow a yield in a critical - * section (some will yield immediately, others wait until the - * critical section exits) - but it is not something that - * application code should ever do. */ - vTaskYieldWithinAPI(); + prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); + } + xAlreadyYielded = xTaskResumeAll(); + + if( xAlreadyYielded == pdFALSE ) + { + taskYIELD_WITHIN_API(); } else { @@ -5840,25 +7725,28 @@ TickType_t uxTaskResetEventItemValue( void ) } else { - mtCOVERAGE_TEST_MARKER(); + taskEXIT_CRITICAL(); } } - taskEXIT_CRITICAL(); + else + { + taskEXIT_CRITICAL(); + } taskENTER_CRITICAL(); { - traceTASK_NOTIFY_TAKE( uxIndexToWait ); - ulReturn = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ]; + traceTASK_NOTIFY_TAKE( uxIndexToWaitOn ); + ulReturn = pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ]; if( ulReturn != 0UL ) { if( xClearCountOnExit != pdFALSE ) { - pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = 0UL; + pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] = ( uint32_t ) 0UL; } else { - pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = ulReturn - ( uint32_t ) 1; + pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] = ulReturn - ( uint32_t ) 1; } } else @@ -5866,10 +7754,12 @@ TickType_t uxTaskResetEventItemValue( void ) mtCOVERAGE_TEST_MARKER(); } - pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION; + pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskNOT_WAITING_NOTIFICATION; } taskEXIT_CRITICAL(); + traceRETURN_ulTaskGenericNotifyTake( ulReturn ); + return ulReturn; } @@ -5878,39 +7768,80 @@ TickType_t uxTaskResetEventItemValue( void ) #if ( configUSE_TASK_NOTIFICATIONS == 1 ) - BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWait, + BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t * pulNotificationValue, TickType_t xTicksToWait ) { - BaseType_t xReturn; + BaseType_t xReturn, xAlreadyYielded; - configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES ); + traceENTER_xTaskGenericNotifyWait( uxIndexToWaitOn, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ); + + configASSERT( uxIndexToWaitOn < configTASK_NOTIFICATION_ARRAY_ENTRIES ); taskENTER_CRITICAL(); + + /* Only block if a notification is not already pending. */ + if( pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] != taskNOTIFICATION_RECEIVED ) { - /* Only block if a notification is not already pending. */ - if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED ) + /* Clear bits in the task's notification value as bits may get + * set by the notifying task or interrupt. This can be used to + * clear the value to zero. */ + pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] &= ~ulBitsToClearOnEntry; + + /* Mark this task as waiting for a notification. */ + pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskWAITING_NOTIFICATION; + + if( xTicksToWait > ( TickType_t ) 0 ) { - /* Clear bits in the task's notification value as bits may get - * set by the notifying task or interrupt. This can be used to - * clear the value to zero. */ - pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnEntry; + traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWaitOn ); - /* Mark this task as waiting for a notification. */ - pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION; - - if( xTicksToWait > ( TickType_t ) 0 ) + /* We MUST suspend the scheduler before exiting the critical + * section (i.e. before enabling interrupts). + * + * If we do not do so, a notification sent from an ISR, which + * happens after exiting the critical section and before + * suspending the scheduler, will get lost. The sequence of + * events will be: + * 1. Exit critical section. + * 2. Interrupt - ISR calls xTaskNotifyFromISR which adds the + * task to the Ready list. + * 3. Suspend scheduler. + * 4. prvAddCurrentTaskToDelayedList moves the task to the + * delayed or suspended list. + * 5. Resume scheduler does not touch the task (because it is + * not on the pendingReady list), effectively losing the + * notification from the ISR. + * + * The same does not happen when we suspend the scheduler before + * exiting the critical section. The sequence of events in this + * case will be: + * 1. Suspend scheduler. + * 2. Exit critical section. + * 3. Interrupt - ISR calls xTaskNotifyFromISR which adds the + * task to the pendingReady list as the scheduler is + * suspended. + * 4. prvAddCurrentTaskToDelayedList adds the task to delayed or + * suspended list. Note that this operation does not nullify + * the add to pendingReady list done in the above step because + * a different list item, namely xEventListItem, is used for + * adding the task to the pendingReady list. In other words, + * the task still remains on the pendingReady list. + * 5. Resume scheduler moves the task from pendingReady list to + * the Ready list. + */ + vTaskSuspendAll(); { - prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); - traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWait ); + taskEXIT_CRITICAL(); - /* All ports are written to allow a yield in a critical - * section (some will yield immediately, others wait until the - * critical section exits) - but it is not something that - * application code should ever do. */ - vTaskYieldWithinAPI(); + prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); + } + xAlreadyYielded = xTaskResumeAll(); + + if( xAlreadyYielded == pdFALSE ) + { + taskYIELD_WITHIN_API(); } else { @@ -5919,27 +7850,30 @@ TickType_t uxTaskResetEventItemValue( void ) } else { - mtCOVERAGE_TEST_MARKER(); + taskEXIT_CRITICAL(); } } - taskEXIT_CRITICAL(); + else + { + taskEXIT_CRITICAL(); + } taskENTER_CRITICAL(); { - traceTASK_NOTIFY_WAIT( uxIndexToWait ); + traceTASK_NOTIFY_WAIT( uxIndexToWaitOn ); if( pulNotificationValue != NULL ) { /* Output the current notification value, which may or may not * have changed. */ - *pulNotificationValue = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ]; + *pulNotificationValue = pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ]; } /* If ucNotifyValue is set then either the task never entered the * blocked state (because a notification was already pending) or the * task unblocked because of a notification. Otherwise the task * unblocked because of a timeout. */ - if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED ) + if( pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] != taskNOTIFICATION_RECEIVED ) { /* A notification was not received. */ xReturn = pdFALSE; @@ -5948,14 +7882,16 @@ TickType_t uxTaskResetEventItemValue( void ) { /* A notification was already pending or a notification was * received while the task was waiting. */ - pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnExit; + pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] &= ~ulBitsToClearOnExit; xReturn = pdTRUE; } - pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION; + pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskNOT_WAITING_NOTIFICATION; } taskEXIT_CRITICAL(); + traceRETURN_xTaskGenericNotifyWait( xReturn ); + return xReturn; } @@ -5974,6 +7910,8 @@ TickType_t uxTaskResetEventItemValue( void ) BaseType_t xReturn = pdPASS; uint8_t ucOriginalNotifyState; + traceENTER_xTaskGenericNotify( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue ); + configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES ); configASSERT( xTaskToNotify ); pxTCB = xTaskToNotify; @@ -6039,33 +7977,31 @@ TickType_t uxTaskResetEventItemValue( void ) * notification then unblock it now. */ if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) { - ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + listREMOVE_ITEM( &( pxTCB->xStateListItem ) ); prvAddTaskToReadyList( pxTCB ); /* The task should not have been on an event list. */ configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); #if ( configUSE_TICKLESS_IDLE != 0 ) - { - /* If a task is blocked waiting for a notification then - * xNextTaskUnblockTime might be set to the blocked task's time - * out time. If the task is unblocked for a reason other than - * a timeout xNextTaskUnblockTime is normally left unchanged, - * because it will automatically get reset to a new value when - * the tick count equals xNextTaskUnblockTime. However if - * tickless idling is used it might be more important to enter - * sleep mode at the earliest possible time - so reset - * xNextTaskUnblockTime here to ensure it is updated at the - * earliest possible time. */ - prvResetNextTaskUnblockTime(); - } + { + /* If a task is blocked waiting for a notification then + * xNextTaskUnblockTime might be set to the blocked task's time + * out time. If the task is unblocked for a reason other than + * a timeout xNextTaskUnblockTime is normally left unchanged, + * because it will automatically get reset to a new value when + * the tick count equals xNextTaskUnblockTime. However if + * tickless idling is used it might be more important to enter + * sleep mode at the earliest possible time - so reset + * xNextTaskUnblockTime here to ensure it is updated at the + * earliest possible time. */ + prvResetNextTaskUnblockTime(); + } #endif - #if ( configUSE_PREEMPTION == 1 ) - { - prvYieldForTask( pxTCB, pdFALSE ); - } - #endif + /* Check if the notified task has a priority above the currently + * executing task. */ + taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB ); } else { @@ -6074,6 +8010,8 @@ TickType_t uxTaskResetEventItemValue( void ) } taskEXIT_CRITICAL(); + traceRETURN_xTaskGenericNotify( xReturn ); + return xReturn; } @@ -6094,6 +8032,8 @@ TickType_t uxTaskResetEventItemValue( void ) BaseType_t xReturn = pdPASS; UBaseType_t uxSavedInterruptStatus; + traceENTER_xTaskGenericNotifyFromISR( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ); + configASSERT( xTaskToNotify ); configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES ); @@ -6117,7 +8057,7 @@ TickType_t uxTaskResetEventItemValue( void ) pxTCB = xTaskToNotify; - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); { if( pulPreviousNotificationValue != NULL ) { @@ -6179,32 +8119,61 @@ TickType_t uxTaskResetEventItemValue( void ) /* The task should not have been on an event list. */ configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); - if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + if( uxSchedulerSuspended == ( UBaseType_t ) 0U ) { - ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + listREMOVE_ITEM( &( pxTCB->xStateListItem ) ); prvAddTaskToReadyList( pxTCB ); } else { /* The delayed and ready lists cannot be accessed, so hold * this task pending until the scheduler is resumed. */ - vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); + listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); } - #if ( configUSE_PREEMPTION == 1 ) - prvYieldForTask( pxTCB, pdFALSE ); - - if( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) + #if ( configNUMBER_OF_CORES == 1 ) + { + if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) { + /* The notified task has a priority above the currently + * executing task so a yield is required. */ if( pxHigherPriorityTaskWoken != NULL ) { *pxHigherPriorityTaskWoken = pdTRUE; } + + /* Mark that a yield is pending in case the user is not + * using the "xHigherPriorityTaskWoken" parameter to an ISR + * safe FreeRTOS function. */ + xYieldPendings[ 0 ] = pdTRUE; } - #endif + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #else /* #if ( configNUMBER_OF_CORES == 1 ) */ + { + #if ( configUSE_PREEMPTION == 1 ) + { + prvYieldForTask( pxTCB ); + + if( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) + { + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + } + } + #endif /* if ( configUSE_PREEMPTION == 1 ) */ + } + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ } } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); + + traceRETURN_xTaskGenericNotifyFromISR( xReturn ); return xReturn; } @@ -6222,6 +8191,8 @@ TickType_t uxTaskResetEventItemValue( void ) uint8_t ucOriginalNotifyState; UBaseType_t uxSavedInterruptStatus; + traceENTER_vTaskGenericNotifyGiveFromISR( xTaskToNotify, uxIndexToNotify, pxHigherPriorityTaskWoken ); + configASSERT( xTaskToNotify ); configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES ); @@ -6245,7 +8216,7 @@ TickType_t uxTaskResetEventItemValue( void ) pxTCB = xTaskToNotify; - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); { ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ]; pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED; @@ -6263,32 +8234,61 @@ TickType_t uxTaskResetEventItemValue( void ) /* The task should not have been on an event list. */ configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); - if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + if( uxSchedulerSuspended == ( UBaseType_t ) 0U ) { - ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + listREMOVE_ITEM( &( pxTCB->xStateListItem ) ); prvAddTaskToReadyList( pxTCB ); } else { /* The delayed and ready lists cannot be accessed, so hold * this task pending until the scheduler is resumed. */ - vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); + listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); } - #if ( configUSE_PREEMPTION == 1 ) - prvYieldForTask( pxTCB, pdFALSE ); - - if( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) + #if ( configNUMBER_OF_CORES == 1 ) + { + if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) { + /* The notified task has a priority above the currently + * executing task so a yield is required. */ if( pxHigherPriorityTaskWoken != NULL ) { *pxHigherPriorityTaskWoken = pdTRUE; } + + /* Mark that a yield is pending in case the user is not + * using the "xHigherPriorityTaskWoken" parameter in an ISR + * safe FreeRTOS function. */ + xYieldPendings[ 0 ] = pdTRUE; } - #endif + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #else /* #if ( configNUMBER_OF_CORES == 1 ) */ + { + #if ( configUSE_PREEMPTION == 1 ) + { + prvYieldForTask( pxTCB ); + + if( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) + { + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + } + } + #endif /* #if ( configUSE_PREEMPTION == 1 ) */ + } + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ } } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); + + traceRETURN_vTaskGenericNotifyGiveFromISR(); } #endif /* configUSE_TASK_NOTIFICATIONS */ @@ -6302,6 +8302,8 @@ TickType_t uxTaskResetEventItemValue( void ) TCB_t * pxTCB; BaseType_t xReturn; + traceENTER_xTaskGenericNotifyStateClear( xTask, uxIndexToClear ); + configASSERT( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES ); /* If null is passed in here then it is the calling task that is having @@ -6322,6 +8324,8 @@ TickType_t uxTaskResetEventItemValue( void ) } taskEXIT_CRITICAL(); + traceRETURN_xTaskGenericNotifyStateClear( xReturn ); + return xReturn; } @@ -6337,6 +8341,10 @@ TickType_t uxTaskResetEventItemValue( void ) TCB_t * pxTCB; uint32_t ulReturn; + traceENTER_ulTaskGenericNotifyValueClear( xTask, uxIndexToClear, ulBitsToClear ); + + configASSERT( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES ); + /* If null is passed in here then it is the calling task that is having * its notification state cleared. */ pxTCB = prvGetTCBFromHandle( xTask ); @@ -6350,23 +8358,119 @@ TickType_t uxTaskResetEventItemValue( void ) } taskEXIT_CRITICAL(); + traceRETURN_ulTaskGenericNotifyValueClear( ulReturn ); + return ulReturn; } #endif /* configUSE_TASK_NOTIFICATIONS */ /*-----------------------------------------------------------*/ +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimeCounter( const TaskHandle_t xTask ) + { + TCB_t * pxTCB; + + traceENTER_ulTaskGetRunTimeCounter( xTask ); + + pxTCB = prvGetTCBFromHandle( xTask ); + + traceRETURN_ulTaskGetRunTimeCounter( pxTCB->ulRunTimeCounter ); + + return pxTCB->ulRunTimeCounter; + } + +#endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */ +/*-----------------------------------------------------------*/ + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent( const TaskHandle_t xTask ) + { + TCB_t * pxTCB; + configRUN_TIME_COUNTER_TYPE ulTotalTime, ulReturn; + + traceENTER_ulTaskGetRunTimePercent( xTask ); + + ulTotalTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE(); + + /* For percentage calculations. */ + ulTotalTime /= ( configRUN_TIME_COUNTER_TYPE ) 100; + + /* Avoid divide by zero errors. */ + if( ulTotalTime > ( configRUN_TIME_COUNTER_TYPE ) 0 ) + { + pxTCB = prvGetTCBFromHandle( xTask ); + ulReturn = pxTCB->ulRunTimeCounter / ulTotalTime; + } + else + { + ulReturn = 0; + } + + traceRETURN_ulTaskGetRunTimePercent( ulReturn ); + + return ulReturn; + } + +#endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */ +/*-----------------------------------------------------------*/ + #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) - uint32_t ulTaskGetIdleRunTimeCounter( void ) + configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ) { - uint32_t ulReturn = 0; + configRUN_TIME_COUNTER_TYPE ulReturn = 0; + BaseType_t i; - for( BaseType_t i = 0; i < configNUM_CORES; i++ ) + traceENTER_ulTaskGetIdleRunTimeCounter(); + + for( i = 0; i < ( BaseType_t ) configNUMBER_OF_CORES; i++ ) { - ulReturn += xIdleTaskHandle[ i ]->ulRunTimeCounter; + ulReturn += xIdleTaskHandles[ i ]->ulRunTimeCounter; } + traceRETURN_ulTaskGetIdleRunTimeCounter( ulReturn ); + + return ulReturn; + } + +#endif /* if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */ +/*-----------------------------------------------------------*/ + +#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) + + configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ) + { + configRUN_TIME_COUNTER_TYPE ulTotalTime, ulReturn; + configRUN_TIME_COUNTER_TYPE ulRunTimeCounter = 0; + BaseType_t i; + + traceENTER_ulTaskGetIdleRunTimePercent(); + + ulTotalTime = portGET_RUN_TIME_COUNTER_VALUE() * configNUMBER_OF_CORES; + + /* For percentage calculations. */ + ulTotalTime /= ( configRUN_TIME_COUNTER_TYPE ) 100; + + /* Avoid divide by zero errors. */ + if( ulTotalTime > ( configRUN_TIME_COUNTER_TYPE ) 0 ) + { + for( i = 0; i < ( BaseType_t ) configNUMBER_OF_CORES; i++ ) + { + ulRunTimeCounter += xIdleTaskHandles[ i ]->ulRunTimeCounter; + } + + ulReturn = ulRunTimeCounter / ulTotalTime; + } + else + { + ulReturn = 0; + } + + traceRETURN_ulTaskGetIdleRunTimePercent( ulReturn ); + return ulReturn; } @@ -6378,14 +8482,16 @@ static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, { TickType_t xTimeToWake; const TickType_t xConstTickCount = xTickCount; + List_t * const pxDelayedList = pxDelayedTaskList; + List_t * const pxOverflowDelayedList = pxOverflowDelayedTaskList; #if ( INCLUDE_xTaskAbortDelay == 1 ) - { - /* About to enter a delayed list, so ensure the ucDelayAborted flag is - * reset to pdFALSE so it can be detected as having been set to pdTRUE - * when the task leaves the Blocked state. */ - pxCurrentTCB->ucDelayAborted = pdFALSE; - } + { + /* About to enter a delayed list, so ensure the ucDelayAborted flag is + * reset to pdFALSE so it can be detected as having been set to pdTRUE + * when the task leaves the Blocked state. */ + pxCurrentTCB->ucDelayAborted = pdFALSE; + } #endif /* Remove the task from the ready list before adding it to the blocked list @@ -6394,7 +8500,7 @@ static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, { /* The current task must be in a ready list, so there is no need to * check, and the port reset macro can be called directly. */ - portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); /*lint !e931 pxCurrentTCB cannot change as it is the calling task. pxCurrentTCB->uxPriority and uxTopReadyPriority cannot change as called with scheduler suspended or in a critical section. */ + portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); } else { @@ -6402,55 +8508,19 @@ static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, } #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) ) { - if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) ) - { - /* Add the task to the suspended task list instead of a delayed task - * list to ensure it is not woken by a timing event. It will block - * indefinitely. */ - vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) ); - } - else - { - /* Calculate the time at which the task should be woken if the event - * does not occur. This may overflow but this doesn't matter, the - * kernel will manage it correctly. */ - xTimeToWake = xConstTickCount + xTicksToWait; - - /* The list item will be inserted in wake time order. */ - listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake ); - - if( xTimeToWake < xConstTickCount ) - { - /* Wake time has overflowed. Place this item in the overflow - * list. */ - vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) ); - } - else - { - /* The wake time has not overflowed, so the current block list - * is used. */ - vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) ); - - /* If the task entering the blocked state was placed at the - * head of the list of blocked tasks then xNextTaskUnblockTime - * needs to be updated too. */ - if( xTimeToWake < xNextTaskUnblockTime ) - { - xNextTaskUnblockTime = xTimeToWake; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } + /* Add the task to the suspended task list instead of a delayed task + * list to ensure it is not woken by a timing event. It will block + * indefinitely. */ + listINSERT_END( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) ); } - #else /* INCLUDE_vTaskSuspend */ + else { /* Calculate the time at which the task should be woken if the event - * does not occur. This may overflow but this doesn't matter, the kernel - * will manage it correctly. */ + * does not occur. This may overflow but this doesn't matter, the + * kernel will manage it correctly. */ xTimeToWake = xConstTickCount + xTicksToWait; /* The list item will be inserted in wake time order. */ @@ -6458,17 +8528,21 @@ static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, if( xTimeToWake < xConstTickCount ) { - /* Wake time has overflowed. Place this item in the overflow list. */ - vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) ); + /* Wake time has overflowed. Place this item in the overflow + * list. */ + traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST(); + vListInsert( pxOverflowDelayedList, &( pxCurrentTCB->xStateListItem ) ); } else { - /* The wake time has not overflowed, so the current block list is used. */ - vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) ); + /* The wake time has not overflowed, so the current block list + * is used. */ + traceMOVED_TASK_TO_DELAYED_LIST(); + vListInsert( pxDelayedList, &( pxCurrentTCB->xStateListItem ) ); - /* If the task entering the blocked state was placed at the head of the - * list of blocked tasks then xNextTaskUnblockTime needs to be updated - * too. */ + /* If the task entering the blocked state was placed at the + * head of the list of blocked tasks then xNextTaskUnblockTime + * needs to be updated too. */ if( xTimeToWake < xNextTaskUnblockTime ) { xNextTaskUnblockTime = xTimeToWake; @@ -6478,12 +8552,67 @@ static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, mtCOVERAGE_TEST_MARKER(); } } - - /* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */ - ( void ) xCanBlockIndefinitely; } + } + #else /* INCLUDE_vTaskSuspend */ + { + /* Calculate the time at which the task should be woken if the event + * does not occur. This may overflow but this doesn't matter, the kernel + * will manage it correctly. */ + xTimeToWake = xConstTickCount + xTicksToWait; + + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake ); + + if( xTimeToWake < xConstTickCount ) + { + traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST(); + /* Wake time has overflowed. Place this item in the overflow list. */ + vListInsert( pxOverflowDelayedList, &( pxCurrentTCB->xStateListItem ) ); + } + else + { + traceMOVED_TASK_TO_DELAYED_LIST(); + /* The wake time has not overflowed, so the current block list is used. */ + vListInsert( pxDelayedList, &( pxCurrentTCB->xStateListItem ) ); + + /* If the task entering the blocked state was placed at the head of the + * list of blocked tasks then xNextTaskUnblockTime needs to be updated + * too. */ + if( xTimeToWake < xNextTaskUnblockTime ) + { + xNextTaskUnblockTime = xTimeToWake; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + /* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */ + ( void ) xCanBlockIndefinitely; + } #endif /* INCLUDE_vTaskSuspend */ } +/*-----------------------------------------------------------*/ + +#if ( portUSING_MPU_WRAPPERS == 1 ) + + xMPU_SETTINGS * xTaskGetMPUSettings( TaskHandle_t xTask ) + { + TCB_t * pxTCB; + + traceENTER_xTaskGetMPUSettings( xTask ); + + pxTCB = prvGetTCBFromHandle( xTask ); + + traceRETURN_xTaskGetMPUSettings( &( pxTCB->xMPUSettings ) ); + + return &( pxTCB->xMPUSettings ); + } + +#endif /* portUSING_MPU_WRAPPERS */ +/*-----------------------------------------------------------*/ /* Code below here allows additional code to be inserted into this source file, * especially where access to file scope functions and data is needed (for example @@ -6506,3 +8635,69 @@ static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, #endif #endif /* if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 ) */ +/*-----------------------------------------------------------*/ + +#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configKERNEL_PROVIDED_STATIC_MEMORY == 1 ) && ( portUSING_MPU_WRAPPERS == 0 ) ) + +/* + * This is the kernel provided implementation of vApplicationGetIdleTaskMemory() + * to provide the memory that is used by the Idle task. It is used when + * configKERNEL_PROVIDED_STATIC_MEMORY is set to 1. The application can provide + * it's own implementation of vApplicationGetIdleTaskMemory by setting + * configKERNEL_PROVIDED_STATIC_MEMORY to 0 or leaving it undefined. + */ + void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, + StackType_t ** ppxIdleTaskStackBuffer, + uint32_t * pulIdleTaskStackSize ) + { + static StaticTask_t xIdleTaskTCB; + static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; + + *ppxIdleTaskTCBBuffer = &( xIdleTaskTCB ); + *ppxIdleTaskStackBuffer = &( uxIdleTaskStack[ 0 ] ); + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; + } + + #if ( configNUMBER_OF_CORES > 1 ) + + void vApplicationGetPassiveIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, + StackType_t ** ppxIdleTaskStackBuffer, + uint32_t * pulIdleTaskStackSize, + BaseType_t xPassiveIdleTaskIndex ) + { + static StaticTask_t xIdleTaskTCBs[ configNUMBER_OF_CORES - 1 ]; + static StackType_t uxIdleTaskStacks[ configNUMBER_OF_CORES - 1 ][ configMINIMAL_STACK_SIZE ]; + + *ppxIdleTaskTCBBuffer = &( xIdleTaskTCBs[ xPassiveIdleTaskIndex ] ); + *ppxIdleTaskStackBuffer = &( uxIdleTaskStacks[ xPassiveIdleTaskIndex ][ 0 ] ); + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; + } + + #endif /* #if ( configNUMBER_OF_CORES > 1 ) */ + +#endif /* #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configKERNEL_PROVIDED_STATIC_MEMORY == 1 ) && ( portUSING_MPU_WRAPPERS == 0 ) ) */ +/*-----------------------------------------------------------*/ + +#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configKERNEL_PROVIDED_STATIC_MEMORY == 1 ) && ( portUSING_MPU_WRAPPERS == 0 ) ) + +/* + * This is the kernel provided implementation of vApplicationGetTimerTaskMemory() + * to provide the memory that is used by the Timer service task. It is used when + * configKERNEL_PROVIDED_STATIC_MEMORY is set to 1. The application can provide + * it's own implementation of vApplicationGetTimerTaskMemory by setting + * configKERNEL_PROVIDED_STATIC_MEMORY to 0 or leaving it undefined. + */ + void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, + StackType_t ** ppxTimerTaskStackBuffer, + uint32_t * pulTimerTaskStackSize ) + { + static StaticTask_t xTimerTaskTCB; + static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; + + *ppxTimerTaskTCBBuffer = &( xTimerTaskTCB ); + *ppxTimerTaskStackBuffer = &( uxTimerTaskStack[ 0 ] ); + *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; + } + +#endif /* #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configKERNEL_PROVIDED_STATIC_MEMORY == 1 ) && ( portUSING_MPU_WRAPPERS == 0 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/timers.c b/components/freertos/FreeRTOS-Kernel-SMP/timers.c index b98e9b9ec9..3f94e15764 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/timers.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/timers.c @@ -1,6 +1,12 @@ /* - * FreeRTOS SMP Kernel V202110.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V11.0.1 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-FileCopyrightText: 2021 Amazon.com, Inc. or its affiliates + * + * SPDX-License-Identifier: MIT + * + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -41,11 +47,10 @@ #error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available. #endif -/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified - * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined +/* The MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined * for the header files above, but not in this file, in order to generate the * correct privileged Vs unprivileged linkage and placement. */ -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e9021 !e961 !e750. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /* This entire source file will be skipped if the application is not configured @@ -55,32 +60,41 @@ #if ( configUSE_TIMERS == 1 ) /* Misc definitions. */ - #define tmrNO_DELAY ( TickType_t ) 0U + #define tmrNO_DELAY ( ( TickType_t ) 0U ) + #define tmrMAX_TIME_BEFORE_OVERFLOW ( ( TickType_t ) -1 ) -/* The name assigned to the timer service task. This can be overridden by - * defining trmTIMER_SERVICE_TASK_NAME in FreeRTOSConfig.h. */ +/* The name assigned to the timer service task. This can be overridden by + * defining configTIMER_SERVICE_TASK_NAME in FreeRTOSConfig.h. */ #ifndef configTIMER_SERVICE_TASK_NAME #define configTIMER_SERVICE_TASK_NAME "Tmr Svc" #endif + #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) + +/* The core affinity assigned to the timer service task on SMP systems. + * This can be overridden by defining configTIMER_SERVICE_TASK_CORE_AFFINITY in FreeRTOSConfig.h. */ + #ifndef configTIMER_SERVICE_TASK_CORE_AFFINITY + #define configTIMER_SERVICE_TASK_CORE_AFFINITY tskNO_AFFINITY + #endif + #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ + /* Bit definitions used in the ucStatus member of a timer structure. */ - #define tmrSTATUS_IS_ACTIVE ( ( uint8_t ) 0x01 ) - #define tmrSTATUS_IS_STATICALLY_ALLOCATED ( ( uint8_t ) 0x02 ) - #define tmrSTATUS_IS_AUTORELOAD ( ( uint8_t ) 0x04 ) + #define tmrSTATUS_IS_ACTIVE ( 0x01U ) + #define tmrSTATUS_IS_STATICALLY_ALLOCATED ( 0x02U ) + #define tmrSTATUS_IS_AUTORELOAD ( 0x04U ) /* The definition of the timers themselves. */ - typedef struct tmrTimerControl /* The old naming convention is used to prevent breaking kernel aware debuggers. */ + typedef struct tmrTimerControl /* The old naming convention is used to prevent breaking kernel aware debuggers. */ { - const char * pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - ListItem_t xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */ - TickType_t xTimerPeriodInTicks; /*<< How quickly and often the timer expires. */ - void * pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */ - portTIMER_CALLBACK_ATTRIBUTE - TimerCallbackFunction_t pxCallbackFunction; /*<< The function that will be called when the timer expires. */ + const char * pcTimerName; /**< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ + ListItem_t xTimerListItem; /**< Standard linked list item as used by all kernel features for event management. */ + TickType_t xTimerPeriodInTicks; /**< How quickly and often the timer expires. */ + void * pvTimerID; /**< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */ + portTIMER_CALLBACK_ATTRIBUTE TimerCallbackFunction_t pxCallbackFunction; /**< The function that will be called when the timer expires. */ #if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxTimerNumber; /*<< An ID assigned by trace tools such as FreeRTOS+Trace */ + UBaseType_t uxTimerNumber; /**< An ID assigned by trace tools such as FreeRTOS+Trace */ #endif - uint8_t ucStatus; /*<< Holds bits to say if the timer was statically allocated or not, and if it is active or not. */ + uint8_t ucStatus; /**< Holds bits to say if the timer was statically allocated or not, and if it is active or not. */ } xTIMER; /* The old xTIMER name is maintained above then typedefed to the new Timer_t @@ -94,8 +108,8 @@ * and xCallbackParametersType respectively. */ typedef struct tmrTimerParameters { - TickType_t xMessageValue; /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */ - Timer_t * pxTimer; /*<< The timer to which the command will be applied. */ + TickType_t xMessageValue; /**< An optional value used by a subset of commands, for example, when changing the period of a timer. */ + Timer_t * pxTimer; /**< The timer to which the command will be applied. */ } TimerParameter_t; @@ -111,7 +125,7 @@ * that is used to determine which message type is valid. */ typedef struct tmrTimerQueueMessage { - BaseType_t xMessageID; /*<< The command being sent to the timer service task. */ + BaseType_t xMessageID; /**< The command being sent to the timer service task. */ union { TimerParameter_t xTimerParameters; @@ -124,9 +138,6 @@ } u; } DaemonTaskMessage_t; -/*lint -save -e956 A manual analysis and inspection has been used to determine - * which static variables must be declared volatile. */ - /* The list in which active timers are stored. Timers are referenced in expire * time order, with the nearest expiry time at the front of the list. Only the * timer service task is allowed to access these lists. @@ -142,8 +153,6 @@ PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL; PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL; -/*lint -restore */ - /*-----------------------------------------------------------*/ /* @@ -174,6 +183,15 @@ const TickType_t xTimeNow, const TickType_t xCommandTime ) PRIVILEGED_FUNCTION; +/* + * Reload the specified auto-reload timer. If the reloading is backlogged, + * clear the backlog, calling the callback for each additional reload. When + * this function returns, the next expiry time is after xTimeNow. + */ + static void prvReloadTimer( Timer_t * const pxTimer, + TickType_t xExpiredTime, + const TickType_t xTimeNow ) PRIVILEGED_FUNCTION; + /* * An active timer has reached its expire time. Reload the timer if it is an * auto-reload timer, then call its callback. @@ -212,9 +230,9 @@ * Called after a Timer_t structure has been allocated either statically or * dynamically to fill in the structure's members. */ - static void prvInitialiseNewTimer( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + static void prvInitialiseNewTimer( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, - const UBaseType_t uxAutoReload, + const BaseType_t xAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, Timer_t * pxNewTimer ) PRIVILEGED_FUNCTION; @@ -224,6 +242,8 @@ { BaseType_t xReturn = pdFAIL; + traceENTER_xTimerCreateTimerTask(); + /* This function is called when the scheduler is started if * configUSE_TIMERS is set to 1. Check that the infrastructure used by the * timer service task has been created/initialised. If timers have already @@ -232,7 +252,44 @@ if( xTimerQueue != NULL ) { - #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) + { + #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + { + StaticTask_t * pxTimerTaskTCBBuffer = NULL; + StackType_t * pxTimerTaskStackBuffer = NULL; + uint32_t ulTimerTaskStackSize; + + vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer, &pxTimerTaskStackBuffer, &ulTimerTaskStackSize ); + xTimerTaskHandle = xTaskCreateStaticAffinitySet( prvTimerTask, + configTIMER_SERVICE_TASK_NAME, + ulTimerTaskStackSize, + NULL, + ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, + pxTimerTaskStackBuffer, + pxTimerTaskTCBBuffer, + configTIMER_SERVICE_TASK_CORE_AFFINITY ); + + if( xTimerTaskHandle != NULL ) + { + xReturn = pdPASS; + } + } + #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ + { + xReturn = xTaskCreateAffinitySet( prvTimerTask, + configTIMER_SERVICE_TASK_NAME, + configTIMER_TASK_STACK_DEPTH, + NULL, + ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, + configTIMER_SERVICE_TASK_CORE_AFFINITY, + &xTimerTaskHandle ); + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ + } + #else /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ + { + #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) { StaticTask_t * pxTimerTaskTCBBuffer = NULL; StackType_t * pxTimerTaskStackBuffer = NULL; @@ -252,7 +309,7 @@ xReturn = pdPASS; } } - #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ + #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ { xReturn = xTaskCreate( prvTimerTask, configTIMER_SERVICE_TASK_NAME, @@ -261,7 +318,9 @@ ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, &xTimerTaskHandle ); } - #endif /* configSUPPORT_STATIC_ALLOCATION */ + #endif /* configSUPPORT_STATIC_ALLOCATION */ + } + #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ } else { @@ -269,21 +328,29 @@ } configASSERT( xReturn ); + + traceRETURN_xTimerCreateTimerTask( xReturn ); + return xReturn; } /*-----------------------------------------------------------*/ #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - TimerHandle_t xTimerCreate( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, - const UBaseType_t uxAutoReload, + const BaseType_t xAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) { Timer_t * pxNewTimer; - pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of Timer_t is always a pointer to the timer's mame. */ + traceENTER_xTimerCreate( pcTimerName, xTimerPeriodInTicks, xAutoReload, pvTimerID, pxCallbackFunction ); + + /* MISRA Ref 11.5.1 [Malloc memory assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) ); if( pxNewTimer != NULL ) { @@ -291,9 +358,11 @@ * and has not been started. The auto-reload bit may get set in * prvInitialiseNewTimer. */ pxNewTimer->ucStatus = 0x00; - prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer ); + prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, xAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer ); } + traceRETURN_xTimerCreate( pxNewTimer ); + return pxNewTimer; } @@ -302,49 +371,56 @@ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) - TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, - const UBaseType_t uxAutoReload, + const BaseType_t xAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, StaticTimer_t * pxTimerBuffer ) { Timer_t * pxNewTimer; + traceENTER_xTimerCreateStatic( pcTimerName, xTimerPeriodInTicks, xAutoReload, pvTimerID, pxCallbackFunction, pxTimerBuffer ); + #if ( configASSERT_DEFINED == 1 ) - { - /* Sanity check that the size of the structure used to declare a - * variable of type StaticTimer_t equals the size of the real timer - * structure. */ - volatile size_t xSize = sizeof( StaticTimer_t ); - configASSERT( xSize == sizeof( Timer_t ) ); - ( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */ - } + { + /* Sanity check that the size of the structure used to declare a + * variable of type StaticTimer_t equals the size of the real timer + * structure. */ + volatile size_t xSize = sizeof( StaticTimer_t ); + configASSERT( xSize == sizeof( Timer_t ) ); + ( void ) xSize; /* Prevent unused variable warning when configASSERT() is not defined. */ + } #endif /* configASSERT_DEFINED */ /* A pointer to a StaticTimer_t structure MUST be provided, use it. */ configASSERT( pxTimerBuffer ); - pxNewTimer = ( Timer_t * ) pxTimerBuffer; /*lint !e740 !e9087 StaticTimer_t is a pointer to a Timer_t, so guaranteed to be aligned and sized correctly (checked by an assert()), so this is safe. */ + /* MISRA Ref 11.3.1 [Misaligned access] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */ + /* coverity[misra_c_2012_rule_11_3_violation] */ + pxNewTimer = ( Timer_t * ) pxTimerBuffer; if( pxNewTimer != NULL ) { /* Timers can be created statically or dynamically so note this * timer was created statically in case it is later deleted. The * auto-reload bit may get set in prvInitialiseNewTimer(). */ - pxNewTimer->ucStatus = tmrSTATUS_IS_STATICALLY_ALLOCATED; + pxNewTimer->ucStatus = ( uint8_t ) tmrSTATUS_IS_STATICALLY_ALLOCATED; - prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer ); + prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, xAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer ); } + traceRETURN_xTimerCreateStatic( pxNewTimer ); + return pxNewTimer; } #endif /* configSUPPORT_STATIC_ALLOCATION */ /*-----------------------------------------------------------*/ - static void prvInitialiseNewTimer( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + static void prvInitialiseNewTimer( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, - const UBaseType_t uxAutoReload, + const BaseType_t xAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, Timer_t * pxNewTimer ) @@ -352,27 +428,24 @@ /* 0 is not a valid value for xTimerPeriodInTicks. */ configASSERT( ( xTimerPeriodInTicks > 0 ) ); - if( pxNewTimer != NULL ) + /* Ensure the infrastructure used by the timer service task has been + * created/initialised. */ + prvCheckForValidListAndQueue(); + + /* Initialise the timer structure members using the function + * parameters. */ + pxNewTimer->pcTimerName = pcTimerName; + pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks; + pxNewTimer->pvTimerID = pvTimerID; + pxNewTimer->pxCallbackFunction = pxCallbackFunction; + vListInitialiseItem( &( pxNewTimer->xTimerListItem ) ); + + if( xAutoReload != pdFALSE ) { - /* Ensure the infrastructure used by the timer service task has been - * created/initialised. */ - prvCheckForValidListAndQueue(); - - /* Initialise the timer structure members using the function - * parameters. */ - pxNewTimer->pcTimerName = pcTimerName; - pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks; - pxNewTimer->pvTimerID = pvTimerID; - pxNewTimer->pxCallbackFunction = pxCallbackFunction; - vListInitialiseItem( &( pxNewTimer->xTimerListItem ) ); - - if( uxAutoReload != pdFALSE ) - { - pxNewTimer->ucStatus |= tmrSTATUS_IS_AUTORELOAD; - } - - traceTIMER_CREATE( pxNewTimer ); + pxNewTimer->ucStatus |= ( uint8_t ) tmrSTATUS_IS_AUTORELOAD; } + + traceTIMER_CREATE( pxNewTimer ); } /*-----------------------------------------------------------*/ @@ -385,6 +458,10 @@ BaseType_t xReturn = pdFAIL; DaemonTaskMessage_t xMessage; + ( void ) pxHigherPriorityTaskWoken; + + traceENTER_xTimerGenericCommandFromTask( xTimer, xCommandID, xOptionalValue, pxHigherPriorityTaskWoken, xTicksToWait ); + configASSERT( xTimer ); /* Send a message to the timer service task to perform a particular action @@ -417,6 +494,8 @@ mtCOVERAGE_TEST_MARKER(); } + traceRETURN_xTimerGenericCommandFromTask( xReturn ); + return xReturn; } /*-----------------------------------------------------------*/ @@ -430,6 +509,10 @@ BaseType_t xReturn = pdFAIL; DaemonTaskMessage_t xMessage; + ( void ) xTicksToWait; + + traceENTER_xTimerGenericCommandFromISR( xTimer, xCommandID, xOptionalValue, pxHigherPriorityTaskWoken, xTicksToWait ); + configASSERT( xTimer ); /* Send a message to the timer service task to perform a particular action @@ -455,15 +538,22 @@ mtCOVERAGE_TEST_MARKER(); } + traceRETURN_xTimerGenericCommandFromISR( xReturn ); + return xReturn; } /*-----------------------------------------------------------*/ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) { + traceENTER_xTimerGetTimerDaemonTaskHandle(); + /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been * started, then xTimerTaskHandle will be NULL. */ configASSERT( ( xTimerTaskHandle != NULL ) ); + + traceRETURN_xTimerGetTimerDaemonTaskHandle( xTimerTaskHandle ); + return xTimerTaskHandle; } /*-----------------------------------------------------------*/ @@ -472,53 +562,79 @@ { Timer_t * pxTimer = xTimer; + traceENTER_xTimerGetPeriod( xTimer ); + configASSERT( xTimer ); + + traceRETURN_xTimerGetPeriod( pxTimer->xTimerPeriodInTicks ); + return pxTimer->xTimerPeriodInTicks; } /*-----------------------------------------------------------*/ void vTimerSetReloadMode( TimerHandle_t xTimer, - const UBaseType_t uxAutoReload ) + const BaseType_t xAutoReload ) { Timer_t * pxTimer = xTimer; + traceENTER_vTimerSetReloadMode( xTimer, xAutoReload ); + configASSERT( xTimer ); taskENTER_CRITICAL(); { - if( uxAutoReload != pdFALSE ) + if( xAutoReload != pdFALSE ) { - pxTimer->ucStatus |= tmrSTATUS_IS_AUTORELOAD; + pxTimer->ucStatus |= ( uint8_t ) tmrSTATUS_IS_AUTORELOAD; } else { - pxTimer->ucStatus &= ~tmrSTATUS_IS_AUTORELOAD; + pxTimer->ucStatus &= ( ( uint8_t ) ~tmrSTATUS_IS_AUTORELOAD ); } } taskEXIT_CRITICAL(); + + traceRETURN_vTimerSetReloadMode(); } /*-----------------------------------------------------------*/ - UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer ) + BaseType_t xTimerGetReloadMode( TimerHandle_t xTimer ) { Timer_t * pxTimer = xTimer; - UBaseType_t uxReturn; + BaseType_t xReturn; + + traceENTER_xTimerGetReloadMode( xTimer ); configASSERT( xTimer ); taskENTER_CRITICAL(); { - if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) == 0 ) + if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) == 0U ) { /* Not an auto-reload timer. */ - uxReturn = ( UBaseType_t ) pdFALSE; + xReturn = pdFALSE; } else { /* Is an auto-reload timer. */ - uxReturn = ( UBaseType_t ) pdTRUE; + xReturn = pdTRUE; } } taskEXIT_CRITICAL(); + traceRETURN_xTimerGetReloadMode( xReturn ); + + return xReturn; + } + + UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer ) + { + UBaseType_t uxReturn; + + traceENTER_uxTimerGetReloadMode( xTimer ); + + uxReturn = ( UBaseType_t ) xTimerGetReloadMode( xTimer ); + + traceRETURN_uxTimerGetReloadMode( uxReturn ); + return uxReturn; } /*-----------------------------------------------------------*/ @@ -528,8 +644,13 @@ Timer_t * pxTimer = xTimer; TickType_t xReturn; + traceENTER_xTimerGetExpiryTime( xTimer ); + configASSERT( xTimer ); xReturn = listGET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ) ); + + traceRETURN_xTimerGetExpiryTime( xReturn ); + return xReturn; } /*-----------------------------------------------------------*/ @@ -541,10 +662,15 @@ BaseType_t xReturn; Timer_t * pxTimer = xTimer; + traceENTER_xTimerGetStaticBuffer( xTimer, ppxTimerBuffer ); + configASSERT( ppxTimerBuffer != NULL ); - if( ( pxTimer->ucStatus & tmrSTATUS_IS_STATICALLY_ALLOCATED ) != 0 ) + if( ( pxTimer->ucStatus & tmrSTATUS_IS_STATICALLY_ALLOCATED ) != 0U ) { + /* MISRA Ref 11.3.1 [Misaligned access] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */ + /* coverity[misra_c_2012_rule_11_3_violation] */ *ppxTimerBuffer = ( StaticTimer_t * ) pxTimer; xReturn = pdTRUE; } @@ -553,59 +679,72 @@ xReturn = pdFALSE; } + traceRETURN_xTimerGetStaticBuffer( xReturn ); + return xReturn; } #endif /* configSUPPORT_STATIC_ALLOCATION */ /*-----------------------------------------------------------*/ - const char * pcTimerGetName( TimerHandle_t xTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const char * pcTimerGetName( TimerHandle_t xTimer ) { Timer_t * pxTimer = xTimer; + traceENTER_pcTimerGetName( xTimer ); + configASSERT( xTimer ); + + traceRETURN_pcTimerGetName( pxTimer->pcTimerName ); + return pxTimer->pcTimerName; } /*-----------------------------------------------------------*/ + static void prvReloadTimer( Timer_t * const pxTimer, + TickType_t xExpiredTime, + const TickType_t xTimeNow ) + { + /* Insert the timer into the appropriate list for the next expiry time. + * If the next expiry time has already passed, advance the expiry time, + * call the callback function, and try again. */ + while( prvInsertTimerInActiveList( pxTimer, ( xExpiredTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xExpiredTime ) != pdFALSE ) + { + /* Advance the expiry time. */ + xExpiredTime += pxTimer->xTimerPeriodInTicks; + + /* Call the timer callback. */ + traceTIMER_EXPIRED( pxTimer ); + pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); + } + } +/*-----------------------------------------------------------*/ + static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) { - BaseType_t xResult; - Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); /*lint !e9087 !e9079 void * is used as this macro is used with tasks and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ + /* MISRA Ref 11.5.3 [Void pointer assignment] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ + /* coverity[misra_c_2012_rule_11_5_violation] */ + Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); /* Remove the timer from the list of active timers. A check has already * been performed to ensure the list is not empty. */ ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); - traceTIMER_EXPIRED( pxTimer ); /* If the timer is an auto-reload timer then calculate the next * expiry time and re-insert the timer in the list of active timers. */ - if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 ) + if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0U ) { - /* The timer is inserted into a list using a time relative to anything - * other than the current time. It will therefore be inserted into the - * correct list relative to the time this task thinks it is now. */ - if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) != pdFALSE ) - { - /* The timer expired before it was added to the active timer - * list. Reload it now. */ - xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY ); - configASSERT( xResult ); - ( void ) xResult; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + prvReloadTimer( pxTimer, xNextExpireTime, xTimeNow ); } else { - pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE; - mtCOVERAGE_TEST_MARKER(); + pxTimer->ucStatus &= ( ( uint8_t ) ~tmrSTATUS_IS_ACTIVE ); } /* Call the timer callback. */ + traceTIMER_EXPIRED( pxTimer ); pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); } /*-----------------------------------------------------------*/ @@ -619,18 +758,16 @@ ( void ) pvParameters; #if ( configUSE_DAEMON_TASK_STARTUP_HOOK == 1 ) - { - extern void vApplicationDaemonTaskStartupHook( void ); - - /* Allow the application writer to execute some code in the context of - * this task at the point the task starts executing. This is useful if the - * application includes initialisation code that would benefit from - * executing after the scheduler has been started. */ - vApplicationDaemonTaskStartupHook(); - } + { + /* Allow the application writer to execute some code in the context of + * this task at the point the task starts executing. This is useful if the + * application includes initialisation code that would benefit from + * executing after the scheduler has been started. */ + vApplicationDaemonTaskStartupHook(); + } #endif /* configUSE_DAEMON_TASK_STARTUP_HOOK */ - for( ; ; ) + for( ; configCONTROL_INFINITE_LOOP(); ) { /* Query the timers list to see if it contains any timers, and if so, * obtain the time at which the next timer will expire. */ @@ -692,7 +829,7 @@ * block time to expire. If a command arrived between the * critical section being exited and this yield then the yield * will not cause the task to block. */ - vTaskYieldWithinAPI(); + taskYIELD_WITHIN_API(); } else { @@ -738,7 +875,7 @@ static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) { TickType_t xTimeNow; - PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U; /*lint !e956 Variable is only accessible to one task. */ + PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U; xTimeNow = xTaskGetTickCount(); @@ -772,7 +909,7 @@ { /* Has the expiry time elapsed between the command to start/reset a * timer was issued, and the time the command was processed? */ - if( ( ( TickType_t ) ( xTimeNow - xCommandTime ) ) >= pxTimer->xTimerPeriodInTicks ) /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + if( ( ( TickType_t ) ( xTimeNow - xCommandTime ) ) >= pxTimer->xTimerPeriodInTicks ) { /* The time between a command being issued and the command being * processed actually exceeds the timers period. */ @@ -804,33 +941,33 @@ static void prvProcessReceivedCommands( void ) { - DaemonTaskMessage_t xMessage; + DaemonTaskMessage_t xMessage = { 0 }; Timer_t * pxTimer; - BaseType_t xTimerListsWereSwitched, xResult; + BaseType_t xTimerListsWereSwitched; TickType_t xTimeNow; - while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) /*lint !e603 xMessage does not have to be initialised as it is passed out, not in, and it is not used unless xQueueReceive() returns pdTRUE. */ + while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) { #if ( INCLUDE_xTimerPendFunctionCall == 1 ) + { + /* Negative commands are pended function calls rather than timer + * commands. */ + if( xMessage.xMessageID < ( BaseType_t ) 0 ) { - /* Negative commands are pended function calls rather than timer - * commands. */ - if( xMessage.xMessageID < ( BaseType_t ) 0 ) - { - const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters ); + const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters ); - /* The timer uses the xCallbackParameters member to request a - * callback be executed. Check the callback is not NULL. */ - configASSERT( pxCallback ); + /* The timer uses the xCallbackParameters member to request a + * callback be executed. Check the callback is not NULL. */ + configASSERT( pxCallback ); - /* Call the function. */ - pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Call the function. */ + pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 ); } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } #endif /* INCLUDE_xTimerPendFunctionCall */ /* Commands that are positive are timer commands rather than pended @@ -841,7 +978,7 @@ * software timer. */ pxTimer = xMessage.u.xTimerParameters.pxTimer; - if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) /*lint !e961. The cast is only redundant when NULL is passed into the macro. */ + if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) { /* The timer is in a list, remove it. */ ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); @@ -867,27 +1004,25 @@ case tmrCOMMAND_START_FROM_ISR: case tmrCOMMAND_RESET: case tmrCOMMAND_RESET_FROM_ISR: - case tmrCOMMAND_START_DONT_TRACE: /* Start or restart a timer. */ - pxTimer->ucStatus |= tmrSTATUS_IS_ACTIVE; + pxTimer->ucStatus |= ( uint8_t ) tmrSTATUS_IS_ACTIVE; if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) != pdFALSE ) { /* The timer expired before it was added to the active * timer list. Process it now. */ - pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); - traceTIMER_EXPIRED( pxTimer ); - - if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 ) + if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0U ) { - xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY ); - configASSERT( xResult ); - ( void ) xResult; + prvReloadTimer( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow ); } else { - mtCOVERAGE_TEST_MARKER(); + pxTimer->ucStatus &= ( ( uint8_t ) ~tmrSTATUS_IS_ACTIVE ); } + + /* Call the timer callback. */ + traceTIMER_EXPIRED( pxTimer ); + pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); } else { @@ -899,12 +1034,12 @@ case tmrCOMMAND_STOP: case tmrCOMMAND_STOP_FROM_ISR: /* The timer has already been removed from the active list. */ - pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE; + pxTimer->ucStatus &= ( ( uint8_t ) ~tmrSTATUS_IS_ACTIVE ); break; case tmrCOMMAND_CHANGE_PERIOD: case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR: - pxTimer->ucStatus |= tmrSTATUS_IS_ACTIVE; + pxTimer->ucStatus |= ( uint8_t ) tmrSTATUS_IS_ACTIVE; pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue; configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) ); @@ -919,27 +1054,27 @@ case tmrCOMMAND_DELETE: #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + { + /* The timer has already been removed from the active list, + * just free up the memory if the memory was dynamically + * allocated. */ + if( ( pxTimer->ucStatus & tmrSTATUS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) 0 ) { - /* The timer has already been removed from the active list, - * just free up the memory if the memory was dynamically - * allocated. */ - if( ( pxTimer->ucStatus & tmrSTATUS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) 0 ) - { - vPortFree( pxTimer ); - } - else - { - pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE; - } + vPortFree( pxTimer ); } + else + { + pxTimer->ucStatus &= ( ( uint8_t ) ~tmrSTATUS_IS_ACTIVE ); + } + } #else /* if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) */ - { - /* If dynamic allocation is not enabled, the memory - * could not have been dynamically allocated. So there is - * no need to free the memory - just mark the timer as - * "not active". */ - pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE; - } + { + /* If dynamic allocation is not enabled, the memory + * could not have been dynamically allocated. So there is + * no need to free the memory - just mark the timer as + * "not active". */ + pxTimer->ucStatus &= ( ( uint8_t ) ~tmrSTATUS_IS_ACTIVE ); + } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ break; @@ -954,10 +1089,8 @@ static void prvSwitchTimerLists( void ) { - TickType_t xNextExpireTime, xReloadTime; + TickType_t xNextExpireTime; List_t * pxTemp; - Timer_t * pxTimer; - BaseType_t xResult; /* The tick count has overflowed. The timer lists must be switched. * If there are any timers still referenced from the current timer list @@ -967,43 +1100,10 @@ { xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); - /* Remove the timer from the list. */ - pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); /*lint !e9087 !e9079 void * is used as this macro is used with tasks and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ - ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); - traceTIMER_EXPIRED( pxTimer ); - - /* Execute its callback, then send a command to restart the timer if - * it is an auto-reload timer. It cannot be restarted here as the lists - * have not yet been switched. */ - pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); - - if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 ) - { - /* Calculate the reload value, and if the reload value results in - * the timer going into the same timer list then it has already expired - * and the timer should be re-inserted into the current list so it is - * processed again within this loop. Otherwise a command should be sent - * to restart the timer to ensure it is only inserted into a list after - * the lists have been swapped. */ - xReloadTime = ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ); - - if( xReloadTime > xNextExpireTime ) - { - listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xReloadTime ); - listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); - vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); - } - else - { - xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY ); - configASSERT( xResult ); - ( void ) xResult; - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Process the expired timer. For auto-reload timers, be careful to + * process only expirations that occur on the current list. Further + * expirations must wait until after the lists are switched. */ + prvProcessExpiredTimer( xNextExpireTime, tmrMAX_TIME_BEFORE_OVERFLOW ); } pxTemp = pxCurrentTimerList; @@ -1027,31 +1127,31 @@ pxOverflowTimerList = &xActiveTimerList2; #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) - { - /* The timer queue is allocated statically in case - * configSUPPORT_DYNAMIC_ALLOCATION is 0. */ - PRIVILEGED_DATA static StaticQueue_t xStaticTimerQueue; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */ - PRIVILEGED_DATA static uint8_t ucStaticTimerQueueStorage[ ( size_t ) configTIMER_QUEUE_LENGTH * sizeof( DaemonTaskMessage_t ) ]; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */ + { + /* The timer queue is allocated statically in case + * configSUPPORT_DYNAMIC_ALLOCATION is 0. */ + PRIVILEGED_DATA static StaticQueue_t xStaticTimerQueue; + PRIVILEGED_DATA static uint8_t ucStaticTimerQueueStorage[ ( size_t ) configTIMER_QUEUE_LENGTH * sizeof( DaemonTaskMessage_t ) ]; - xTimerQueue = xQueueCreateStatic( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, ( UBaseType_t ) sizeof( DaemonTaskMessage_t ), &( ucStaticTimerQueueStorage[ 0 ] ), &xStaticTimerQueue ); - } + xTimerQueue = xQueueCreateStatic( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, ( UBaseType_t ) sizeof( DaemonTaskMessage_t ), &( ucStaticTimerQueueStorage[ 0 ] ), &xStaticTimerQueue ); + } #else - { - xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) ); - } + { + xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, ( UBaseType_t ) sizeof( DaemonTaskMessage_t ) ); + } #endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ #if ( configQUEUE_REGISTRY_SIZE > 0 ) + { + if( xTimerQueue != NULL ) { - if( xTimerQueue != NULL ) - { - vQueueAddToRegistry( xTimerQueue, "TmrQ" ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + vQueueAddToRegistry( xTimerQueue, "TmrQ" ); } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } #endif /* configQUEUE_REGISTRY_SIZE */ } else @@ -1068,12 +1168,14 @@ BaseType_t xReturn; Timer_t * pxTimer = xTimer; + traceENTER_xTimerIsTimerActive( xTimer ); + configASSERT( xTimer ); /* Is the timer in the list of active timers? */ taskENTER_CRITICAL(); { - if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0 ) + if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0U ) { xReturn = pdFALSE; } @@ -1084,8 +1186,10 @@ } taskEXIT_CRITICAL(); + traceRETURN_xTimerIsTimerActive( xReturn ); + return xReturn; - } /*lint !e818 Can't be pointer to const due to the typedef. */ + } /*-----------------------------------------------------------*/ void * pvTimerGetTimerID( const TimerHandle_t xTimer ) @@ -1093,6 +1197,8 @@ Timer_t * const pxTimer = xTimer; void * pvReturn; + traceENTER_pvTimerGetTimerID( xTimer ); + configASSERT( xTimer ); taskENTER_CRITICAL(); @@ -1101,6 +1207,8 @@ } taskEXIT_CRITICAL(); + traceRETURN_pvTimerGetTimerID( pvReturn ); + return pvReturn; } /*-----------------------------------------------------------*/ @@ -1110,6 +1218,8 @@ { Timer_t * const pxTimer = xTimer; + traceENTER_vTimerSetTimerID( xTimer, pvNewID ); + configASSERT( xTimer ); taskENTER_CRITICAL(); @@ -1117,6 +1227,8 @@ pxTimer->pvTimerID = pvNewID; } taskEXIT_CRITICAL(); + + traceRETURN_vTimerSetTimerID(); } /*-----------------------------------------------------------*/ @@ -1130,6 +1242,8 @@ DaemonTaskMessage_t xMessage; BaseType_t xReturn; + traceENTER_xTimerPendFunctionCallFromISR( xFunctionToPend, pvParameter1, ulParameter2, pxHigherPriorityTaskWoken ); + /* Complete the message with the function parameters and post it to the * daemon task. */ xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR; @@ -1140,6 +1254,7 @@ xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken ); tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, xReturn ); + traceRETURN_xTimerPendFunctionCallFromISR( xReturn ); return xReturn; } @@ -1157,6 +1272,8 @@ DaemonTaskMessage_t xMessage; BaseType_t xReturn; + traceENTER_xTimerPendFunctionCall( xFunctionToPend, pvParameter1, ulParameter2, xTicksToWait ); + /* This function can only be called after a timer has been created or * after the scheduler has been started because, until then, the timer * queue does not exist. */ @@ -1172,6 +1289,7 @@ xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait ); tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, xReturn ); + traceRETURN_xTimerPendFunctionCall( xReturn ); return xReturn; } @@ -1183,6 +1301,10 @@ UBaseType_t uxTimerGetTimerNumber( TimerHandle_t xTimer ) { + traceENTER_uxTimerGetTimerNumber( xTimer ); + + traceRETURN_uxTimerGetTimerNumber( ( ( Timer_t * ) xTimer )->uxTimerNumber ); + return ( ( Timer_t * ) xTimer )->uxTimerNumber; } @@ -1194,7 +1316,11 @@ void vTimerSetTimerNumber( TimerHandle_t xTimer, UBaseType_t uxTimerNumber ) { + traceENTER_vTimerSetTimerNumber( xTimer, uxTimerNumber ); + ( ( Timer_t * ) xTimer )->uxTimerNumber = uxTimerNumber; + + traceRETURN_vTimerSetTimerNumber(); } #endif /* configUSE_TRACE_FACILITY */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/uncrustify.cfg b/components/freertos/FreeRTOS-Kernel-SMP/uncrustify.cfg new file mode 100644 index 0000000000..3f4c40cab1 --- /dev/null +++ b/components/freertos/FreeRTOS-Kernel-SMP/uncrustify.cfg @@ -0,0 +1,673 @@ +# Uncrustify-0.69.0 + +newlines = auto # lf/crlf/cr/auto +input_tab_size = 4 # unsigned number +output_tab_size = 4 # unsigned number +string_escape_char = 92 # unsigned number +string_escape_char2 = 0 # unsigned number +string_replace_tab_chars = false # true/false +tok_split_gte = false # true/false +disable_processing_cmt = " *INDENT-OFF*" # string +enable_processing_cmt = " *INDENT-ON*" # string +enable_digraphs = false # true/false +utf8_bom = ignore # ignore/add/remove/force +utf8_byte = false # true/false +utf8_force = false # true/false +sp_arith = force # ignore/add/remove/force +sp_arith_additive = ignore # ignore/add/remove/force +sp_assign = force # ignore/add/remove/force +sp_cpp_lambda_assign = ignore # ignore/add/remove/force +sp_cpp_lambda_paren = ignore # ignore/add/remove/force +sp_assign_default = force # ignore/add/remove/force +sp_before_assign = force # ignore/add/remove/force +sp_after_assign = force # ignore/add/remove/force +sp_enum_paren = ignore # ignore/add/remove/force +sp_enum_assign = force # ignore/add/remove/force +sp_enum_before_assign = force # ignore/add/remove/force +sp_enum_after_assign = force # ignore/add/remove/force +sp_enum_colon = ignore # ignore/add/remove/force +sp_pp_concat = add # ignore/add/remove/force +sp_pp_stringify = add # ignore/add/remove/force +sp_before_pp_stringify = ignore # ignore/add/remove/force +sp_bool = force # ignore/add/remove/force +sp_compare = force # ignore/add/remove/force +sp_inside_paren = force # ignore/add/remove/force +sp_paren_paren = force # ignore/add/remove/force +sp_cparen_oparen = ignore # ignore/add/remove/force +sp_balance_nested_parens = false # true/false +sp_paren_brace = force # ignore/add/remove/force +sp_brace_brace = ignore # ignore/add/remove/force +sp_before_ptr_star = force # ignore/add/remove/force +sp_before_unnamed_ptr_star = force # ignore/add/remove/force +sp_between_ptr_star = remove # ignore/add/remove/force +sp_after_ptr_star = force # ignore/add/remove/force +sp_after_ptr_block_caret = ignore # ignore/add/remove/force +sp_after_ptr_star_qualifier = ignore # ignore/add/remove/force +sp_after_ptr_star_func = ignore # ignore/add/remove/force +sp_ptr_star_paren = ignore # ignore/add/remove/force +sp_before_ptr_star_func = ignore # ignore/add/remove/force +sp_before_byref = force # ignore/add/remove/force +sp_before_unnamed_byref = ignore # ignore/add/remove/force +sp_after_byref = remove # ignore/add/remove/force +sp_after_byref_func = remove # ignore/add/remove/force +sp_before_byref_func = ignore # ignore/add/remove/force +sp_after_type = force # ignore/add/remove/force +sp_after_decltype = ignore # ignore/add/remove/force +sp_before_template_paren = ignore # ignore/add/remove/force +sp_template_angle = ignore # ignore/add/remove/force +sp_before_angle = remove # ignore/add/remove/force +sp_inside_angle = remove # ignore/add/remove/force +sp_inside_angle_empty = ignore # ignore/add/remove/force +sp_angle_colon = ignore # ignore/add/remove/force +sp_after_angle = force # ignore/add/remove/force +sp_angle_paren = ignore # ignore/add/remove/force +sp_angle_paren_empty = ignore # ignore/add/remove/force +sp_angle_word = ignore # ignore/add/remove/force +sp_angle_shift = add # ignore/add/remove/force +sp_permit_cpp11_shift = false # true/false +sp_before_sparen = remove # ignore/add/remove/force +sp_inside_sparen = force # ignore/add/remove/force +sp_inside_sparen_open = ignore # ignore/add/remove/force +sp_inside_sparen_close = ignore # ignore/add/remove/force +sp_after_sparen = force # ignore/add/remove/force +sp_sparen_brace = force # ignore/add/remove/force +sp_invariant_paren = ignore # ignore/add/remove/force +sp_after_invariant_paren = ignore # ignore/add/remove/force +sp_special_semi = ignore # ignore/add/remove/force +sp_before_semi = remove # ignore/add/remove/force +sp_before_semi_for = remove # ignore/add/remove/force +sp_before_semi_for_empty = add # ignore/add/remove/force +sp_after_semi = add # ignore/add/remove/force +sp_after_semi_for = force # ignore/add/remove/force +sp_after_semi_for_empty = force # ignore/add/remove/force +sp_before_square = remove # ignore/add/remove/force +sp_before_squares = remove # ignore/add/remove/force +sp_cpp_before_struct_binding = ignore # ignore/add/remove/force +sp_inside_square = force # ignore/add/remove/force +sp_inside_square_oc_array = ignore # ignore/add/remove/force +sp_after_comma = force # ignore/add/remove/force +sp_before_comma = remove # ignore/add/remove/force +sp_after_mdatype_commas = ignore # ignore/add/remove/force +sp_before_mdatype_commas = ignore # ignore/add/remove/force +sp_between_mdatype_commas = ignore # ignore/add/remove/force +sp_paren_comma = force # ignore/add/remove/force +sp_before_ellipsis = ignore # ignore/add/remove/force +sp_type_ellipsis = ignore # ignore/add/remove/force +sp_type_question = ignore # ignore/add/remove/force +sp_paren_ellipsis = ignore # ignore/add/remove/force +sp_paren_qualifier = ignore # ignore/add/remove/force +sp_paren_noexcept = ignore # ignore/add/remove/force +sp_after_class_colon = ignore # ignore/add/remove/force +sp_before_class_colon = ignore # ignore/add/remove/force +sp_after_constr_colon = ignore # ignore/add/remove/force +sp_before_constr_colon = ignore # ignore/add/remove/force +sp_before_case_colon = remove # ignore/add/remove/force +sp_after_operator = ignore # ignore/add/remove/force +sp_after_operator_sym = ignore # ignore/add/remove/force +sp_after_operator_sym_empty = ignore # ignore/add/remove/force +sp_after_cast = force # ignore/add/remove/force +sp_inside_paren_cast = force # ignore/add/remove/force +sp_cpp_cast_paren = ignore # ignore/add/remove/force +sp_sizeof_paren = remove # ignore/add/remove/force +sp_sizeof_ellipsis = ignore # ignore/add/remove/force +sp_sizeof_ellipsis_paren = ignore # ignore/add/remove/force +sp_decltype_paren = ignore # ignore/add/remove/force +sp_after_tag = ignore # ignore/add/remove/force +sp_inside_braces_enum = force # ignore/add/remove/force +sp_inside_braces_struct = force # ignore/add/remove/force +sp_inside_braces_oc_dict = ignore # ignore/add/remove/force +sp_after_type_brace_init_lst_open = ignore # ignore/add/remove/force +sp_before_type_brace_init_lst_close = ignore # ignore/add/remove/force +sp_inside_type_brace_init_lst = ignore # ignore/add/remove/force +sp_inside_braces = force # ignore/add/remove/force +sp_inside_braces_empty = remove # ignore/add/remove/force +sp_type_func = force # ignore/add/remove/force +sp_type_brace_init_lst = ignore # ignore/add/remove/force +sp_func_proto_paren = remove # ignore/add/remove/force +sp_func_proto_paren_empty = ignore # ignore/add/remove/force +sp_func_def_paren = remove # ignore/add/remove/force +sp_func_def_paren_empty = ignore # ignore/add/remove/force +sp_inside_fparens = remove # ignore/add/remove/force +sp_inside_fparen = force # ignore/add/remove/force +sp_inside_tparen = ignore # ignore/add/remove/force +sp_after_tparen_close = ignore # ignore/add/remove/force +sp_square_fparen = ignore # ignore/add/remove/force +sp_fparen_brace = add # ignore/add/remove/force +sp_fparen_brace_initializer = ignore # ignore/add/remove/force +sp_fparen_dbrace = ignore # ignore/add/remove/force +sp_func_call_paren = remove # ignore/add/remove/force +sp_func_call_paren_empty = ignore # ignore/add/remove/force +sp_func_call_user_paren = ignore # ignore/add/remove/force +sp_func_call_user_inside_fparen = ignore # ignore/add/remove/force +sp_func_call_user_paren_paren = ignore # ignore/add/remove/force +sp_func_class_paren = remove # ignore/add/remove/force +sp_func_class_paren_empty = ignore # ignore/add/remove/force +sp_return_paren = remove # ignore/add/remove/force +sp_return_brace = ignore # ignore/add/remove/force +sp_attribute_paren = remove # ignore/add/remove/force +sp_defined_paren = remove # ignore/add/remove/force +sp_throw_paren = ignore # ignore/add/remove/force +sp_after_throw = ignore # ignore/add/remove/force +sp_catch_paren = ignore # ignore/add/remove/force +sp_oc_catch_paren = ignore # ignore/add/remove/force +sp_oc_classname_paren = ignore # ignore/add/remove/force +sp_version_paren = ignore # ignore/add/remove/force +sp_scope_paren = ignore # ignore/add/remove/force +sp_super_paren = remove # ignore/add/remove/force +sp_this_paren = remove # ignore/add/remove/force +sp_macro = force # ignore/add/remove/force +sp_macro_func = force # ignore/add/remove/force +sp_else_brace = ignore # ignore/add/remove/force +sp_brace_else = ignore # ignore/add/remove/force +sp_brace_typedef = force # ignore/add/remove/force +sp_catch_brace = ignore # ignore/add/remove/force +sp_oc_catch_brace = ignore # ignore/add/remove/force +sp_brace_catch = ignore # ignore/add/remove/force +sp_oc_brace_catch = ignore # ignore/add/remove/force +sp_finally_brace = ignore # ignore/add/remove/force +sp_brace_finally = ignore # ignore/add/remove/force +sp_try_brace = ignore # ignore/add/remove/force +sp_getset_brace = ignore # ignore/add/remove/force +sp_word_brace = add # ignore/add/remove/force +sp_word_brace_ns = add # ignore/add/remove/force +sp_before_dc = remove # ignore/add/remove/force +sp_after_dc = remove # ignore/add/remove/force +sp_d_array_colon = ignore # ignore/add/remove/force +sp_not = remove # ignore/add/remove/force +sp_inv = remove # ignore/add/remove/force +sp_addr = remove # ignore/add/remove/force +sp_member = remove # ignore/add/remove/force +sp_deref = remove # ignore/add/remove/force +sp_sign = remove # ignore/add/remove/force +sp_incdec = remove # ignore/add/remove/force +sp_before_nl_cont = add # ignore/add/remove/force +sp_after_oc_scope = ignore # ignore/add/remove/force +sp_after_oc_colon = ignore # ignore/add/remove/force +sp_before_oc_colon = ignore # ignore/add/remove/force +sp_after_oc_dict_colon = ignore # ignore/add/remove/force +sp_before_oc_dict_colon = ignore # ignore/add/remove/force +sp_after_send_oc_colon = ignore # ignore/add/remove/force +sp_before_send_oc_colon = ignore # ignore/add/remove/force +sp_after_oc_type = ignore # ignore/add/remove/force +sp_after_oc_return_type = ignore # ignore/add/remove/force +sp_after_oc_at_sel = ignore # ignore/add/remove/force +sp_after_oc_at_sel_parens = ignore # ignore/add/remove/force +sp_inside_oc_at_sel_parens = ignore # ignore/add/remove/force +sp_before_oc_block_caret = ignore # ignore/add/remove/force +sp_after_oc_block_caret = ignore # ignore/add/remove/force +sp_after_oc_msg_receiver = ignore # ignore/add/remove/force +sp_after_oc_property = ignore # ignore/add/remove/force +sp_after_oc_synchronized = ignore # ignore/add/remove/force +sp_cond_colon = force # ignore/add/remove/force +sp_cond_colon_before = ignore # ignore/add/remove/force +sp_cond_colon_after = ignore # ignore/add/remove/force +sp_cond_question = force # ignore/add/remove/force +sp_cond_question_before = ignore # ignore/add/remove/force +sp_cond_question_after = ignore # ignore/add/remove/force +sp_cond_ternary_short = ignore # ignore/add/remove/force +sp_case_label = force # ignore/add/remove/force +sp_range = ignore # ignore/add/remove/force +sp_after_for_colon = ignore # ignore/add/remove/force +sp_before_for_colon = ignore # ignore/add/remove/force +sp_extern_paren = ignore # ignore/add/remove/force +sp_cmt_cpp_start = ignore # ignore/add/remove/force +sp_cmt_cpp_doxygen = false # true/false +sp_cmt_cpp_qttr = false # true/false +sp_endif_cmt = force # ignore/add/remove/force +sp_after_new = ignore # ignore/add/remove/force +sp_between_new_paren = ignore # ignore/add/remove/force +sp_after_newop_paren = ignore # ignore/add/remove/force +sp_inside_newop_paren = ignore # ignore/add/remove/force +sp_inside_newop_paren_open = ignore # ignore/add/remove/force +sp_inside_newop_paren_close = ignore # ignore/add/remove/force +sp_before_tr_emb_cmt = force # ignore/add/remove/force +sp_num_before_tr_emb_cmt = 1 # unsigned number +sp_annotation_paren = ignore # ignore/add/remove/force +sp_skip_vbrace_tokens = false # true/false +sp_after_noexcept = ignore # ignore/add/remove/force +sp_vala_after_translation = ignore # ignore/add/remove/force +force_tab_after_define = false # true/false +indent_columns = 4 # unsigned number +indent_continue = 0 # number +indent_continue_class_head = 0 # unsigned number +indent_single_newlines = false # true/false +indent_param = 0 # unsigned number +indent_with_tabs = 0 # unsigned number +indent_cmt_with_tabs = false # true/false +indent_align_string = true # true/false +indent_xml_string = 0 # unsigned number +indent_brace = 0 # unsigned number +indent_braces = false # true/false +indent_braces_no_func = false # true/false +indent_braces_no_class = false # true/false +indent_braces_no_struct = false # true/false +indent_brace_parent = false # true/false +indent_paren_open_brace = false # true/false +indent_cs_delegate_brace = false # true/false +indent_cs_delegate_body = false # true/false +indent_namespace = false # true/false +indent_namespace_single_indent = false # true/false +indent_namespace_level = 0 # unsigned number +indent_namespace_limit = 0 # unsigned number +indent_extern = false # true/false +indent_class = true # true/false +indent_class_colon = true # true/false +indent_class_on_colon = false # true/false +indent_constr_colon = false # true/false +indent_ctor_init_leading = 2 # unsigned number +indent_ctor_init = 0 # number +indent_else_if = false # true/false +indent_var_def_blk = 0 # number +indent_var_def_cont = false # true/false +indent_shift = false # true/false +indent_func_def_force_col1 = false # true/false +indent_func_call_param = false # true/false +indent_func_def_param = false # true/false +indent_func_proto_param = false # true/false +indent_func_class_param = false # true/false +indent_func_ctor_var_param = false # true/false +indent_template_param = false # true/false +indent_func_param_double = false # true/false +indent_func_const = 0 # unsigned number +indent_func_throw = 0 # unsigned number +indent_member = 3 # unsigned number +indent_member_single = false # true/false +indent_sing_line_comments = 0 # unsigned number +indent_relative_single_line_comments = false # true/false +indent_switch_case = 4 # unsigned number +indent_switch_pp = true # true/false +indent_case_shift = 0 # unsigned number +indent_case_brace = 3 # number +indent_col1_comment = false # true/false +indent_col1_multi_string_literal = false # true/false +indent_label = 1 # number +indent_access_spec = 1 # number +indent_access_spec_body = false # true/false +indent_paren_nl = false # true/false +indent_paren_close = 0 # unsigned number +indent_paren_after_func_def = false # true/false +indent_paren_after_func_decl = false # true/false +indent_paren_after_func_call = false # true/false +indent_comma_paren = false # true/false +indent_bool_paren = false # true/false +indent_semicolon_for_paren = false # true/false +indent_first_bool_expr = false # true/false +indent_first_for_expr = false # true/false +indent_square_nl = false # true/false +indent_preserve_sql = false # true/false +indent_align_assign = true # true/false +indent_align_paren = true # true/false +indent_oc_block = false # true/false +indent_oc_block_msg = 0 # unsigned number +indent_oc_msg_colon = 0 # unsigned number +indent_oc_msg_prioritize_first_colon = true # true/false +indent_oc_block_msg_xcode_style = false # true/false +indent_oc_block_msg_from_keyword = false # true/false +indent_oc_block_msg_from_colon = false # true/false +indent_oc_block_msg_from_caret = false # true/false +indent_oc_block_msg_from_brace = false # true/false +indent_min_vbrace_open = 0 # unsigned number +indent_vbrace_open_on_tabstop = false # true/false +indent_token_after_brace = true # true/false +indent_cpp_lambda_body = false # true/false +indent_using_block = true # true/false +indent_ternary_operator = 0 # unsigned number +indent_off_after_return_new = false # true/false +indent_single_after_return = false # true/false +indent_ignore_asm_block = false # true/false +nl_collapse_empty_body = false # true/false +nl_assign_leave_one_liners = true # true/false +nl_class_leave_one_liners = true # true/false +nl_enum_leave_one_liners = false # true/false +nl_getset_leave_one_liners = false # true/false +nl_cs_property_leave_one_liners = false # true/false +nl_func_leave_one_liners = false # true/false +nl_cpp_lambda_leave_one_liners = false # true/false +nl_if_leave_one_liners = false # true/false +nl_while_leave_one_liners = false # true/false +nl_for_leave_one_liners = false # true/false +nl_oc_msg_leave_one_liner = false # true/false +nl_oc_mdef_brace = ignore # ignore/add/remove/force +nl_oc_block_brace = ignore # ignore/add/remove/force +nl_oc_interface_brace = ignore # ignore/add/remove/force +nl_oc_implementation_brace = ignore # ignore/add/remove/force +nl_start_of_file = remove # ignore/add/remove/force +nl_start_of_file_min = 0 # unsigned number +nl_end_of_file = force # ignore/add/remove/force +nl_end_of_file_min = 1 # unsigned number +nl_assign_brace = add # ignore/add/remove/force +nl_assign_square = ignore # ignore/add/remove/force +nl_tsquare_brace = ignore # ignore/add/remove/force +nl_after_square_assign = ignore # ignore/add/remove/force +nl_fcall_brace = add # ignore/add/remove/force +nl_enum_brace = force # ignore/add/remove/force +nl_enum_class = ignore # ignore/add/remove/force +nl_enum_class_identifier = ignore # ignore/add/remove/force +nl_enum_identifier_colon = ignore # ignore/add/remove/force +nl_enum_colon_type = ignore # ignore/add/remove/force +nl_struct_brace = force # ignore/add/remove/force +nl_union_brace = force # ignore/add/remove/force +nl_if_brace = add # ignore/add/remove/force +nl_brace_else = add # ignore/add/remove/force +nl_elseif_brace = ignore # ignore/add/remove/force +nl_else_brace = add # ignore/add/remove/force +nl_else_if = ignore # ignore/add/remove/force +nl_before_if_closing_paren = ignore # ignore/add/remove/force +nl_brace_finally = ignore # ignore/add/remove/force +nl_finally_brace = ignore # ignore/add/remove/force +nl_try_brace = ignore # ignore/add/remove/force +nl_getset_brace = force # ignore/add/remove/force +nl_for_brace = add # ignore/add/remove/force +nl_catch_brace = ignore # ignore/add/remove/force +nl_oc_catch_brace = ignore # ignore/add/remove/force +nl_brace_catch = ignore # ignore/add/remove/force +nl_oc_brace_catch = ignore # ignore/add/remove/force +nl_brace_square = ignore # ignore/add/remove/force +nl_brace_fparen = ignore # ignore/add/remove/force +nl_while_brace = add # ignore/add/remove/force +nl_scope_brace = ignore # ignore/add/remove/force +nl_unittest_brace = ignore # ignore/add/remove/force +nl_version_brace = ignore # ignore/add/remove/force +nl_using_brace = ignore # ignore/add/remove/force +nl_brace_brace = ignore # ignore/add/remove/force +nl_do_brace = add # ignore/add/remove/force +nl_brace_while = ignore # ignore/add/remove/force +nl_switch_brace = add # ignore/add/remove/force +nl_synchronized_brace = ignore # ignore/add/remove/force +nl_multi_line_cond = false # true/false +nl_multi_line_define = true # true/false +nl_before_case = true # true/false +nl_after_case = true # true/false +nl_case_colon_brace = ignore # ignore/add/remove/force +nl_before_throw = ignore # ignore/add/remove/force +nl_namespace_brace = ignore # ignore/add/remove/force +nl_template_class = ignore # ignore/add/remove/force +nl_class_brace = ignore # ignore/add/remove/force +nl_class_init_args = ignore # ignore/add/remove/force +nl_constr_init_args = ignore # ignore/add/remove/force +nl_enum_own_lines = ignore # ignore/add/remove/force +nl_func_type_name = remove # ignore/add/remove/force +nl_func_type_name_class = ignore # ignore/add/remove/force +nl_func_class_scope = ignore # ignore/add/remove/force +nl_func_scope_name = ignore # ignore/add/remove/force +nl_func_proto_type_name = remove # ignore/add/remove/force +nl_func_paren = remove # ignore/add/remove/force +nl_func_paren_empty = ignore # ignore/add/remove/force +nl_func_def_paren = remove # ignore/add/remove/force +nl_func_def_paren_empty = ignore # ignore/add/remove/force +nl_func_call_paren = ignore # ignore/add/remove/force +nl_func_call_paren_empty = ignore # ignore/add/remove/force +nl_func_decl_start = remove # ignore/add/remove/force +nl_func_def_start = remove # ignore/add/remove/force +nl_func_decl_start_single = ignore # ignore/add/remove/force +nl_func_def_start_single = ignore # ignore/add/remove/force +nl_func_decl_start_multi_line = false # true/false +nl_func_def_start_multi_line = false # true/false +nl_func_decl_args = add # ignore/add/remove/force +nl_func_def_args = add # ignore/add/remove/force +nl_func_decl_args_multi_line = false # true/false +nl_func_def_args_multi_line = false # true/false +nl_func_decl_end = remove # ignore/add/remove/force +nl_func_def_end = remove # ignore/add/remove/force +nl_func_decl_end_single = ignore # ignore/add/remove/force +nl_func_def_end_single = ignore # ignore/add/remove/force +nl_func_decl_end_multi_line = false # true/false +nl_func_def_end_multi_line = false # true/false +nl_func_decl_empty = ignore # ignore/add/remove/force +nl_func_def_empty = ignore # ignore/add/remove/force +nl_func_call_empty = ignore # ignore/add/remove/force +nl_func_call_start = ignore # ignore/add/remove/force +nl_func_call_start_multi_line = false # true/false +nl_func_call_args_multi_line = false # true/false +nl_func_call_end_multi_line = false # true/false +nl_oc_msg_args = false # true/false +nl_fdef_brace = add # ignore/add/remove/force +nl_fdef_brace_cond = ignore # ignore/add/remove/force +nl_cpp_ldef_brace = ignore # ignore/add/remove/force +nl_return_expr = ignore # ignore/add/remove/force +nl_after_semicolon = true # true/false +nl_paren_dbrace_open = ignore # ignore/add/remove/force +nl_type_brace_init_lst = ignore # ignore/add/remove/force +nl_type_brace_init_lst_open = ignore # ignore/add/remove/force +nl_type_brace_init_lst_close = ignore # ignore/add/remove/force +nl_after_brace_open = true # true/false +nl_after_brace_open_cmt = false # true/false +nl_after_vbrace_open = false # true/false +nl_after_vbrace_open_empty = false # true/false +nl_after_brace_close = true # true/false +nl_after_vbrace_close = false # true/false +nl_brace_struct_var = ignore # ignore/add/remove/force +nl_define_macro = false # true/false +nl_squeeze_paren_close = false # true/false +nl_squeeze_ifdef = true # true/false +nl_squeeze_ifdef_top_level = false # true/false +nl_before_if = force # ignore/add/remove/force +nl_after_if = force # ignore/add/remove/force +nl_before_for = force # ignore/add/remove/force +nl_after_for = force # ignore/add/remove/force +nl_before_while = force # ignore/add/remove/force +nl_after_while = force # ignore/add/remove/force +nl_before_switch = force # ignore/add/remove/force +nl_after_switch = force # ignore/add/remove/force +nl_before_synchronized = ignore # ignore/add/remove/force +nl_after_synchronized = ignore # ignore/add/remove/force +nl_before_do = force # ignore/add/remove/force +nl_after_do = force # ignore/add/remove/force +nl_before_return = false # true/false +nl_after_return = true # true/false +nl_ds_struct_enum_cmt = false # true/false +nl_ds_struct_enum_close_brace = false # true/false +nl_class_colon = ignore # ignore/add/remove/force +nl_constr_colon = ignore # ignore/add/remove/force +nl_namespace_two_to_one_liner = false # true/false +nl_create_if_one_liner = false # true/false +nl_create_for_one_liner = false # true/false +nl_create_while_one_liner = false # true/false +nl_create_func_def_one_liner = false # true/false +nl_split_if_one_liner = false # true/false +nl_split_for_one_liner = false # true/false +nl_split_while_one_liner = false # true/false +nl_max = 4 # unsigned number +nl_max_blank_in_func = 0 # unsigned number +nl_before_func_body_proto = 0 # unsigned number +nl_before_func_body_def = 0 # unsigned number +nl_before_func_class_proto = 0 # unsigned number +nl_before_func_class_def = 0 # unsigned number +nl_after_func_proto = 0 # unsigned number +nl_after_func_proto_group = 1 # unsigned number +nl_after_func_class_proto = 0 # unsigned number +nl_after_func_class_proto_group = 0 # unsigned number +nl_class_leave_one_liner_groups = false # true/false +nl_after_func_body = 0 # unsigned number +nl_after_func_body_class = 2 # unsigned number +nl_after_func_body_one_liner = 0 # unsigned number +nl_func_var_def_blk = 1 # unsigned number +nl_typedef_blk_start = 0 # unsigned number +nl_typedef_blk_end = 0 # unsigned number +nl_typedef_blk_in = 0 # unsigned number +nl_var_def_blk_start = 0 # unsigned number +nl_var_def_blk_end = 0 # unsigned number +nl_var_def_blk_in = 0 # unsigned number +nl_before_block_comment = 2 # unsigned number +nl_before_c_comment = 0 # unsigned number +nl_before_cpp_comment = 0 # unsigned number +nl_after_multiline_comment = false # true/false +nl_after_label_colon = false # true/false +nl_after_struct = 0 # unsigned number +nl_before_class = 0 # unsigned number +nl_after_class = 0 # unsigned number +nl_before_access_spec = 0 # unsigned number +nl_after_access_spec = 0 # unsigned number +nl_comment_func_def = 0 # unsigned number +nl_after_try_catch_finally = 0 # unsigned number +nl_around_cs_property = 0 # unsigned number +nl_between_get_set = 0 # unsigned number +nl_property_brace = ignore # ignore/add/remove/force +nl_inside_namespace = 0 # unsigned number +eat_blanks_after_open_brace = true # true/false +eat_blanks_before_close_brace = true # true/false +nl_remove_extra_newlines = 0 # unsigned number +nl_after_annotation = ignore # ignore/add/remove/force +nl_between_annotation = ignore # ignore/add/remove/force +pos_arith = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force +pos_assign = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force +pos_bool = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force +pos_compare = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force +pos_conditional = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force +pos_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force +pos_enum_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force +pos_class_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force +pos_constr_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force +pos_class_colon = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force +pos_constr_colon = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force +code_width = 0 # unsigned number +ls_for_split_full = false # true/false +ls_func_split_full = false # true/false +ls_code_width = false # true/false +align_keep_tabs = false # true/false +align_with_tabs = false # true/false +align_on_tabstop = false # true/false +align_number_right = false # true/false +align_keep_extra_space = false # true/false +align_func_params = false # true/false +align_func_params_span = 0 # unsigned number +align_func_params_thresh = 0 # number +align_func_params_gap = 0 # unsigned number +align_constr_value_span = 0 # unsigned number +align_constr_value_thresh = 0 # number +align_constr_value_gap = 0 # unsigned number +align_same_func_call_params = false # true/false +align_same_func_call_params_span = 0 # unsigned number +align_same_func_call_params_thresh = 0 # number +align_var_def_span = 0 # unsigned number +align_var_def_star_style = 0 # unsigned number +align_var_def_amp_style = 1 # unsigned number +align_var_def_thresh = 16 # number +align_var_def_gap = 0 # unsigned number +align_var_def_colon = false # true/false +align_var_def_colon_gap = 0 # unsigned number +align_var_def_attribute = false # true/false +align_var_def_inline = false # true/false +align_assign_span = 0 # unsigned number +align_assign_func_proto_span = 0 # unsigned number +align_assign_thresh = 12 # number +align_assign_decl_func = 0 # unsigned number +align_enum_equ_span = 0 # unsigned number +align_enum_equ_thresh = 0 # number +align_var_class_span = 0 # unsigned number +align_var_class_thresh = 0 # number +align_var_class_gap = 0 # unsigned number +align_var_struct_span = 0 # unsigned number +align_var_struct_thresh = 0 # number +align_var_struct_gap = 0 # unsigned number +align_struct_init_span = 3 # unsigned number +align_typedef_span = 5 # unsigned number +align_typedef_gap = 3 # unsigned number +align_typedef_func = 0 # unsigned number +align_typedef_star_style = 1 # unsigned number +align_typedef_amp_style = 1 # unsigned number +align_right_cmt_span = 3 # unsigned number +align_right_cmt_gap = 0 # unsigned number +align_right_cmt_mix = false # true/false +align_right_cmt_same_level = false # true/false +align_right_cmt_at_col = 0 # unsigned number +align_func_proto_span = 0 # unsigned number +align_func_proto_thresh = 0 # number +align_func_proto_gap = 0 # unsigned number +align_on_operator = false # true/false +align_mix_var_proto = false # true/false +align_single_line_func = false # true/false +align_single_line_brace = false # true/false +align_single_line_brace_gap = 0 # unsigned number +align_oc_msg_spec_span = 0 # unsigned number +align_nl_cont = true # true/false +align_pp_define_together = false # true/false +align_pp_define_span = 3 # unsigned number +align_pp_define_gap = 4 # unsigned number +align_left_shift = true # true/false +align_asm_colon = false # true/false +align_oc_msg_colon_span = 0 # unsigned number +align_oc_msg_colon_first = false # true/false +align_oc_decl_colon = false # true/false +cmt_width = 0 # unsigned number +cmt_reflow_mode = 0 # unsigned number +cmt_convert_tab_to_spaces = false # true/false +cmt_indent_multi = true # true/false +cmt_c_group = false # true/false +cmt_c_nl_start = false # true/false +cmt_c_nl_end = false # true/false +cmt_cpp_to_c = true # true/false +cmt_cpp_group = false # true/false +cmt_cpp_nl_start = false # true/false +cmt_cpp_nl_end = false # true/false +cmt_star_cont = true # true/false +cmt_sp_before_star_cont = 0 # unsigned number +cmt_sp_after_star_cont = 0 # unsigned number +cmt_multi_check_last = true # true/false +cmt_multi_first_len_minimum = 4 # unsigned number +cmt_insert_file_header = "" # string +cmt_insert_file_footer = "" # string +cmt_insert_func_header = "" # string +cmt_insert_class_header = "" # string +cmt_insert_oc_msg_header = "" # string +cmt_insert_before_preproc = false # true/false +cmt_insert_before_inlines = true # true/false +cmt_insert_before_ctor_dtor = false # true/false +mod_full_brace_do = add # ignore/add/remove/force +mod_full_brace_for = add # ignore/add/remove/force +mod_full_brace_function = ignore # ignore/add/remove/force +mod_full_brace_if = add # ignore/add/remove/force +mod_full_brace_if_chain = false # true/false +mod_full_brace_if_chain_only = false # true/false +mod_full_brace_while = add # ignore/add/remove/force +mod_full_brace_using = ignore # ignore/add/remove/force +mod_full_brace_nl = 0 # unsigned number +mod_full_brace_nl_block_rem_mlcond = false # true/false +mod_paren_on_return = ignore # ignore/add/remove/force +mod_pawn_semicolon = false # true/false +mod_full_paren_if_bool = true # true/false +mod_remove_extra_semicolon = true # true/false +mod_add_long_function_closebrace_comment = 0 # unsigned number +mod_add_long_namespace_closebrace_comment = 0 # unsigned number +mod_add_long_class_closebrace_comment = 0 # unsigned number +mod_add_long_switch_closebrace_comment = 0 # unsigned number +mod_add_long_ifdef_endif_comment = 10 # unsigned number +mod_add_long_ifdef_else_comment = 10 # unsigned number +mod_sort_import = false # true/false +mod_sort_using = false # true/false +mod_sort_include = false # true/false +mod_move_case_break = false # true/false +mod_case_brace = remove # ignore/add/remove/force +mod_remove_empty_return = true # true/false +mod_enum_last_comma = ignore # ignore/add/remove/force +mod_sort_oc_properties = false # true/false +mod_sort_oc_property_class_weight = 0 # number +mod_sort_oc_property_thread_safe_weight = 0 # number +mod_sort_oc_property_readwrite_weight = 0 # number +mod_sort_oc_property_reference_weight = 0 # number +mod_sort_oc_property_getter_weight = 0 # number +mod_sort_oc_property_setter_weight = 0 # number +mod_sort_oc_property_nullability_weight = 0 # number +pp_indent = force # ignore/add/remove/force +pp_indent_at_level = true # true/false +pp_indent_count = 4 # unsigned number +pp_space = remove # ignore/add/remove/force +pp_space_count = 0 # unsigned number +pp_indent_region = 0 # number +pp_region_indent_code = false # true/false +pp_indent_if = 0 # number +pp_if_indent_code = true # true/false +pp_define_at_level = false # true/false +pp_ignore_define_body = false # true/false +pp_indent_case = true # true/false +pp_indent_func_def = true # true/false +pp_indent_extern = true # true/false +pp_indent_brace = false # true/false +include_category_0 = "" # string +include_category_1 = "" # string +include_category_2 = "" # string +use_indent_func_call_param = true # true/false +use_indent_continue_only_once = false # true/false +indent_cpp_lambda_only_once = false # true/false +use_options_overriding_for_qt_macros = true # true/false +warn_level_tabs_found_in_verbatim_string_literals = 2 # unsigned number diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 423a94d910..25bb1eaa26 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -494,31 +494,6 @@ components/fatfs/src/ff.h components/fatfs/src/ffconf.h components/fatfs/src/ffsystem.c components/fatfs/src/ffunicode.c -components/freertos/FreeRTOS-Kernel-SMP/croutine.c -components/freertos/FreeRTOS-Kernel-SMP/event_groups.c -components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h -components/freertos/FreeRTOS-Kernel-SMP/include/freertos/StackMacros.h -components/freertos/FreeRTOS-Kernel-SMP/include/freertos/atomic.h -components/freertos/FreeRTOS-Kernel-SMP/include/freertos/croutine.h -components/freertos/FreeRTOS-Kernel-SMP/include/freertos/deprecated_definitions.h -components/freertos/FreeRTOS-Kernel-SMP/include/freertos/event_groups.h -components/freertos/FreeRTOS-Kernel-SMP/include/freertos/list.h -components/freertos/FreeRTOS-Kernel-SMP/include/freertos/message_buffer.h -components/freertos/FreeRTOS-Kernel-SMP/include/freertos/mpu_prototypes.h -components/freertos/FreeRTOS-Kernel-SMP/include/freertos/mpu_wrappers.h -components/freertos/FreeRTOS-Kernel-SMP/include/freertos/portable.h -components/freertos/FreeRTOS-Kernel-SMP/include/freertos/projdefs.h -components/freertos/FreeRTOS-Kernel-SMP/include/freertos/queue.h -components/freertos/FreeRTOS-Kernel-SMP/include/freertos/semphr.h -components/freertos/FreeRTOS-Kernel-SMP/include/freertos/stack_macros.h -components/freertos/FreeRTOS-Kernel-SMP/include/freertos/stream_buffer.h -components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h -components/freertos/FreeRTOS-Kernel-SMP/include/freertos/timers.h -components/freertos/FreeRTOS-Kernel-SMP/list.c -components/freertos/FreeRTOS-Kernel-SMP/queue.c -components/freertos/FreeRTOS-Kernel-SMP/stream_buffer.c -components/freertos/FreeRTOS-Kernel-SMP/tasks.c -components/freertos/FreeRTOS-Kernel-SMP/timers.c components/hal/include/hal/dac_types.h components/hal/spi_slave_hal.c components/hal/spi_slave_hal_iram.c From 888678d102b5b879e17735688f5cf7efd2a8a6ff Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Fri, 2 Feb 2024 23:33:27 +0800 Subject: [PATCH 2/4] feat(freertos/smp): Add ESP-IDF specific modifications - Add ESP-IDF specific modifications to FreeRTOS-Kernel-SMP source code - Update IDF addition source files to support V11 kernel --- .../include/freertos/FreeRTOS.h | 25 ++++++++++ .../include/freertos/task.h | 4 +- .../freertos/FreeRTOS-Kernel-SMP/tasks.c | 47 ++++++++++++------- .../freertos_tasks_c_additions.h | 26 +++++----- .../include/freertos/idf_additions.h | 17 ++++--- 5 files changed, 77 insertions(+), 42 deletions(-) diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h index 6efa94bf27..b4c745b23c 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h @@ -3262,4 +3262,29 @@ typedef StaticStreamBuffer_t StaticMessageBuffer_t; #endif /* *INDENT-ON* */ +/*----------------------------------------------------------- +* IDF Compatibility +*----------------------------------------------------------*/ + +#ifdef ESP_PLATFORM + +/* + * Include ESP-IDF API additions implicitly for compatibility reasons. + * + * ESP-IDF API additions were previously added directly to FreeRTOS headers + * (e.g., task.h, queue.h). These APIs have now been moved to + * idf_additions.h. + * + * To ensure there are no breaking changes, we include idf_additions.h + * implicitly here so that those API additions are still accessible. Given + * that FreeRTOS.h must be included first before calling any FreeRTOS API, + * any existing source code can continue using these relocated APIs without + * any additional header inclusions via this implicit inclusion. + * + * Todo: Deprecate this implicit inclusion by ESP-IDF v6.0 (IDF-8126) + */ + #include "freertos/idf_additions.h" + +#endif /* ESP_PLATFORM */ + #endif /* INC_FREERTOS_H */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h index 73af157edc..4ecc60acf4 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h @@ -3578,9 +3578,7 @@ TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; /* * Return the handle of the task running on specified core. */ -#if ( configNUMBER_OF_CORES > 1 ) - TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID ) PRIVILEGED_FUNCTION; -#endif +TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID ) PRIVILEGED_FUNCTION; /* * Shortcut used by the queue implementation to prevent unnecessary call to diff --git a/components/freertos/FreeRTOS-Kernel-SMP/tasks.c b/components/freertos/FreeRTOS-Kernel-SMP/tasks.c index d021999871..2ff460167b 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/tasks.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/tasks.c @@ -483,7 +483,16 @@ PRIVILEGED_DATA static List_t xPendingReadyList; /**< Ta PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U; PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT; PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY; -PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE; +#if ( ( ESP_PLATFORM == 1 ) && ( configNUM_CORES > 1 ) ) + +/* + * Workaround for non-thread safe multi-core OS startup (see IDF-4524) + */ +PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunningPerCore[ configNUM_CORES ] = { pdFALSE }; + #define xSchedulerRunning xSchedulerRunningPerCore[ portGET_CORE_ID() ] +#else // ( ESP_PLATFORM == 1 ) && ( configNUM_CORES > 1 ) + PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE; +#endif // ( ESP_PLATFORM == 1 ) && ( configNUM_CORES > 1 ) PRIVILEGED_DATA static volatile TickType_t xPendedTicks = ( TickType_t ) 0U; PRIVILEGED_DATA static volatile BaseType_t xYieldPendings[ configNUMBER_OF_CORES ] = { pdFALSE }; PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0; @@ -6552,24 +6561,28 @@ static void prvResetNextTaskUnblockTime( void ) return xReturn; } - - TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID ) - { - TaskHandle_t xReturn = NULL; - - traceENTER_xTaskGetCurrentTaskHandleForCore( xCoreID ); - - if( taskVALID_CORE_ID( xCoreID ) != pdFALSE ) - { - xReturn = pxCurrentTCBs[ xCoreID ]; - } - - traceRETURN_xTaskGetCurrentTaskHandleForCore( xReturn ); - - return xReturn; - } #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ + TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID ) + { + TaskHandle_t xReturn = NULL; + + traceENTER_xTaskGetCurrentTaskHandleForCore( xCoreID ); + + if( taskVALID_CORE_ID( xCoreID ) != pdFALSE ) + { + #if ( configNUMBER_OF_CORES == 1 ) + xReturn = pxCurrentTCB; + #else /* #if ( configNUMBER_OF_CORES == 1 ) */ + xReturn = pxCurrentTCBs[ xCoreID ]; + #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ + } + + traceRETURN_xTaskGetCurrentTaskHandleForCore( xReturn ); + + return xReturn; + } + #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/components/freertos/esp_additions/freertos_tasks_c_additions.h b/components/freertos/esp_additions/freertos_tasks_c_additions.h index ef70d65dac..76317c2028 100644 --- a/components/freertos/esp_additions/freertos_tasks_c_additions.h +++ b/components/freertos/esp_additions/freertos_tasks_c_additions.h @@ -440,7 +440,7 @@ BaseType_t xTaskGetCoreID( TaskHandle_t xTask ) } /*----------------------------------------------------------*/ -#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) +#if ( ( !CONFIG_FREERTOS_SMP ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) TaskHandle_t xTaskGetIdleTaskHandleForCore( BaseType_t xCoreID ) { @@ -451,10 +451,10 @@ BaseType_t xTaskGetCoreID( TaskHandle_t xTask ) return xIdleTaskHandle[ xCoreID ]; } -#endif /* INCLUDE_xTaskGetIdleTaskHandle */ +#endif /* ( ( !CONFIG_FREERTOS_SMP ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */ /*----------------------------------------------------------*/ -#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) +#if ( ( !CONFIG_FREERTOS_SMP ) && ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) ) TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID ) { @@ -478,7 +478,7 @@ BaseType_t xTaskGetCoreID( TaskHandle_t xTask ) return xReturn; } -#endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */ +#endif /* ( ( !CONFIG_FREERTOS_SMP ) && ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) ) */ /*----------------------------------------------------------*/ #if ( !CONFIG_FREERTOS_SMP && ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) @@ -743,7 +743,11 @@ uint8_t * pxTaskGetStackStart( TaskHandle_t xTask ) if( xYieldRequired != pdFALSE ) { - taskYIELD_IF_USING_PREEMPTION(); + #if CONFIG_FREERTOS_SMP + taskYIELD_TASK_CORE_IF_USING_PREEMPTION( pxTCB ); + #else + taskYIELD_IF_USING_PREEMPTION(); + #endif } } } @@ -849,16 +853,8 @@ uint8_t * pxTaskGetStackStart( TaskHandle_t xTask ) } else { - /* We have a task; return its reentrant struct. */ - #if ( CONFIG_FREERTOS_SMP ) - { - ret = &pxCurTask->xNewLib_reent; - } - #else /* CONFIG_FREERTOS_SMP */ - { - ret = &pxCurTask->xTLSBlock; - } - #endif /* CONFIG_FREERTOS_SMP */ + /* We have a currently executing task. Return its reentrant struct. */ + ret = &pxCurTask->xTLSBlock; } return ret; diff --git a/components/freertos/esp_additions/include/freertos/idf_additions.h b/components/freertos/esp_additions/include/freertos/idf_additions.h index 6c989f05be..b9fb9c47a0 100644 --- a/components/freertos/esp_additions/include/freertos/idf_additions.h +++ b/components/freertos/esp_additions/include/freertos/idf_additions.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -131,17 +131,21 @@ */ BaseType_t xTaskGetCoreID( TaskHandle_t xTask ); +#if ( ( !CONFIG_FREERTOS_SMP ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) + /** * @brief Get the handle of idle task for the given core. * * [refactor-todo] See if this needs to be deprecated (IDF-8145) * - * @note If CONFIG_FREERTOS_SMP is enabled, please call xTaskGetIdleTaskHandle() - * instead. * @param xCoreID The core to query * @return Handle of the idle task for the queried core */ -TaskHandle_t xTaskGetIdleTaskHandleForCore( BaseType_t xCoreID ); + TaskHandle_t xTaskGetIdleTaskHandleForCore( BaseType_t xCoreID ); + +#endif /* ( ( !CONFIG_FREERTOS_SMP ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */ + +#if ( ( !CONFIG_FREERTOS_SMP ) && ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) ) /** * @brief Get the handle of the task currently running on a certain core @@ -152,13 +156,12 @@ TaskHandle_t xTaskGetIdleTaskHandleForCore( BaseType_t xCoreID ); * * [refactor-todo] See if this needs to be deprecated (IDF-8145) * - * @note If CONFIG_FREERTOS_SMP is enabled, please call xTaskGetCurrentTaskHandleCPU() - * instead. * @param xCoreID The core to query * @return Handle of the current task running on the queried core */ -TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID ); + TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID ); +#endif /* ( ( !CONFIG_FREERTOS_SMP ) && ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) ) */ #if ( !CONFIG_FREERTOS_SMP && ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) From 83c686c74402ebb64a1aed46f8ee43e6828f99c5 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Fri, 2 Feb 2024 23:37:36 +0800 Subject: [PATCH 3/4] feat(freertos/smp): Update ports to support Amazon FreeRTOS v11.0.1 - vTaskPreemptionDisable()/vTaskPreemptionEnable() are no longer available in single-core builds. - xTaskIncrementTick() calls must now be wrapped by critical section - Minimal Idle Task renamed to Passive Idle Task - Port critical section APIs updated --- .../linux/include/freertos/portmacro.h | 18 ++----- .../FreeRTOS-Kernel-SMP/portable/linux/port.c | 4 +- .../riscv/include/freertos/portmacro.h | 35 ++++++++++---- .../FreeRTOS-Kernel-SMP/portable/riscv/port.c | 22 +++++---- .../portable/riscv/portasm.S | 4 ++ .../xtensa/include/freertos/portmacro.h | 47 ++++++++++--------- .../portable/xtensa/port.c | 30 +++++++----- .../portable/xtensa/portasm.S | 4 ++ .../FreeRTOS-Kernel-SMP/porting_notes.md | 41 ++++------------ components/freertos/Kconfig | 7 +-- .../config/include/freertos/FreeRTOSConfig.h | 7 +-- .../include/freertos/FreeRTOSConfig_arch.h | 2 +- .../include/freertos/FreeRTOSConfig_arch.h | 19 ++++---- .../include/freertos/FreeRTOSConfig_arch.h | 19 ++++---- .../freertos_tasks_c_additions.h | 2 + components/freertos/linker_common.lf | 2 + components/freertos/port_common.c | 10 ++++ components/freertos/port_systick.c | 2 + .../test_apps/freertos/port/test_fpu_in_isr.c | 4 +- .../freertos/port/test_fpu_in_task.c | 4 +- 20 files changed, 148 insertions(+), 135 deletions(-) diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/linux/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/linux/include/freertos/portmacro.h index 9937260b05..f4ee05e14e 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/linux/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/linux/include/freertos/portmacro.h @@ -6,7 +6,7 @@ * * SPDX-License-Identifier: MIT * - * SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -110,15 +110,16 @@ BaseType_t xPortCheckIfInISR(void); // ------------------ Critical Sections -------------------- +#if ( configNUMBER_OF_CORES > 1 ) /* These are always called with interrupts already disabled. We simply need to get/release the spinlocks */ - extern portMUX_TYPE port_xTaskLock; extern portMUX_TYPE port_xISRLock; void vPortTakeLock( portMUX_TYPE *lock ); void vPortReleaseLock( portMUX_TYPE *lock ); +#endif /* configNUMBER_OF_CORES > 1 */ // ---------------------- Yielding ------------------------- @@ -151,18 +152,9 @@ void vPortCleanUpTCB ( void *pxTCB ); #define portDISABLE_INTERRUPTS() xPortSetInterruptMask() #define portENABLE_INTERRUPTS() vPortClearInterruptMask(0) -#define portRESTORE_INTERRUPTS(x) vPortClearInterruptMask(x) // ------------------ Critical Sections -------------------- -#define portGET_TASK_LOCK() vPortTakeLock(&port_xTaskLock) -#define portRELEASE_TASK_LOCK() vPortReleaseLock(&port_xTaskLock) -#define portGET_ISR_LOCK() vPortTakeLock(&port_xISRLock) -#define portRELEASE_ISR_LOCK() vPortReleaseLock(&port_xISRLock) - -//Critical sections used by FreeRTOS SMP -extern void vTaskEnterCritical( void ); -extern void vTaskExitCritical( void ); #define portENTER_CRITICAL_SMP() vTaskEnterCritical(); #define portEXIT_CRITICAL_SMP() vTaskExitCritical(); @@ -286,8 +278,8 @@ void vPortExitCriticalIDF(void); // ---------------------- Yielding ------------------------- -// Added for backward compatibility with IDF -#define portYIELD_WITHIN_API() vTaskYieldWithinAPI() +extern void vPortYield( void ); +#define portYIELD() vPortYield() // ----------------------- System -------------------------- diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/linux/port.c b/components/freertos/FreeRTOS-Kernel-SMP/portable/linux/port.c index c25bb0344a..aba16051f0 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/linux/port.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/linux/port.c @@ -298,7 +298,7 @@ void vPortYieldFromISR( void ) xThreadToSuspend = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); - vTaskSwitchContext(xPortGetCoreID()); + vTaskSwitchContext(); xThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); @@ -419,7 +419,7 @@ static void vPortSystemTickHandler( int sig ) #if ( configUSE_PREEMPTION == 1 ) if (xSwitchRequired == pdTRUE) { /* Select Next Task. */ - vTaskSwitchContext(xPortGetCoreID()); + vTaskSwitchContext(); pxThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h index 754e2e3d24..2e252bb421 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,15 +10,28 @@ /* Macros used instead ofsetoff() for better performance of interrupt handler */ #if CONFIG_FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES +/* +pxTopOfStack (4) + +xStateListItem (28) + +xEventListItem (28) + +uxPriority (4) +*/ #define PORT_OFFSET_PX_STACK 0x40 #else +/* +pxTopOfStack (4) + +xStateListItem (20) + +xEventListItem (20) + +uxPriority (4) +*/ #define PORT_OFFSET_PX_STACK 0x30 #endif /* #if CONFIG_FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES */ -#define PORT_OFFSET_PX_END_OF_STACK (PORT_OFFSET_PX_STACK + \ - /* void * pxDummy6 */ 4 + \ - /* BaseType_t xDummy23[ 2 ] */ 8 + \ - /* uint8_t ucDummy7[ configMAX_TASK_NAME_LEN ] */ CONFIG_FREERTOS_MAX_TASK_NAME_LEN + \ - /* BaseType_t xDummy24 */ 4) + +#define PORT_OFFSET_PX_END_OF_STACK ( \ + PORT_OFFSET_PX_STACK \ + + 4 /* StackType_t * pxStack */ \ + + CONFIG_FREERTOS_MAX_TASK_NAME_LEN /* pcTaskName[ configMAX_TASK_NAME_LEN ] */ \ +) #ifndef __ASSEMBLER__ @@ -102,15 +115,16 @@ BaseType_t xPortCheckIfInISR(void); // ------------------ Critical Sections -------------------- +#if ( configNUMBER_OF_CORES > 1 ) /* These are always called with interrupts already disabled. We simply need to get/release the spinlocks */ - extern portMUX_TYPE port_xTaskLock; extern portMUX_TYPE port_xISRLock; void vPortTakeLock( portMUX_TYPE *lock ); void vPortReleaseLock( portMUX_TYPE *lock ); +#endif /* configNUMBER_OF_CORES > 1 */ // ---------------------- Yielding ------------------------- @@ -175,11 +189,12 @@ void vPortTCBPreDeleteHook( void *pxTCB ); // ------------------ Critical Sections -------------------- +#if ( configNUMBER_OF_CORES > 1 ) #define portGET_TASK_LOCK() vPortTakeLock(&port_xTaskLock) #define portRELEASE_TASK_LOCK() vPortReleaseLock(&port_xTaskLock) #define portGET_ISR_LOCK() vPortTakeLock(&port_xISRLock) #define portRELEASE_ISR_LOCK() vPortReleaseLock(&port_xISRLock) - +#endif /* configNUMBER_OF_CORES > 1 */ //Critical sections used by FreeRTOS SMP extern void vTaskEnterCritical( void ); @@ -314,8 +329,8 @@ static inline bool IRAM_ATTR xPortCanYield(void) return (threshold <= 1); } -// Added for backward compatibility with IDF -#define portYIELD_WITHIN_API() vTaskYieldWithinAPI() +// Defined even for configNUMBER_OF_CORES > 1 for IDF compatibility +#define portYIELD_WITHIN_API() esp_crosscore_int_send_yield(xPortGetCoreID()) // ----------------------- System -------------------------- diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c index 5af4c851f5..eb13f9e7f0 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c @@ -170,6 +170,7 @@ BaseType_t xPortCheckIfInISR(void) // ------------------ Critical Sections -------------------- +#if ( configNUMBER_OF_CORES > 1 ) void IRAM_ATTR vPortTakeLock( portMUX_TYPE *lock ) { spinlock_acquire( lock, portMUX_NO_TIMEOUT); @@ -179,6 +180,7 @@ void IRAM_ATTR vPortReleaseLock( portMUX_TYPE *lock ) { spinlock_release( lock ); } +#endif /* configNUMBER_OF_CORES > 1 */ // ---------------------- Yielding ------------------------- @@ -486,21 +488,21 @@ void vApplicationTickHook( void ) #endif extern void esp_vApplicationIdleHook(void); -#if CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK +#if CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK /* -By default, the port uses vApplicationMinimalIdleHook() to run IDF style idle -hooks. However, users may also want to provide their own vApplicationMinimalIdleHook(). -In this case, we use to -Wl,--wrap option to wrap the user provided vApplicationMinimalIdleHook() +By default, the port uses vApplicationPassiveIdleHook() to run IDF style idle +hooks. However, users may also want to provide their own vApplicationPassiveIdleHook(). +In this case, we use to -Wl,--wrap option to wrap the user provided vApplicationPassiveIdleHook() */ -extern void __real_vApplicationMinimalIdleHook( void ); -void __wrap_vApplicationMinimalIdleHook( void ) +extern void __real_vApplicationPassiveIdleHook( void ); +void __wrap_vApplicationPassiveIdleHook( void ) { esp_vApplicationIdleHook(); //Run IDF style hooks - __real_vApplicationMinimalIdleHook(); //Call the user provided vApplicationMinimalIdleHook() + __real_vApplicationPassiveIdleHook(); //Call the user provided vApplicationPassiveIdleHook() } -#else // CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK -void vApplicationMinimalIdleHook( void ) +#else // CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK +void vApplicationPassiveIdleHook( void ) { esp_vApplicationIdleHook(); //Run IDF style hooks } -#endif // CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK +#endif // CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/portasm.S b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/portasm.S index a40244c33d..e3b4ccc59d 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/portasm.S +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/portasm.S @@ -7,6 +7,10 @@ #include "portmacro.h" #if CONFIG_ESP_SYSTEM_HW_STACK_GUARD #include "esp_private/hw_stack_guard.h" +#endif + +#if CONFIG_FREERTOS_UNICORE +#define pxCurrentTCBs pxCurrentTCB #endif .global uxInterruptNesting diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h index 9198685e58..4ac4ffdb55 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -100,15 +100,16 @@ BaseType_t xPortCheckIfInISR(void); UBaseType_t uxPortEnterCriticalFromISR( void ); void vPortExitCriticalFromISR( UBaseType_t level ); +#if ( configNUMBER_OF_CORES > 1 ) /* These are always called with interrupts already disabled. We simply need to get/release the spinlocks */ - extern portMUX_TYPE port_xTaskLock; extern portMUX_TYPE port_xISRLock; void vPortTakeLock( portMUX_TYPE *lock ); void vPortReleaseLock( portMUX_TYPE *lock ); +#endif /* configNUMBER_OF_CORES > 1 */ // ---------------------- Yielding ------------------------- @@ -151,35 +152,42 @@ void vPortTCBPreDeleteHook( void *pxTCB ); // --------------------- Interrupts ------------------------ -#define portDISABLE_INTERRUPTS() ({ \ +#define portSET_INTERRUPT_MASK() ({ \ unsigned int prev_level = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); \ portbenchmarkINTERRUPT_DISABLE(); \ prev_level = ((prev_level >> XCHAL_PS_INTLEVEL_SHIFT) & XCHAL_PS_INTLEVEL_MASK); \ prev_level; \ }) - -#define portENABLE_INTERRUPTS() ({ \ - portbenchmarkINTERRUPT_RESTORE(0); \ - XTOS_SET_INTLEVEL(0); \ -}) +#define portSET_INTERRUPT_MASK_FROM_ISR() portSET_INTERRUPT_MASK() +#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK() /* -Note: XTOS_RESTORE_INTLEVEL() will overwrite entire PS register on XEA2. So we need ot make the value INTLEVEL field ourselves +Note: XTOS_RESTORE_INTLEVEL() will overwrite entire PS register on XEA2. So we need to set the value of the INTLEVEL field ourselves */ -#define portRESTORE_INTERRUPTS(x) ({ \ +#define portCLEAR_INTERRUPT_MASK(x) ({ \ unsigned int ps_reg; \ RSR(PS, ps_reg); \ ps_reg = (ps_reg & ~XCHAL_PS_INTLEVEL_MASK); \ ps_reg |= ((x << XCHAL_PS_INTLEVEL_SHIFT) & XCHAL_PS_INTLEVEL_MASK); \ XTOS_RESTORE_INTLEVEL(ps_reg); \ }) +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) portCLEAR_INTERRUPT_MASK(x) +#define portENABLE_INTERRUPTS() ({ \ + portbenchmarkINTERRUPT_RESTORE(0); \ + XTOS_SET_INTLEVEL(0); \ +}) + +/* Compatibility */ +#define portRESTORE_INTERRUPTS(x) portCLEAR_INTERRUPT_MASK(x) // ------------------ Critical Sections -------------------- +#if ( configNUMBER_OF_CORES > 1 ) #define portGET_TASK_LOCK() vPortTakeLock(&port_xTaskLock) #define portRELEASE_TASK_LOCK() vPortReleaseLock(&port_xTaskLock) #define portGET_ISR_LOCK() vPortTakeLock(&port_xISRLock) #define portRELEASE_ISR_LOCK() vPortReleaseLock(&port_xISRLock) +#endif /* configNUMBER_OF_CORES > 1 */ //Critical sections used by FreeRTOS SMP extern void vTaskEnterCritical( void ); @@ -195,17 +203,10 @@ extern void vTaskExitCritical( void ); #define portEXIT_CRITICAL(...) CHOOSE_MACRO_VA_ARG(portEXIT_CRITICAL_IDF, portEXIT_CRITICAL_SMP, ##__VA_ARGS__)(__VA_ARGS__) #endif -#define portSET_INTERRUPT_MASK_FROM_ISR() ({ \ - unsigned int cur_level; \ - RSR(PS, cur_level); \ - cur_level = (cur_level & XCHAL_PS_INTLEVEL_MASK) >> XCHAL_PS_INTLEVEL_SHIFT; \ - vTaskEnterCritical(); \ - cur_level; \ -}) -#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) ({ \ - vTaskExitCritical(); \ - portRESTORE_INTERRUPTS(x); \ -}) +extern UBaseType_t vTaskEnterCriticalFromISR( void ); +extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus ); +#define portENTER_CRITICAL_FROM_ISR() vTaskEnterCriticalFromISR() +#define portEXIT_CRITICAL_FROM_ISR(x) vTaskExitCriticalFromISR(x) // ---------------------- Yielding ------------------------- @@ -356,8 +357,8 @@ static inline bool IRAM_ATTR xPortCanYield(void) return ((ps_reg & PS_INTLEVEL_MASK) == 0); } -// Added for backward compatibility with IDF -#define portYIELD_WITHIN_API() vTaskYieldWithinAPI() +// Defined even for configNUMBER_OF_CORES > 1 for IDF compatibility +#define portYIELD_WITHIN_API() esp_crosscore_int_send_yield(xPortGetCoreID()) // ----------------------- System -------------------------- diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c index f238dbc6e6..d5010bf708 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -63,7 +63,7 @@ const DRAM_ATTR uint32_t offset_pxEndOfStack = offsetof(StaticTask_t, pxDummy8); const DRAM_ATTR uint32_t offset_cpsa = XT_CP_SIZE; /* Offset to start of the CPSA area on the stack. See uxInitialiseStackCPSA(). */ #if configNUM_CORES > 1 /* Offset to TCB_t.uxCoreAffinityMask member. Used to pin unpinned tasks that use the FPU. */ -const DRAM_ATTR uint32_t offset_uxCoreAffinityMask = offsetof(StaticTask_t, uxDummy25); +const DRAM_ATTR uint32_t offset_uxCoreAffinityMask = offsetof(StaticTask_t, uxDummy26); #if configUSE_CORE_AFFINITY != 1 #error "configUSE_CORE_AFFINITY must be 1 on multicore targets with coprocessor support" #endif @@ -72,9 +72,11 @@ const DRAM_ATTR uint32_t offset_uxCoreAffinityMask = offsetof(StaticTask_t, uxDu volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0}; // Indicates whether scheduler is running on a per-core basis unsigned int port_interruptNesting[portNUM_PROCESSORS] = {0}; // Interrupt nesting level. Increased/decreased in portasm.c, _frxt_int_enter/_frxt_int_exit +#if ( configNUMBER_OF_CORES > 1 ) //FreeRTOS SMP Locks portMUX_TYPE port_xTaskLock = portMUX_INITIALIZER_UNLOCKED; portMUX_TYPE port_xISRLock = portMUX_INITIALIZER_UNLOCKED; +#endif /* configNUMBER_OF_CORES > 1 */ /* ------------------------------------------------ IDF Compatibility -------------------------------------------------- * - These need to be defined for IDF to compile @@ -204,6 +206,7 @@ BaseType_t xPortCheckIfInISR(void) // ------------------ Critical Sections -------------------- +#if ( configNUMBER_OF_CORES > 1 ) void vPortTakeLock( portMUX_TYPE *lock ) { spinlock_acquire( lock, portMUX_NO_TIMEOUT); @@ -213,6 +216,7 @@ void vPortReleaseLock( portMUX_TYPE *lock ) { spinlock_release( lock ); } +#endif /* configNUMBER_OF_CORES > 1 */ // ---------------------- Yielding ------------------------- @@ -262,7 +266,7 @@ static void vPortCleanUpCoprocArea( void *pxTCB ) uxCoprocArea = STACKPTR_ALIGN_DOWN(16, uxCoprocArea - XT_CP_SIZE); /* Extract core ID from the affinity mask */ - xTargetCoreID = ( ( StaticTask_t * ) pxTCB )->uxDummy25 ; + xTargetCoreID = ( ( StaticTask_t * ) pxTCB )->uxDummy26; xTargetCoreID = ( BaseType_t ) __builtin_ffs( ( int ) xTargetCoreID ); assert( xTargetCoreID >= 1 ); // __builtin_ffs always returns first set index + 1 xTargetCoreID -= 1; @@ -667,21 +671,21 @@ void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, c #endif extern void esp_vApplicationIdleHook(void); -#if CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK +#if CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK /* -By default, the port uses vApplicationMinimalIdleHook() to run IDF style idle -hooks. However, users may also want to provide their own vApplicationMinimalIdleHook(). -In this case, we use to -Wl,--wrap option to wrap the user provided vApplicationMinimalIdleHook() +By default, the port uses vApplicationPassiveIdleHook() to run IDF style idle +hooks. However, users may also want to provide their own vApplicationPassiveIdleHook(). +In this case, we use to -Wl,--wrap option to wrap the user provided vApplicationPassiveIdleHook() */ -extern void __real_vApplicationMinimalIdleHook( void ); -void __wrap_vApplicationMinimalIdleHook( void ) +extern void __real_vApplicationPassiveIdleHook( void ); +void __wrap_vApplicationPassiveIdleHook( void ) { esp_vApplicationIdleHook(); //Run IDF style hooks - __real_vApplicationMinimalIdleHook(); //Call the user provided vApplicationMinimalIdleHook() + __real_vApplicationPassiveIdleHook(); //Call the user provided vApplicationPassiveIdleHook() } -#else // CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK -void vApplicationMinimalIdleHook( void ) +#else // CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK +void vApplicationPassiveIdleHook( void ) { esp_vApplicationIdleHook(); //Run IDF style hooks } -#endif // CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK +#endif // CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/portasm.S b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/portasm.S index b472be7305..b05c44f65e 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/portasm.S +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/portasm.S @@ -33,6 +33,10 @@ #define TOPOFSTACK_OFFS 0x00 /* StackType_t *pxTopOfStack */ +#if CONFIG_FREERTOS_UNICORE +#define pxCurrentTCBs pxCurrentTCB +#endif + .extern pxCurrentTCBs #if XCHAL_CP_NUM > 0 /* Offsets used to get a task's coprocessor save area (CPSA) from its TCB */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/porting_notes.md b/components/freertos/FreeRTOS-Kernel-SMP/porting_notes.md index 86504067bf..a9e7fb1b45 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/porting_notes.md +++ b/components/freertos/FreeRTOS-Kernel-SMP/porting_notes.md @@ -1,20 +1,17 @@ # Overview -This document outlines some useful notes about - -- The porting of SMP FreeRTOS to ESP-IDF -- And the difference between IDF FreeRTOS and SMP FreeRTOS +This document outlines some notes regarding the Amazon AMP FreeRTOS port in ESP-IDF # Terminology The following terms will be used in this document to avoid confusion between the different FreeRTOS versions currently in ESP-IDF -- SMP FreeRTOS: The SMP branch of the FreeRTOS kernel found [here](https://github.com/FreeRTOS/FreeRTOS-Kernel/tree/smp) +- SMP FreeRTOS: An SMP capable release of the FreeRTOS kernel described [here](https://github.com/FreeRTOS/FreeRTOS-Kernel/tree/smp) - IDF FreeRTOS: The version of FreeRTOS used in mainline ESP-IDF that contained custom modifications to support SMP features specific to the ESP chips. # Organization -This directory contains a copy of SMP FreeRTOS based off of upstream commit [8128208](https://github.com/FreeRTOS/FreeRTOS-Kernel/commit/8128208bdee1f997f83cae631b861f36aeea9b1f) +This directory contains a copy of upstream [v11.0.1](https://github.com/FreeRTOS/FreeRTOS-Kernel/tree/V11.0.1) FreeRTOS which is SMP capable. - IDF FreeRTOS remains in `components/freertos/FreeRTOS-Kernel` - SMP FreeRTOS is entirely contained in `components/freertos/FreeRTOS-Kernel-SMP` @@ -104,15 +101,15 @@ IDF FreeRTOS: SMP FreeRTOS: -- There are now two types of idle task functions. The `prvIdleTask()` and `prvMinimalIdleTask()` - - `prvMinimalIdleTask()` simply calls the `vApplicationMinimalIdleHook()` - - `prvIdleTask()` calls `prvCheckTasksWaitingTermination()`, `vApplicationIdleHook()`, `vApplicationMinimalIdleHook()`, and handles tickless idle. - - On an N core build, one `prvIdleTask()` task is created and N-1 `prvMinimalIdleTask()` tasks are created. +- There are now two types of idle task functions. The `prvIdleTask()` and `prvPassiveIdleTask()` + - `prvPassiveIdleTask()` simply calls the `vApplicationPassiveIdleHook()` + - `prvIdleTask()` calls `prvCheckTasksWaitingTermination()`, `vApplicationIdleHook()`, `vApplicationPassiveIdleHook()`, and handles tickless idling. + - On an N core build, one `prvIdleTask()` task is created and N-1 `prvPassiveIdleTask()` tasks are created. - The created idle tasks are all unpinned. The idle tasks are run on a "first come first serve" basis meaning when a core goes idle, it selects whatever available idle task it can run. Changes Made: -- The `esp_vApplicationIdleHook()` is now called from `vApplicationMinimalIdleHook()` since every idle task calls the `vApplicationMinimalIdleHook()`. +- The `esp_vApplicationIdleHook()` is now called from `vApplicationPassiveIdleHook()` since every idle task calls the `vApplicationPassiveIdleHook()`. - Since the idle tasks are unpinned, the task WDT has been updated to use the "User" feature. Thus, feeding the task watchdog now tracks which "core" has fed the task WDT instead of which specific idle task has fed. - Since `prvIdleTask()` is solely responsible for calling `prvCheckTasksWaitingTermination()` but can run on any core, multiple IDF cleanup routines are now routed through `portCLEAN_UP_TCB()` - FPU registers of a task are now cleaned up via `portCLEAN_UP_TCB() -> vPortCleanUpCoprocArea()` and can clean FPU save areas across cores. @@ -169,25 +166,3 @@ IDF FreeRTOS added multiple features/APIs that are specific to IDF. For SMP Free - If TLSP deletion callbacks are used, `configNUM_THREAD_LOCAL_STORAGE_POINTERS` will be doubled (in order to store the callback pointers in the same array as the TLSPs themselves) - `vTaskSetThreadLocalStoragePointerAndDelCallback()` moved to `freertos_tasks_c_additions.h`/`idf_additions.h` - Deletion callbacks invoked from the main idle task via `portCLEAN_UP_TCB()` - -### `xTaskGetCurrentTaskHandleForCPU()` - -- Convenience function to the get current task of a particular CPU -- Moved to `freertos_tasks_c_additions.h`/`idf_additions.h` for now - -Todo: Check if this can be upstreamed - -### `xTaskGetIdleTaskHandleForCPU()` - -- Currently moved to `freertos_tasks_c_additions.h`/`idf_additions.h` - -Todo: This needs to be deprecated as there is no longer the concept of idle tasks pinned to a particular CPU - -### `xTaskGetAffinity()` - -- Returns what core a task is pinned to, and not the task's affinity mask. -- Moved to `freertos_tasks_c_additions.h`/`idf_additions.h` and simple wraps `vTaskCoreAffinityGet()` -- If the task's affinity mask has more than one permissible core, we simply return `tskNO_AFFINITY` even if the task is not completely unpinned. - -Todo: This needs to be deprecated and users should call `vTaskCoreAffinityGet()` instead - diff --git a/components/freertos/Kconfig b/components/freertos/Kconfig index 48407ceae9..f82ac3cd44 100644 --- a/components/freertos/Kconfig +++ b/components/freertos/Kconfig @@ -3,6 +3,7 @@ menu "FreeRTOS" menu "Kernel" # Upstream FreeRTOS configurations go here + config FREERTOS_SMP bool "Run the Amazon SMP FreeRTOS kernel instead (FEATURE UNDER DEVELOPMENT)" depends on !IDF_TARGET_ESP32P4 #TODO: IDF-8113: Enable P4 support on AMZ SMP @@ -116,7 +117,7 @@ menu "FreeRTOS" - The FreeRTOS idle hook is NOT the same as the ESP-IDF Idle Hook, but both can be enabled simultaneously. - config FREERTOS_USE_MINIMAL_IDLE_HOOK + config FREERTOS_USE_PASSIVE_IDLE_HOOK bool "Use FreeRTOS minimal idle hook" depends on FREERTOS_SMP default n @@ -126,8 +127,8 @@ menu "FreeRTOS" Note: - - The application must provide the hook function ``void vApplicationMinimalIdleHook( void );`` - - ``vApplicationMinimalIdleHook()`` is called from FreeRTOS minimal idle task(s) + - The application must provide the hook function ``void vApplicationPassiveIdleHook( void );`` + - ``vApplicationPassiveIdleHook()`` is called from FreeRTOS minimal idle task(s) config FREERTOS_USE_TICK_HOOK bool "configUSE_TICK_HOOK" diff --git a/components/freertos/config/include/freertos/FreeRTOSConfig.h b/components/freertos/config/include/freertos/FreeRTOSConfig.h index 399f69d1d4..314051f1bf 100644 --- a/components/freertos/config/include/freertos/FreeRTOSConfig.h +++ b/components/freertos/config/include/freertos/FreeRTOSConfig.h @@ -262,10 +262,11 @@ * - All Amazon SMP FreeRTOS specific configurations * ------------------------------------------------------------------------------------------------------------------ */ -#if CONFIG_FREERTOS_SMP +#if CONFIG_FREERTOS_SMP && ( CONFIG_FREERTOS_NUMBER_OF_CORES > 1 ) + #define configUSE_CORE_AFFINITY 1 #define configRUN_MULTIPLE_PRIORITIES 1 #define configUSE_TASK_PREEMPTION_DISABLE 1 -#endif /* CONFIG_FREERTOS_SMP */ +#endif /* CONFIG_FREERTOS_SMP && ( CONFIG_FREERTOS_NUMBER_OF_CORES > 1 ) */ /* -------------------------------------------------- IDF FreeRTOS ----------------------------------------------------- * - All IDF FreeRTOS specific configurations @@ -290,4 +291,4 @@ /* portNUM_PROCESSORS is deprecated and will be removed in ESP-IDF v6.0 (IDF-8785) * Please use the Kconfig option CONFIG_FREERTOS_NUMBER_OF_CORES instead. */ -#define portNUM_PROCESSORS configNUMBER_OF_CORES +#define portNUM_PROCESSORS configNUMBER_OF_CORES diff --git a/components/freertos/config/linux/include/freertos/FreeRTOSConfig_arch.h b/components/freertos/config/linux/include/freertos/FreeRTOSConfig_arch.h index 8c356eb4bc..7eb4e33c77 100644 --- a/components/freertos/config/linux/include/freertos/FreeRTOSConfig_arch.h +++ b/components/freertos/config/linux/include/freertos/FreeRTOSConfig_arch.h @@ -31,7 +31,7 @@ /* ---------------- Amazon SMP FreeRTOS -------------------- */ #if CONFIG_FREERTOS_SMP - #define configUSE_MINIMAL_IDLE_HOOK 0 /* Not implemented yet, TODO IDF-6654 */ + #define configUSE_PASSIVE_IDLE_HOOK 0 /* Not implemented yet, TODO IDF-6654 */ #endif /* ----------------------- System -------------------------- */ diff --git a/components/freertos/config/riscv/include/freertos/FreeRTOSConfig_arch.h b/components/freertos/config/riscv/include/freertos/FreeRTOSConfig_arch.h index b46fbbb4fa..198720a577 100644 --- a/components/freertos/config/riscv/include/freertos/FreeRTOSConfig_arch.h +++ b/components/freertos/config/riscv/include/freertos/FreeRTOSConfig_arch.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,15 +27,10 @@ /* ---------------- Amazon SMP FreeRTOS -------------------- */ #if CONFIG_FREERTOS_SMP - #define configUSE_CORE_AFFINITY 1 /* This is always enabled to call IDF style idle hooks, by can be "--Wl,--wrap" - * if users enable CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK. */ - #define configUSE_MINIMAL_IDLE_HOOK 1 - -/* IDF Newlib supports dynamic reentrancy. We provide our own __getreent() - * function. */ - #define configNEWLIB_REENTRANT_IS_DYNAMIC 1 + * if users enable CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK. */ + #define configUSE_PASSIVE_IDLE_HOOK 1 #endif /* ----------------------- System -------------------------- */ @@ -46,9 +41,13 @@ * - We simply provide our own INIT and DEINIT functions * - We set "SET" to a blank macro since there is no need to set the reentrancy * pointer. All newlib functions calls __getreent. */ -#define configINIT_TLS_BLOCK( xTLSBlock ) esp_reent_init( &( xTLSBlock ) ) +#if CONFIG_FREERTOS_SMP + #define configINIT_TLS_BLOCK( xTLSBlock, pxTopOfStack ) esp_reent_init( &( xTLSBlock ) ) +#else /* CONFIG_FREERTOS_SMP */ + #define configINIT_TLS_BLOCK( xTLSBlock ) esp_reent_init( &( xTLSBlock ) ) +#endif /* CONFIG_FREERTOS_SMP */ #define configSET_TLS_BLOCK( xTLSBlock ) -#define configDEINIT_TLS_BLOCK( xTLSBlock ) _reclaim_reent( &( xTLSBlock ) ) +#define configDEINIT_TLS_BLOCK( xTLSBlock ) _reclaim_reent( &( xTLSBlock ) ) #define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1 diff --git a/components/freertos/config/xtensa/include/freertos/FreeRTOSConfig_arch.h b/components/freertos/config/xtensa/include/freertos/FreeRTOSConfig_arch.h index 0b3b1c8161..30210fee35 100644 --- a/components/freertos/config/xtensa/include/freertos/FreeRTOSConfig_arch.h +++ b/components/freertos/config/xtensa/include/freertos/FreeRTOSConfig_arch.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -54,15 +54,10 @@ /* ---------------- Amazon SMP FreeRTOS -------------------- */ #if CONFIG_FREERTOS_SMP - #define configUSE_CORE_AFFINITY 1 /* This is always enabled to call IDF style idle hooks, by can be "--Wl,--wrap" - * if users enable CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK. */ - #define configUSE_MINIMAL_IDLE_HOOK 1 - -/* IDF Newlib supports dynamic reentrancy. We provide our own __getreent() - * function. */ - #define configNEWLIB_REENTRANT_IS_DYNAMIC 1 + * if users enable CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK. */ + #define configUSE_PASSIVE_IDLE_HOOK 1 #endif /* ----------------------- System -------------------------- */ @@ -73,9 +68,13 @@ * - We simply provide our own INIT and DEINIT functions * - We set "SET" to a blank macro since there is no need to set the reentrancy * pointer. All newlib functions calls __getreent. */ -#define configINIT_TLS_BLOCK( xTLSBlock ) esp_reent_init( &( xTLSBlock ) ) +#if CONFIG_FREERTOS_SMP + #define configINIT_TLS_BLOCK( xTLSBlock, pxTopOfStack ) esp_reent_init( &( xTLSBlock ) ) +#else /* CONFIG_FREERTOS_SMP */ + #define configINIT_TLS_BLOCK( xTLSBlock ) esp_reent_init( &( xTLSBlock ) ) +#endif /* CONFIG_FREERTOS_SMP */ #define configSET_TLS_BLOCK( xTLSBlock ) -#define configDEINIT_TLS_BLOCK( xTLSBlock ) _reclaim_reent( &( xTLSBlock ) ) +#define configDEINIT_TLS_BLOCK( xTLSBlock ) _reclaim_reent( &( xTLSBlock ) ) #define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1 diff --git a/components/freertos/esp_additions/freertos_tasks_c_additions.h b/components/freertos/esp_additions/freertos_tasks_c_additions.h index 76317c2028..38bd6ac9df 100644 --- a/components/freertos/esp_additions/freertos_tasks_c_additions.h +++ b/components/freertos/esp_additions/freertos_tasks_c_additions.h @@ -29,7 +29,9 @@ */ _Static_assert( offsetof( StaticTask_t, pxDummy6 ) == offsetof( TCB_t, pxStack ) ); _Static_assert( offsetof( StaticTask_t, pxDummy8 ) == offsetof( TCB_t, pxEndOfStack ) ); +#if !CONFIG_IDF_TARGET_LINUX // Disabled for linux builds due to differences in types _Static_assert( tskNO_AFFINITY == ( BaseType_t ) CONFIG_FREERTOS_NO_AFFINITY, "CONFIG_FREERTOS_NO_AFFINITY must be the same as tskNO_AFFINITY" ); +#endif /* ------------------------------------------------- Kernel Control ------------------------------------------------- */ diff --git a/components/freertos/linker_common.lf b/components/freertos/linker_common.lf index 80c25639d8..8e3f63030b 100644 --- a/components/freertos/linker_common.lf +++ b/components/freertos/linker_common.lf @@ -88,6 +88,8 @@ entries: port_common (noflash_text) # Default all functions to internal RAM if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y: port_common:vApplicationGetIdleTaskMemory (default) + if FREERTOS_SMP = y && FREERTOS_UNICORE = n: + port_common:vApplicationGetPassiveIdleTaskMemory (default) port_common:vApplicationGetTimerTaskMemory (default) # ------------------------------------------------------------------------------------------------------------------ diff --git a/components/freertos/port_common.c b/components/freertos/port_common.c index 3e322c9772..0ac795ab82 100644 --- a/components/freertos/port_common.c +++ b/components/freertos/port_common.c @@ -57,6 +57,16 @@ void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; } +#if ( ( CONFIG_FREERTOS_SMP ) && ( configNUMBER_OF_CORES > 1 ) ) +void vApplicationGetPassiveIdleTaskMemory(StaticTask_t ** ppxIdleTaskTCBBuffer, + StackType_t ** ppxIdleTaskStackBuffer, + uint32_t * pulIdleTaskStackSize, + BaseType_t xPassiveIdleTaskIndex) +{ + vApplicationGetIdleTaskMemory(ppxIdleTaskTCBBuffer, ppxIdleTaskStackBuffer, pulIdleTaskStackSize); +} +#endif /* ( ( CONFIG_FREERTOS_SMP ) && ( configNUMBER_OF_CORES > 1 ) ) */ + void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize) diff --git a/components/freertos/port_systick.c b/components/freertos/port_systick.c index ea6a72bdb7..094fac1e65 100644 --- a/components/freertos/port_systick.c +++ b/components/freertos/port_systick.c @@ -201,6 +201,7 @@ BaseType_t xPortSysTickHandler(void) // Call FreeRTOS Increment tick function BaseType_t xSwitchRequired; #if CONFIG_FREERTOS_SMP + UBaseType_t uxSavedStatus = taskENTER_CRITICAL_FROM_ISR(); // Amazon SMP FreeRTOS requires that only core 0 calls xTaskIncrementTick() #if ( configNUM_CORES > 1 ) if (portGET_CORE_ID() == 0) { @@ -211,6 +212,7 @@ BaseType_t xPortSysTickHandler(void) #else /* configNUM_CORES > 1 */ xSwitchRequired = xTaskIncrementTick(); #endif /* configNUM_CORES > 1 */ + taskEXIT_CRITICAL_FROM_ISR(uxSavedStatus); #else /* !CONFIG_FREERTOS_SMP */ #if ( configNUM_CORES > 1 ) /* diff --git a/components/freertos/test_apps/freertos/port/test_fpu_in_isr.c b/components/freertos/test_apps/freertos/port/test_fpu_in_isr.c index 5bdbc1375b..f86bec14ac 100644 --- a/components/freertos/test_apps/freertos/port/test_fpu_in_isr.c +++ b/components/freertos/test_apps/freertos/port/test_fpu_in_isr.c @@ -109,7 +109,7 @@ Expected: static void unpinned_task(void *arg) { // Disable scheduling/preemption to make sure the current task doesn't switch cores -#if CONFIG_FREERTOS_SMP +#if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) vTaskPreemptionDisable(NULL); #else vTaskSuspendAll(); @@ -140,7 +140,7 @@ static void unpinned_task(void *arg) #endif #endif // !CONFIG_FREERTOS_UNICORE // Reenable scheduling/preemption -#if CONFIG_FREERTOS_SMP +#if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) vTaskPreemptionEnable(NULL); #else xTaskResumeAll(); diff --git a/components/freertos/test_apps/freertos/port/test_fpu_in_task.c b/components/freertos/test_apps/freertos/port/test_fpu_in_task.c index b472713d4c..6c52f314d9 100644 --- a/components/freertos/test_apps/freertos/port/test_fpu_in_task.c +++ b/components/freertos/test_apps/freertos/port/test_fpu_in_task.c @@ -130,7 +130,7 @@ Expected: static void unpinned_task(void *arg) { // Disable scheduling/preemption to make sure current core ID doesn't change -#if CONFIG_FREERTOS_SMP +#if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) vTaskPreemptionDisable(NULL); #else vTaskSuspendAll(); @@ -166,7 +166,7 @@ static void unpinned_task(void *arg) #endif #endif // !CONFIG_FREERTOS_UNICORE // Reenable scheduling/preemption -#if CONFIG_FREERTOS_SMP +#if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) vTaskPreemptionEnable(NULL); #else xTaskResumeAll(); From 48a7f053d50ad5f0b0074c143ca59f3842ff037b Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Fri, 2 Feb 2024 23:38:00 +0800 Subject: [PATCH 4/4] feat(freertos/smp): Update other IDF components to be compatible with FreeRTOS v11.0.1 --- CMakeLists.txt | 6 ++--- components/esp_system/esp_system.c | 4 ++-- .../esp_system_unity_tests/main/test_sleep.c | 4 ++-- components/spi_flash/cache_utils.c | 24 +++++++++---------- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 153d9e24f0..8caae634f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -223,9 +223,9 @@ else() endif() # SMP FreeRTOS user provided minimal idle hook. This allows the user to provide -# their own copy of vApplicationMinimalIdleHook() -if(CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK) - list(APPEND link_options "-Wl,--wrap=vApplicationMinimalIdleHook") +# their own copy of vApplicationPassiveIdleHook() +if(CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK) + list(APPEND link_options "-Wl,--wrap=vApplicationPassiveIdleHook") endif() # Placing jump tables in flash would cause issues with code that required diff --git a/components/esp_system/esp_system.c b/components/esp_system/esp_system.c index d5cc6f5c06..bd80e2459f 100644 --- a/components/esp_system/esp_system.c +++ b/components/esp_system/esp_system.c @@ -52,13 +52,13 @@ void esp_restart(void) } } -#ifdef CONFIG_FREERTOS_SMP +#if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) //Note: Scheduler suspension behavior changed in FreeRTOS SMP vTaskPreemptionDisable(NULL); #else // Disable scheduler on this core. vTaskSuspendAll(); -#endif // CONFIG_FREERTOS_SMP +#endif // #if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) esp_restart_noos(); } diff --git a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c index 1bd7db14e3..c5f925c418 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c +++ b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c @@ -60,13 +60,13 @@ static void do_deep_sleep_from_app_cpu(void) xTaskCreatePinnedToCore(&deep_sleep_task, "ds", 2048, NULL, 5, NULL, 1); -#ifdef CONFIG_FREERTOS_SMP +#if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) //Note: Scheduler suspension behavior changed in FreeRTOS SMP vTaskPreemptionDisable(NULL); #else // keep running some non-IRAM code vTaskSuspendAll(); -#endif // CONFIG_FREERTOS_SMP +#endif // #if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) while (true) { ; diff --git a/components/spi_flash/cache_utils.c b/components/spi_flash/cache_utils.c index 862e57e5b5..7cf59ef6d5 100644 --- a/components/spi_flash/cache_utils.c +++ b/components/spi_flash/cache_utils.c @@ -118,7 +118,7 @@ void spi_flash_op_unlock(void) void IRAM_ATTR spi_flash_op_block_func(void *arg) { // Disable scheduler on this CPU -#ifdef CONFIG_FREERTOS_SMP +#if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) /* Note: FreeRTOS SMP has changed the behavior of scheduler suspension. But the vTaskPreemptionDisable() function should achieve the same affect as before (i.e., prevent the current task from being preempted). @@ -126,7 +126,7 @@ void IRAM_ATTR spi_flash_op_block_func(void *arg) vTaskPreemptionDisable(NULL); #else vTaskSuspendAll(); -#endif // CONFIG_FREERTOS_SMP +#endif // #if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) // Restore interrupts that aren't located in IRAM esp_intr_noniram_disable(); uint32_t cpuid = (uint32_t) arg; @@ -142,13 +142,13 @@ void IRAM_ATTR spi_flash_op_block_func(void *arg) spi_flash_restore_cache(cpuid, s_flash_op_cache_state[cpuid]); // Restore interrupts that aren't located in IRAM esp_intr_noniram_enable(); -#ifdef CONFIG_FREERTOS_SMP +#if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) //Note: Scheduler suspension behavior changed in FreeRTOS SMP vTaskPreemptionEnable(NULL); #else // Re-enable scheduler xTaskResumeAll(); -#endif // CONFIG_FREERTOS_SMP +#endif // #if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) } void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu(void) @@ -187,13 +187,13 @@ void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu(void) // Busy loop and wait for spi_flash_op_block_func to disable cache // on the other CPU } -#ifdef CONFIG_FREERTOS_SMP +#if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) //Note: Scheduler suspension behavior changed in FreeRTOS SMP vTaskPreemptionDisable(NULL); #else // Disable scheduler on the current CPU vTaskSuspendAll(); -#endif // CONFIG_FREERTOS_SMP +#endif // #if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) // Can now set the priority back to the normal one prvTaskPriorityRestore(&SavedPriority); // This is guaranteed to run on CPU because the other CPU is now @@ -248,12 +248,12 @@ void IRAM_ATTR spi_flash_enable_interrupts_caches_and_other_cpu(void) // But esp_intr_noniram_enable has to be called on the same CPU which // called esp_intr_noniram_disable if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { -#ifdef CONFIG_FREERTOS_SMP +#if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) //Note: Scheduler suspension behavior changed in FreeRTOS SMP vTaskPreemptionEnable(NULL); #else xTaskResumeAll(); -#endif // CONFIG_FREERTOS_SMP +#endif // #if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) } // Release API lock spi_flash_op_unlock(); @@ -290,26 +290,26 @@ void spi_flash_init_lock(void) void spi_flash_op_lock(void) { -#ifdef CONFIG_FREERTOS_SMP +#if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) { //Note: Scheduler suspension behavior changed in FreeRTOS SMP vTaskPreemptionDisable(NULL); } #else vTaskSuspendAll(); -#endif // CONFIG_FREERTOS_SMP +#endif // #if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) } void spi_flash_op_unlock(void) { -#ifdef CONFIG_FREERTOS_SMP +#if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) { //Note: Scheduler suspension behavior changed in FreeRTOS SMP vTaskPreemptionEnable(NULL); } #else xTaskResumeAll(); -#endif // CONFIG_FREERTOS_SMP +#endif // #if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) ) }