Merge branch 'feature/freertos_upstream_plus_tlsf_allocator_preview' into 'master'

freertos/heap: Preview branch containing TLSF allocator and FreeRTOS 10 kernel

Closes IDF-1637 and IDFGH-3859

See merge request espressif/esp-idf!8414
This commit is contained in:
Angus Gratton 2020-10-14 15:58:51 +08:00
commit a1d3f2b291
77 changed files with 13137 additions and 5605 deletions

2
.gitignore vendored
View File

@ -87,4 +87,4 @@ flake8_output.txt
build
# lock files for examples and components
dependencies.lock
dependencies.lock

View File

@ -230,11 +230,12 @@ Notes:
#define traceQUEUE_CREATE( pxNewQueue ) SEGGER_SYSVIEW_RecordU32x3(apiFastID_OFFSET + apiID_XQUEUEGENERICCREATE, uxQueueLength, uxItemSize, ucQueueType)
#define traceQUEUE_DELETE( pxQueue ) SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VQUEUEDELETE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue))
#define traceQUEUE_PEEK( pxQueue ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICRECEIVE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer), xTicksToWait, xJustPeeking)
#define traceQUEUE_PEEK( pxQueue ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICRECEIVE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer), xTicksToWait, 0)
#define traceQUEUE_PEEK_FROM_ISR( pxQueue ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_XQUEUEPEEKFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer))
#define traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_XQUEUEPEEKFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer))
#define traceQUEUE_RECEIVE( pxQueue ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICRECEIVE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer), xTicksToWait, xJustPeeking)
#define traceQUEUE_RECEIVE_FAILED( pxQueue ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICRECEIVE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer), xTicksToWait, xJustPeeking)
#define traceQUEUE_RECEIVE( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICRECEIVE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)0), xTicksToWait, 1)
#define traceQUEUE_RECEIVE_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICRECEIVE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)0), xTicksToWait, 1)
#define traceQUEUE_SEMAPHORE_RECEIVE( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICRECEIVE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)0), xTicksToWait, 0)
#define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) SEGGER_SYSVIEW_RecordU32x3(apiFastID_OFFSET + apiID_XQUEUERECEIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer), (U32)pxHigherPriorityTaskWoken)
#define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x3(apiFastID_OFFSET + apiID_XQUEUERECEIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer), (U32)pxHigherPriorityTaskWoken)
#define traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_VQUEUEADDTOREGISTRY, SEGGER_SYSVIEW_ShrinkId((U32)xQueue), (U32)pcQueueName)

View File

@ -719,7 +719,7 @@ static SPI_MASTER_ISR_ATTR void uninstall_priv_desc(spi_trans_priv_t* trans_buf)
}
// copy data from temporary DMA-capable buffer back to IRAM buffer and free the temporary one.
if ((void *)trans_buf->buffer_to_rcv != &trans_desc->rx_data[0] &&
trans_buf->buffer_to_rcv != trans_desc->rx_buffer) {
trans_buf->buffer_to_rcv != trans_desc->rx_buffer) { // NOLINT(clang-analyzer-unix.Malloc)
if (trans_desc->flags & SPI_TRANS_USE_RXDATA) {
memcpy((uint8_t *) & trans_desc->rx_data[0], trans_buf->buffer_to_rcv, (trans_desc->rxlength + 7) / 8);
} else {

View File

@ -564,7 +564,7 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]")
ESP_LOGI(TAG, "iram: %p, dram: %p", data_iram, data_dram);
ESP_LOGI(TAG, "drom: %p, malloc: %p", data_drom, data_malloc);
TEST_ASSERT(esp_ptr_in_dram(data_dram));
TEST_ASSERT(esp_ptr_in_iram(data_iram));
TEST_ASSERT(esp_ptr_executable(data_iram) || esp_ptr_in_iram(data_iram) || esp_ptr_in_diram_iram(data_iram));
TEST_ASSERT(esp_ptr_in_drom(data_drom));
srand(52);

View File

@ -5,6 +5,10 @@ entries:
panic_handler (noflash)
reset_reason (noflash)
system_api:esp_system_abort (noflash)
startup:do_core_init (default)
startup:do_secondary_init (default)
startup:start_cpu0_default (default)
if ESP_CONSOLE_USB_CDC_SUPPORT_ETS_PRINTF:
usb_console:esp_usb_console_write_char (noflash)

View File

@ -16,11 +16,12 @@ set(srcs
list(APPEND srcs
"croutine.c"
"event_groups.c"
"FreeRTOS-openocd.c"
"list.c"
"queue.c"
"tasks.c"
"timers.c")
"timers.c"
"stream_buffer.c"
"FreeRTOS-openocd.c")
set(include_dirs
include
@ -57,6 +58,7 @@ set_source_files_properties(
event_groups.c
timers.c
queue.c
stream_buffer.c
PROPERTIES COMPILE_DEFINITIONS
_ESP_FREERTOS_INTERNAL
)

File diff suppressed because it is too large Load Diff

View File

@ -163,7 +163,7 @@ menu "FreeRTOS"
config FREERTOS_IDLE_TASK_STACKSIZE
int "Idle Task stack size"
range 768 32768
default 1536
default 2304
help
The idle task has its own stack, sized in bytes. The default size is enough for most uses. Size can be
reduced to 768 bytes if no (or simple) FreeRTOS idle hooks are used and pthread local storage or FreeRTOS

View File

@ -1,76 +1,37 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#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.
@ -143,7 +104,6 @@ BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPri
BaseType_t xReturn;
CRCB_t *pxCoRoutine;
UNTESTED_FUNCTION(); //Actually, coroutines are entirely unsupported
/* Allocate the memory that will store the co-routine control block. */
pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) );
if( pxCoRoutine )
@ -300,7 +260,7 @@ CRCB_t *pxCRCB;
( void ) uxListRemove( &( pxCRCB->xGenericListItem ) );
/* Is the co-routine waiting on an event also? */
if( pxCRCB->xEventListItem.pvContainer )
if( pxCRCB->xEventListItem.pxContainer )
{
( void ) uxListRemove( &( pxCRCB->xEventListItem ) );
}
@ -389,3 +349,5 @@ BaseType_t xReturn;
return xReturn;
}
#endif /* configUSE_CO_ROUTINES == 0 */

View File

@ -1,71 +1,29 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/* Standard includes. */
#include <stdlib.h>
@ -81,19 +39,11 @@ task.h is included from an application file. */
#include "timers.h"
#include "event_groups.h"
/* Lint e961 and e750 are suppressed as a MISRA exception justified because 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. */
#if ( INCLUDE_xEventGroupSetBitFromISR == 1 ) && ( configUSE_TIMERS == 0 )
#error configUSE_TIMERS must be set to 1 to make the xEventGroupSetBitFromISR() function available.
#endif
#if ( INCLUDE_xEventGroupSetBitFromISR == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 0 )
#error INCLUDE_xTimerPendFunctionCall must also be set to one to make the xEventGroupSetBitFromISR() function available.
#endif
/* 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
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
@ -110,7 +60,7 @@ taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
#define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL
#endif
typedef struct xEventGroupDefinition
typedef struct EventGroupDef_t
{
EventBits_t uxEventBits;
List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */
@ -126,7 +76,6 @@ typedef struct xEventGroupDefinition
portMUX_TYPE eventGroupMux; //Mutex required due to SMP
} EventGroup_t;
/*-----------------------------------------------------------*/
/*
@ -137,7 +86,7 @@ typedef struct xEventGroupDefinition
* wait condition is met if any of the bits set in uxBitsToWait for are also set
* in uxCurrentEventBits.
*/
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits );
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
/*-----------------------------------------------------------*/
@ -150,8 +99,18 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
/* 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. */
#endif /* configASSERT_DEFINED */
/* The user has provided a statically allocated event group - use it. */
pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 EventGroup_t and StaticEventGroup_t are guaranteed to have the same size and alignment requirement - checked by configASSERT(). */
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(). */
if( pxEventBits != NULL )
{
@ -167,16 +126,19 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
vPortCPUInitializeMutex(&pxEventBits->eventGroupMux);
traceEVENT_GROUP_CREATE( pxEventBits );
vPortCPUInitializeMutex( &pxEventBits->eventGroupMux );
}
else
{
/* xEventGroupCreateStatic should only ever be called with
pxEventGroupBuffer pointing to a pre-allocated (compile time
allocated) StaticEventGroup_t variable. */
traceEVENT_GROUP_CREATE_FAILED();
}
return ( EventGroupHandle_t ) pxEventBits;
return pxEventBits;
}
#endif /* configSUPPORT_STATIC_ALLOCATION */
@ -188,8 +150,20 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
{
EventGroup_t *pxEventBits;
/* Allocate the event group. */
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );
/* 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. */
if( pxEventBits != NULL )
{
@ -205,16 +179,16 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
}
#endif /* configSUPPORT_STATIC_ALLOCATION */
vPortCPUInitializeMutex(&pxEventBits->eventGroupMux);
vPortCPUInitializeMutex( &pxEventBits->eventGroupMux );
traceEVENT_GROUP_CREATE( pxEventBits );
}
else
{
traceEVENT_GROUP_CREATE_FAILED();
traceEVENT_GROUP_CREATE_FAILED(); /*lint !e9063 Else branch only exists to allow tracing and does not generate code if trace macros are not defined. */
}
return ( EventGroupHandle_t ) pxEventBits;
return pxEventBits;
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
@ -223,8 +197,8 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait )
{
EventBits_t uxOriginalBitValue, uxReturn;
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
BaseType_t xAlreadyYielded;
EventGroup_t *pxEventBits = xEventGroup;
BaseType_t xAlreadyYielded = pdFALSE;
BaseType_t xTimeoutOccurred = pdFALSE;
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
@ -235,8 +209,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
}
#endif
vTaskSuspendAll();
taskENTER_CRITICAL(&pxEventBits->eventGroupMux);
taskENTER_CRITICAL( &pxEventBits->eventGroupMux );
{
uxOriginalBitValue = pxEventBits->uxEventBits;
@ -275,11 +248,12 @@ BaseType_t xTimeoutOccurred = pdFALSE;
/* The rendezvous bits were not set, but no block time was
specified - just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits;
xTimeoutOccurred = pdTRUE;
}
}
}
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux );
xAlreadyYielded = xTaskResumeAll();
if( xTicksToWait != ( TickType_t ) 0 )
{
@ -334,15 +308,18 @@ BaseType_t xTimeoutOccurred = pdFALSE;
traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
/* Prevent compiler warnings when trace macros are not used. */
( void ) xTimeoutOccurred;
return uxReturn;
}
/*-----------------------------------------------------------*/
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
{
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
EventGroup_t *pxEventBits = xEventGroup;
EventBits_t uxReturn, uxControlBits = 0;
BaseType_t xWaitConditionMet, xAlreadyYielded;
BaseType_t xWaitConditionMet;
BaseType_t xTimeoutOccurred = pdFALSE;
/* Check the user is not attempting to wait on the bits used by the kernel
@ -356,7 +333,6 @@ BaseType_t xTimeoutOccurred = pdFALSE;
}
#endif
vTaskSuspendAll();
taskENTER_CRITICAL( &pxEventBits->eventGroupMux );
{
const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
@ -386,6 +362,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
/* The wait condition has not been met, but no block time was
specified, so just return the current value. */
uxReturn = uxCurrentEventBits;
xTimeoutOccurred = pdTRUE;
}
else
{
@ -424,19 +401,12 @@ BaseType_t xTimeoutOccurred = pdFALSE;
traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
}
}
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux );
xAlreadyYielded = xTaskResumeAll();
if( xTicksToWait != ( TickType_t ) 0 )
{
if( xAlreadyYielded == pdFALSE )
{
portYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
portYIELD_WITHIN_API();
/* The task blocked to wait for its required bits to be set - at this
point either the required bits were set or the block time expired. If
@ -468,11 +438,9 @@ BaseType_t xTimeoutOccurred = pdFALSE;
{
mtCOVERAGE_TEST_MARKER();
}
xTimeoutOccurred = pdTRUE;
}
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux );
/* Prevent compiler warnings when trace macros are not used. */
xTimeoutOccurred = pdFALSE;
}
else
{
@ -484,13 +452,16 @@ BaseType_t xTimeoutOccurred = pdFALSE;
}
traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
/* Prevent compiler warnings when trace macros are not used. */
( void ) xTimeoutOccurred;
return uxReturn;
}
/*-----------------------------------------------------------*/
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
{
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
EventGroup_t *pxEventBits = xEventGroup;
EventBits_t uxReturn;
/* Check the user is not attempting to clear the bits used by the kernel
@ -522,7 +493,7 @@ EventBits_t uxReturn;
BaseType_t xReturn;
traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL );
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. */
return xReturn;
}
@ -533,7 +504,7 @@ EventBits_t uxReturn;
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
{
UBaseType_t uxSavedInterruptStatus;
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
EventGroup_t const * const pxEventBits = xEventGroup;
EventBits_t uxReturn;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
@ -543,16 +514,16 @@ EventBits_t uxReturn;
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
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 const *pxListEnd;
List_t *pxList;
List_t const * pxList;
EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
EventGroup_t *pxEventBits = xEventGroup;
BaseType_t xMatchFound = pdFALSE;
/* Check the user is not attempting to set the bits used by the kernel
@ -561,10 +532,9 @@ BaseType_t xMatchFound = pdFALSE;
configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
pxList = &( pxEventBits->xTasksWaitingForBits );
pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
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. */
vTaskSuspendAll();
taskENTER_CRITICAL(&pxEventBits->eventGroupMux);
taskENTER_CRITICAL( &pxEventBits->eventGroupMux );
{
traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
@ -623,7 +593,7 @@ BaseType_t xMatchFound = pdFALSE;
eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
that is was unblocked due to its required bits matching, rather
than because it timed out. */
( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
}
/* Move onto the next list item. Note pxListItem->pxNext is not
@ -636,8 +606,7 @@ BaseType_t xMatchFound = pdFALSE;
bit was set in the control word. */
pxEventBits->uxEventBits &= ~uxBitsToClear;
}
taskEXIT_CRITICAL(&pxEventBits->eventGroupMux);
( void ) xTaskResumeAll();
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux );
return pxEventBits->uxEventBits;
}
@ -645,47 +614,43 @@ BaseType_t xMatchFound = pdFALSE;
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
{
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
EventGroup_t *pxEventBits = xEventGroup;
const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
traceEVENT_GROUP_DELETE( xEventGroup );
vTaskSuspendAll();
taskENTER_CRITICAL( &pxEventBits->eventGroupMux );
{
traceEVENT_GROUP_DELETE( xEventGroup );
while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
{
/* Unblock the task, returning 0 as the event list is being deleted
and cannot therefore have any bits set. */
configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
and cannot therefore have any bits set. */
configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
}
}
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux );
#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
#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 )
{
/* The event group can only have been allocated dynamically - free
it again. */
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux );
vPortFree( pxEventBits );
}
#elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
else
{
/* The event group could have been allocated statically or
dynamically, so check before attempting to free the memory. */
if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
{
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); //Exit mux of event group before deleting it
vPortFree( pxEventBits );
}
else
{
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux );
mtCOVERAGE_TEST_MARKER();
}
mtCOVERAGE_TEST_MARKER();
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
}
( void ) xTaskResumeAll();
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
}
/*-----------------------------------------------------------*/
@ -693,7 +658,7 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup )
an interrupt. */
void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet )
{
( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_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. */
}
/*-----------------------------------------------------------*/
@ -701,7 +666,7 @@ void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet
an interrupt. */
void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear )
{
( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_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. */
}
/*-----------------------------------------------------------*/
@ -747,7 +712,7 @@ BaseType_t xWaitConditionMet = pdFALSE;
BaseType_t xReturn;
traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken );
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. */
return xReturn;
}
@ -760,7 +725,7 @@ BaseType_t xWaitConditionMet = pdFALSE;
UBaseType_t uxEventGroupGetNumber( void* xEventGroup )
{
UBaseType_t xReturn;
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
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. */
if( xEventGroup == NULL )
{
@ -774,5 +739,17 @@ BaseType_t xWaitConditionMet = pdFALSE;
return xReturn;
}
#endif
#endif /* configUSE_TRACE_FACILITY */
/*-----------------------------------------------------------*/
#if ( configUSE_TRACE_FACILITY == 1 )
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. */
}
#endif /* configUSE_TRACE_FACILITY */
/*-----------------------------------------------------------*/

View File

@ -1,71 +1,29 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef INC_FREERTOS_H
#define INC_FREERTOS_H
@ -74,7 +32,6 @@
* Include the generic headers required for the FreeRTOS port being used.
*/
#include <stddef.h>
#include "sys/reent.h"
/*
* If stdint.h cannot be located then:
@ -106,6 +63,15 @@ extern "C" {
/* Definitions specific to the port being used. */
#include "portable.h"
/* Must be defaulted before configUSE_NEWLIB_REENTRANT is used below. */
#ifndef configUSE_NEWLIB_REENTRANT
#define configUSE_NEWLIB_REENTRANT 0
#endif
/* Required if struct _reent is used. */
#if ( configUSE_NEWLIB_REENTRANT == 1 )
#include <reent.h>
#endif
/*
* Check all the required application specific macros have been defined.
* These macros are application specific and (as downloaded) are defined
@ -120,6 +86,10 @@ extern "C" {
#error Missing definition: configMAX_PRIORITIES must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details.
#endif
#if configMAX_PRIORITIES < 1
#error configMAX_PRIORITIES must be defined to be greater than or equal to 1.
#endif
#ifndef configUSE_PREEMPTION
#error Missing definition: configUSE_PREEMPTION must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif
@ -132,54 +102,44 @@ extern "C" {
#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_CO_ROUTINES
#error Missing definition: configUSE_CO_ROUTINES must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif
#ifndef INCLUDE_vTaskPrioritySet
#error Missing definition: INCLUDE_vTaskPrioritySet must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif
#ifndef INCLUDE_uxTaskPriorityGet
#error Missing definition: INCLUDE_uxTaskPriorityGet must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif
#ifndef INCLUDE_vTaskDelete
#error Missing definition: INCLUDE_vTaskDelete must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif
#ifndef INCLUDE_vTaskSuspend
#error Missing definition: INCLUDE_vTaskSuspend must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif
#ifndef INCLUDE_vTaskDelayUntil
#error Missing definition: INCLUDE_vTaskDelayUntil must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif
#ifndef INCLUDE_vTaskDelay
#error Missing definition: INCLUDE_vTaskDelay 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.
#endif
#if configUSE_CO_ROUTINES != 0
#ifndef configMAX_CO_ROUTINE_PRIORITIES
#error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1.
#endif
#ifndef configUSE_CO_ROUTINES
#define configUSE_CO_ROUTINES 0
#endif
#ifndef configMAX_PRIORITIES
#error configMAX_PRIORITIES must be defined to be greater than or equal to 1.
#ifndef INCLUDE_vTaskPrioritySet
#define INCLUDE_vTaskPrioritySet 0
#endif
#ifndef INCLUDE_uxTaskPriorityGet
#define INCLUDE_uxTaskPriorityGet 0
#endif
#ifndef INCLUDE_vTaskDelete
#define INCLUDE_vTaskDelete 0
#endif
#ifndef INCLUDE_vTaskSuspend
#define INCLUDE_vTaskSuspend 0
#endif
#ifndef INCLUDE_vTaskDelayUntil
#define INCLUDE_vTaskDelayUntil 0
#endif
#ifndef INCLUDE_vTaskDelay
#define INCLUDE_vTaskDelay 0
#endif
#ifndef INCLUDE_xTaskGetIdleTaskHandle
#define INCLUDE_xTaskGetIdleTaskHandle 0
#endif
#ifndef INCLUDE_xTimerGetTimerDaemonTaskHandle
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
#ifndef INCLUDE_xTaskAbortDelay
#define INCLUDE_xTaskAbortDelay 0
#endif
#ifndef INCLUDE_xQueueGetMutexHolder
@ -190,26 +150,56 @@ extern "C" {
#define INCLUDE_xSemaphoreGetMutexHolder INCLUDE_xQueueGetMutexHolder
#endif
#ifndef INCLUDE_pcTaskGetTaskName
#define INCLUDE_pcTaskGetTaskName 1
#endif
#ifndef configUSE_APPLICATION_TASK_TAG
#define configUSE_APPLICATION_TASK_TAG 0
#ifndef INCLUDE_xTaskGetHandle
#define INCLUDE_xTaskGetHandle 0
#endif
#ifndef INCLUDE_uxTaskGetStackHighWaterMark
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#endif
#ifndef INCLUDE_pxTaskGetStackStart
#define INCLUDE_pxTaskGetStackStart 0
#ifndef INCLUDE_uxTaskGetStackHighWaterMark2
#define INCLUDE_uxTaskGetStackHighWaterMark2 0
#endif
#ifndef INCLUDE_eTaskGetState
#define INCLUDE_eTaskGetState 0
#endif
#ifndef INCLUDE_xTaskResumeFromISR
#define INCLUDE_xTaskResumeFromISR 1
#endif
#ifndef INCLUDE_xTimerPendFunctionCall
#define INCLUDE_xTimerPendFunctionCall 0
#endif
#ifndef INCLUDE_xTaskGetSchedulerState
#define INCLUDE_xTaskGetSchedulerState 0
#endif
#ifndef INCLUDE_xTaskGetCurrentTaskHandle
#define INCLUDE_xTaskGetCurrentTaskHandle 0
#endif
#if configUSE_CO_ROUTINES != 0
#ifndef configMAX_CO_ROUTINE_PRIORITIES
#error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1.
#endif
#endif
#ifndef configUSE_DAEMON_TASK_STARTUP_HOOK
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
#endif
#ifndef configUSE_APPLICATION_TASK_TAG
#define configUSE_APPLICATION_TASK_TAG 0
#endif
#ifndef configNUM_THREAD_LOCAL_STORAGE_POINTERS
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0
#endif
#ifndef configUSE_RECURSIVE_MUTEXES
#define configUSE_RECURSIVE_MUTEXES 0
#endif
@ -246,18 +236,6 @@ extern "C" {
#error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h
#endif
#ifndef INCLUDE_xTaskResumeFromISR
#define INCLUDE_xTaskResumeFromISR 1
#endif
#ifndef INCLUDE_xEventGroupSetBitFromISR
#define INCLUDE_xEventGroupSetBitFromISR 0
#endif
#ifndef INCLUDE_xTimerPendFunctionCall
#define INCLUDE_xTimerPendFunctionCall 0
#endif
#ifndef configASSERT
#define configASSERT( x )
#define configASSERT_DEFINED 0
@ -265,6 +243,22 @@ extern "C" {
#define configASSERT_DEFINED 1
#endif
/* configPRECONDITION should be resolve to configASSERT.
The CBMC proofs need a way to track assumptions and assertions.
A configPRECONDITION statement should express an implicit invariant or assumption made.
A configASSERT statement should express an invariant that must hold explicit before calling
the code. */
#ifndef configPRECONDITION
#define configPRECONDITION( X ) configASSERT(X)
#define configPRECONDITION_DEFINED 0
#else
#define configPRECONDITION_DEFINED 1
#endif
#ifndef portMEMORY_BARRIER
#define portMEMORY_BARRIER()
#endif
/* The timers module relies on xTaskGetSchedulerState(). */
#if configUSE_TIMERS == 1
@ -282,15 +276,6 @@ extern "C" {
#endif /* configUSE_TIMERS */
#ifndef INCLUDE_xTaskGetSchedulerState
#define INCLUDE_xTaskGetSchedulerState 0
#endif
#ifndef INCLUDE_xTaskGetCurrentTaskHandle
#define INCLUDE_xTaskGetCurrentTaskHandle 0
#endif
#ifndef portSET_INTERRUPT_MASK_FROM_ISR
#define portSET_INTERRUPT_MASK_FROM_ISR() 0
#endif
@ -318,6 +303,7 @@ extern "C" {
#if ( configQUEUE_REGISTRY_SIZE < 1 )
#define vQueueAddToRegistry( xQueue, pcName )
#define vQueueUnregisterQueue( xQueue )
#define pcQueueGetName( xQueue )
#endif
#ifndef portPOINTER_SIZE_TYPE
@ -390,6 +376,14 @@ extern "C" {
#define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue )
#endif
#ifndef traceBLOCKING_ON_QUEUE_PEEK
/* Task is about to block because it cannot read from a
queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore
upon which the read was attempted. pxCurrentTCB points to the TCB of the
task that attempted the read. */
#define traceBLOCKING_ON_QUEUE_PEEK( pxQueue )
#endif
#ifndef traceBLOCKING_ON_QUEUE_SEND
/* Task is about to block because it cannot write to a
queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore
@ -402,26 +396,22 @@ extern "C" {
#define configCHECK_FOR_STACK_OVERFLOW 0
#endif
#ifndef configRECORD_STACK_HIGH_ADDRESS
#define configRECORD_STACK_HIGH_ADDRESS 0
#endif
#ifndef configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H
#define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 0
#endif
/* The following event macros are embedded in the kernel API calls. */
#ifndef traceMOVED_TASK_TO_READY_STATE
#define traceMOVED_TASK_TO_READY_STATE( pxTCB )
#endif
#ifndef traceREADDED_TASK_TO_READY_STATE
#define traceREADDED_TASK_TO_READY_STATE( pxTCB ) traceMOVED_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 traceMOVED_TASK_TO_SUSPENDED_LIST
#define traceMOVED_TASK_TO_SUSPENDED_LIST( pxTCB )
#ifndef tracePOST_MOVED_TASK_TO_READY_STATE
#define tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )
#endif
#ifndef traceQUEUE_CREATE
@ -464,6 +454,10 @@ extern "C" {
#define traceCREATE_COUNTING_SEMAPHORE_FAILED()
#endif
#ifndef traceQUEUE_SEMAPHORE_RECEIVE
#define traceQUEUE_SEMAPHORE_RECEIVE( pxQueue )
#endif
#ifndef traceQUEUE_SEND
#define traceQUEUE_SEND( pxQueue )
#endif
@ -480,6 +474,10 @@ extern "C" {
#define traceQUEUE_PEEK( pxQueue )
#endif
#ifndef traceQUEUE_PEEK_FAILED
#define traceQUEUE_PEEK_FAILED( pxQueue )
#endif
#ifndef traceQUEUE_PEEK_FROM_ISR
#define traceQUEUE_PEEK_FROM_ISR( pxQueue )
#endif
@ -512,10 +510,6 @@ extern "C" {
#define traceQUEUE_DELETE( pxQueue )
#endif
#ifndef traceTASK_CREATE
#define traceTASK_CREATE( pxNewTCB )
#endif
#ifndef traceQUEUE_GIVE_FROM_ISR
#define traceQUEUE_GIVE_FROM_ISR( pxQueue )
#endif
@ -524,6 +518,10 @@ extern "C" {
#define traceQUEUE_GIVE_FROM_ISR_FAILED( pxQueue )
#endif
#ifndef traceTASK_CREATE
#define traceTASK_CREATE( pxNewTCB )
#endif
#ifndef traceTASK_CREATE_FAILED
#define traceTASK_CREATE_FAILED()
#endif
@ -533,7 +531,7 @@ extern "C" {
#endif
#ifndef traceTASK_DELAY_UNTIL
#define traceTASK_DELAY_UNTIL()
#define traceTASK_DELAY_UNTIL( x )
#endif
#ifndef traceTASK_DELAY
@ -644,10 +642,86 @@ extern "C" {
#define traceQUEUE_REGISTRY_ADD(xQueue, pcQueueName)
#endif
#ifndef traceTASK_NOTIFY_TAKE_BLOCK
#define traceTASK_NOTIFY_TAKE_BLOCK()
#endif
#ifndef traceTASK_NOTIFY_TAKE
#define traceTASK_NOTIFY_TAKE()
#endif
#ifndef traceTASK_NOTIFY_WAIT_BLOCK
#define traceTASK_NOTIFY_WAIT_BLOCK()
#endif
#ifndef traceTASK_NOTIFY_WAIT
#define traceTASK_NOTIFY_WAIT()
#endif
#ifndef traceTASK_NOTIFY
#define traceTASK_NOTIFY()
#endif
#ifndef traceTASK_NOTIFY_FROM_ISR
#define traceTASK_NOTIFY_FROM_ISR()
#endif
#ifndef traceTASK_NOTIFY_GIVE_FROM_ISR
#define traceTASK_NOTIFY_GIVE_FROM_ISR()
#endif
#define traceTASK_NOTIFY_GIVE_FROM_ISR()
#endif
#ifndef traceSTREAM_BUFFER_CREATE_FAILED
#define traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer )
#endif
#ifndef traceSTREAM_BUFFER_CREATE_STATIC_FAILED
#define traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer )
#endif
#ifndef traceSTREAM_BUFFER_CREATE
#define traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer )
#endif
#ifndef traceSTREAM_BUFFER_DELETE
#define traceSTREAM_BUFFER_DELETE( xStreamBuffer )
#endif
#ifndef traceSTREAM_BUFFER_RESET
#define traceSTREAM_BUFFER_RESET( xStreamBuffer )
#endif
#ifndef traceBLOCKING_ON_STREAM_BUFFER_SEND
#define traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer )
#endif
#ifndef traceSTREAM_BUFFER_SEND
#define traceSTREAM_BUFFER_SEND( xStreamBuffer, xBytesSent )
#endif
#ifndef traceSTREAM_BUFFER_SEND_FAILED
#define traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer )
#endif
#ifndef traceSTREAM_BUFFER_SEND_FROM_ISR
#define traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xBytesSent )
#endif
#ifndef traceBLOCKING_ON_STREAM_BUFFER_RECEIVE
#define traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer )
#endif
#ifndef traceSTREAM_BUFFER_RECEIVE
#define traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength )
#endif
#ifndef traceSTREAM_BUFFER_RECEIVE_FAILED
#define traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer )
#endif
#ifndef traceSTREAM_BUFFER_RECEIVE_FROM_ISR
#define traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength )
#endif
#ifndef traceISR_EXIT_TO_SCHEDULER
#define traceISR_EXIT_TO_SCHEDULER()
#endif
@ -694,14 +768,6 @@ extern "C" {
#define portYIELD_WITHIN_API portYIELD
#endif
#ifndef pvPortMallocAligned
#define pvPortMallocAligned( x, puxStackBuffer ) ( ( ( puxStackBuffer ) == NULL ) ? ( pvPortMalloc( ( x ) ) ) : ( puxStackBuffer ) )
#endif
#ifndef vPortFreeAligned
#define vPortFreeAligned( pvBlockToFree ) vPortFree( pvBlockToFree )
#endif
#ifndef portSUPPRESS_TICKS_AND_SLEEP
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime )
#endif
@ -718,6 +784,10 @@ extern "C" {
#define configUSE_TICKLESS_IDLE 0
#endif
#ifndef configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING
#define configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( x )
#endif
#ifndef configPRE_SLEEP_PROCESSING
#define configPRE_SLEEP_PROCESSING( x )
#endif
@ -734,6 +804,14 @@ extern "C" {
#define portTASK_USES_FLOATING_POINT()
#endif
#ifndef portALLOCATE_SECURE_CONTEXT
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
#endif
#ifndef portDONT_DISCARD
#define portDONT_DISCARD
#endif
#ifndef configUSE_TIME_SLICING
#define configUSE_TIME_SLICING 1
#endif
@ -742,18 +820,10 @@ extern "C" {
#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0
#endif
#ifndef configUSE_NEWLIB_REENTRANT
#define configUSE_NEWLIB_REENTRANT 0
#endif
#ifndef configUSE_STATS_FORMATTING_FUNCTIONS
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
#endif
#ifndef configTASKLIST_INCLUDE_COREID
#define configTASKLIST_INCLUDE_COREID 0
#endif
#ifndef portASSERT_IF_INTERRUPT_PRIORITY_INVALID
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
#endif
@ -766,6 +836,10 @@ extern "C" {
#define mtCOVERAGE_TEST_MARKER()
#endif
#ifndef mtCOVERAGE_TEST_DELAY
#define mtCOVERAGE_TEST_DELAY()
#endif
#ifndef portASSERT_IF_IN_ISR
#define portASSERT_IF_IN_ISR()
#endif
@ -782,6 +856,10 @@ extern "C" {
#define configUSE_TASK_NOTIFICATIONS 1
#endif
#ifndef configUSE_POSIX_ERRNO
#define configUSE_POSIX_ERRNO 0
#endif
#ifndef portTICK_TYPE_IS_ATOMIC
#define portTICK_TYPE_IS_ATOMIC 0
#endif
@ -796,10 +874,38 @@ extern "C" {
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#endif
#ifndef configSTACK_DEPTH_TYPE
/* Defaults to uint16_t for backward compatibility, but can be overridden
in FreeRTOSConfig.h if uint16_t is too restrictive. */
#define configSTACK_DEPTH_TYPE uint16_t
#endif
#ifndef configMESSAGE_BUFFER_LENGTH_TYPE
/* Defaults to size_t for backward compatibility, but can be overridden
in FreeRTOSConfig.h if lengths will always be less than the number of bytes
in a size_t. */
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t
#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
#if( ( configUSE_RECURSIVE_MUTEXES == 1 ) && ( configUSE_MUTEXES != 1 ) )
#error configUSE_MUTEXES must be set to 1 to use recursive mutexes
#endif
#ifndef configINITIAL_TICK_COUNT
#define configINITIAL_TICK_COUNT 0
#endif
#if( portTICK_TYPE_IS_ATOMIC == 0 )
/* Either variables of tick type cannot be read atomically, or
portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when
@ -823,6 +929,32 @@ V8 if desired. */
#define configENABLE_BACKWARD_COMPATIBILITY 1
#endif
#ifndef configPRINTF
/* configPRINTF() was not defined, so define it away to nothing. To use
configPRINTF() then define it as follows (where MyPrintFunction() is
provided by the application writer):
void MyPrintFunction(const char *pcFormat, ... );
#define configPRINTF( X ) MyPrintFunction X
Then call like a standard printf() function, but placing brackets around
all parameters so they are passed as a single parameter. For example:
configPRINTF( ("Value = %d", MyVariable) ); */
#define configPRINTF( X )
#endif
#ifndef configMAX
/* The application writer has not provided their own MAX macro, so define
the following generic implementation. */
#define configMAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
#endif
#ifndef configMIN
/* The application writer has not provided their own MAX macro, so define
the following generic implementation. */
#define configMIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
#endif
#if configENABLE_BACKWARD_COMPATIBILITY == 1
#define eTaskStateGet eTaskGetState
#define portTickType TickType_t
@ -839,6 +971,10 @@ V8 if desired. */
#define xCoRoutineHandle CoRoutineHandle_t
#define pdTASK_HOOK_CODE TaskHookFunction_t
#define portTICK_RATE_MS portTICK_PERIOD_MS
#define pcTaskGetTaskName pcTaskGetName
#define pcTimerGetTimerName pcTimerGetName
#define pcQueueGetQueueName pcQueueGetName
#define vTaskGetTaskInfo vTaskGetInfo
/* Backward compatibility within the scheduler code only - these definitions
are not really required but are included for completeness. */
@ -846,12 +982,97 @@ V8 if desired. */
#define pdTASK_CODE TaskFunction_t
#define xListItem ListItem_t
#define xList List_t
/* For libraries that break the list data hiding, and access list structure
members directly (which is not supposed to be done). */
#define pxContainer pvContainer
#endif /* configENABLE_BACKWARD_COMPATIBILITY */
#ifndef configESP32_PER_TASK_DATA
#define configESP32_PER_TASK_DATA 1
#endif
#if( configUSE_ALTERNATIVE_API != 0 )
#error The alternative API was deprecated some time ago, and was removed in FreeRTOS V9.0 0
#endif
/* Set configUSE_TASK_FPU_SUPPORT to 0 to omit floating point support even
if floating point hardware is otherwise supported by the FreeRTOS port in use.
This constant is not supported by all FreeRTOS ports that include floating
point support. */
#ifndef configUSE_TASK_FPU_SUPPORT
#define configUSE_TASK_FPU_SUPPORT 1
#endif
/* Set configENABLE_MPU to 1 to enable MPU support and 0 to disable it. This is
currently used in ARMv8M ports. */
#ifndef configENABLE_MPU
#define configENABLE_MPU 0
#endif
/* Set configENABLE_FPU to 1 to enable FPU support and 0 to disable it. This is
currently used in ARMv8M ports. */
#ifndef configENABLE_FPU
#define configENABLE_FPU 1
#endif
/* Set configENABLE_TRUSTZONE to 1 enable TrustZone support and 0 to disable it.
This is currently used in ARMv8M ports. */
#ifndef configENABLE_TRUSTZONE
#define configENABLE_TRUSTZONE 1
#endif
/* Set configRUN_FREERTOS_SECURE_ONLY to 1 to run the FreeRTOS ARMv8M port on
the Secure Side only. */
#ifndef configRUN_FREERTOS_SECURE_ONLY
#define configRUN_FREERTOS_SECURE_ONLY 0
#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
* FreeRTOSConfig.h settings only allow a task to be created using statically
* allocated RAM, in which case when any task is deleted it is known that neither
* the task's stack or TCB should be freed. Sometimes the FreeRTOSConfig.h
* settings allow a task to be created using either statically or dynamically
* allocated RAM, in which case a member of the TCB is used to record whether the
* stack and/or TCB were allocated statically or dynamically, so when a task is
* deleted the RAM that was allocated dynamically is freed again and no attempt is
* made to free the RAM that was allocated statically.
* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is only true if it is possible for a
* task to be created using either statically or dynamically allocated RAM. Note
* that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with
* a statically allocated stack and a dynamically allocated TCB.
*
* The following table lists various combinations of portUSING_MPU_WRAPPERS,
* configSUPPORT_DYNAMIC_ALLOCATION and configSUPPORT_STATIC_ALLOCATION and
* when it is possible to have both static and dynamic allocation:
* +-----+---------+--------+-----------------------------+-----------------------------------+------------------+-----------+
* | MPU | Dynamic | Static | Available Functions | Possible Allocations | Both Dynamic and | Need Free |
* | | | | | | Static Possible | |
* +-----+---------+--------+-----------------------------+-----------------------------------+------------------+-----------+
* | 0 | 0 | 1 | xTaskCreateStatic | TCB - Static, Stack - Static | No | No |
* +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------|
* | 0 | 1 | 0 | xTaskCreate | TCB - Dynamic, Stack - Dynamic | No | Yes |
* +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------|
* | 0 | 1 | 1 | xTaskCreate, | 1. TCB - Dynamic, Stack - Dynamic | Yes | Yes |
* | | | | xTaskCreateStatic | 2. TCB - Static, Stack - Static | | |
* +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------|
* | 1 | 0 | 1 | xTaskCreateStatic, | TCB - Static, Stack - Static | No | No |
* | | | | xTaskCreateRestrictedStatic | | | |
* +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------|
* | 1 | 1 | 0 | xTaskCreate, | 1. TCB - Dynamic, Stack - Dynamic | Yes | Yes |
* | | | | xTaskCreateRestricted | 2. TCB - Dynamic, Stack - Static | | |
* +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------|
* | 1 | 1 | 1 | xTaskCreate, | 1. TCB - Dynamic, Stack - Dynamic | Yes | Yes |
* | | | | xTaskCreateStatic, | 2. TCB - Dynamic, Stack - Static | | |
* | | | | xTaskCreateRestricted, | 3. TCB - Static, Stack - Static | | |
* | | | | xTaskCreateRestrictedStatic | | | |
* +-----+---------+--------+-----------------------------+-----------------------------------+------------------+-----------+
*/
#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( ( portUSING_MPU_WRAPPERS == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) || \
( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) )
/*
* In line with software engineering best practice, FreeRTOS implements a strict
* data hiding policy, so the real structures used by FreeRTOS to maintain the
@ -864,25 +1085,40 @@ V8 if desired. */
*/
struct xSTATIC_LIST_ITEM
{
TickType_t xDummy1;
void *pvDummy2[ 4 ];
#if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 )
TickType_t xDummy1;
#endif
TickType_t xDummy2;
void *pvDummy3[ 4 ];
#if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 )
TickType_t xDummy4;
#endif
};
typedef struct xSTATIC_LIST_ITEM StaticListItem_t;
/* See the comments above the struct xSTATIC_LIST_ITEM definition. */
struct xSTATIC_MINI_LIST_ITEM
{
TickType_t xDummy1;
void *pvDummy2[ 2 ];
#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;
/* See the comments above the struct xSTATIC_LIST_ITEM definition. */
typedef struct xSTATIC_LIST
{
UBaseType_t uxDummy1;
void *pvDummy2;
StaticMiniListItem_t xDummy3;
#if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 )
TickType_t xDummy1;
#endif
UBaseType_t uxDummy2;
void *pvDummy3;
StaticMiniListItem_t xDummy4;
#if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 )
TickType_t xDummy5;
#endif
} StaticList_t;
/*
@ -908,13 +1144,12 @@ typedef struct xSTATIC_TCB
UBaseType_t uxDummy5;
void *pxDummy6;
uint8_t ucDummy7[ configMAX_TASK_NAME_LEN ];
UBaseType_t uxDummyCoreId;
#if ( portSTACK_GROWTH > 0 || configENABLE_TASK_SNAPSHOT == 1 )
void *pxDummy8;
BaseType_t xDummyCore;
#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
void *pxDummy8;
#endif
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
UBaseType_t uxDummy9;
uint32_t OldInterruptState;
#endif
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxDummy10[ 2 ];
@ -927,7 +1162,7 @@ typedef struct xSTATIC_TCB
#endif
#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
void *pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
#if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS )
#if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS )
void *pvDummyLocalStorageCallBack[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
#endif
#endif
@ -939,13 +1174,18 @@ typedef struct xSTATIC_TCB
#endif
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
uint32_t ulDummy18;
uint32_t ucDummy19;
uint8_t ucDummy19;
#endif
#if( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) \
|| ( portUSING_MPU_WRAPPERS == 1 ) )
#if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
uint8_t uxDummy20;
#endif
#if( INCLUDE_xTaskAbortDelay == 1 )
uint8_t ucDummy21;
#endif
#if ( configUSE_POSIX_ERRNO == 1 )
int iDummy22;
#endif
} StaticTask_t;
/*
@ -974,6 +1214,7 @@ typedef struct xSTATIC_QUEUE
StaticList_t xDummy3[ 2 ];
UBaseType_t uxDummy4[ 3 ];
uint8_t ucDummy5[ 2 ];
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
uint8_t ucDummy6;
@ -988,7 +1229,7 @@ typedef struct xSTATIC_QUEUE
uint8_t ucDummy9;
#endif
portMUX_TYPE muxDummy; //Mutex required due to SMP
portMUX_TYPE xDummy10;
} StaticQueue_t;
typedef StaticQueue_t StaticSemaphore_t;
@ -1020,7 +1261,7 @@ typedef struct xSTATIC_EVENT_GROUP
uint8_t ucDummy4;
#endif
portMUX_TYPE muxDummy; //Mutex required due to SMP
portMUX_TYPE xDummy5;
} StaticEventGroup_t;
@ -1043,18 +1284,44 @@ typedef struct xSTATIC_TIMER
void *pvDummy1;
StaticListItem_t xDummy2;
TickType_t xDummy3;
UBaseType_t uxDummy4;
void *pvDummy5[ 2 ];
void *pvDummy5;
TaskFunction_t pvDummy6;
#if( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxDummy6;
UBaseType_t uxDummy7;
#endif
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
uint8_t ucDummy7;
#endif
uint8_t ucDummy8;
} StaticTimer_t;
/*
* In line with software engineering best practice, especially when supplying a
* library that is likely to change in future versions, FreeRTOS implements a
* strict data hiding policy. This means the stream buffer structure used
* internally by FreeRTOS is not accessible to application code. However, if
* the application writer wants to statically allocate the memory required to
* create a stream buffer then the size of the stream buffer object needs to be
* know. The StaticStreamBuffer_t structure below is provided for this purpose.
* Its size and alignment requirements are guaranteed to match those of the
* genuine structure, no matter which architecture is being used, and no matter
* how the values in FreeRTOSConfig.h are set. Its contents are somewhat
* obfuscated in the hope users will recognise that it would be unwise to make
* direct use of the structure members.
*/
typedef struct xSTATIC_STREAM_BUFFER
{
size_t uxDummy1[ 4 ];
void * pvDummy2[ 3 ];
uint8_t ucDummy3;
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxDummy4;
#endif
portMUX_TYPE xDummy5;
} StaticStreamBuffer_t;
/* Message buffers are built on stream buffers. */
typedef StaticStreamBuffer_t StaticMessageBuffer_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,418 @@
/*
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/**
* @file atomic.h
* @brief FreeRTOS atomic operation support.
*
* This file implements atomic by disabling interrupts globally.
* Implementation with architecture specific atomic instructions
* are to be provided under each compiler directory.
*/
#ifndef ATOMIC_H
#define ATOMIC_H
#ifndef INC_FREERTOS_H
#error "include FreeRTOS.h must appear in source files before include atomic.h"
#endif
/* Standard includes. */
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Port specific definitions -- entering/exiting critical section.
* Refer template -- ./lib/FreeRTOS/portable/Compiler/Arch/portmacro.h
*
* Every call to ATOMIC_EXIT_CRITICAL() must be closely paired with
* ATOMIC_ENTER_CRITICAL().
* */
#if defined( portSET_INTERRUPT_MASK_FROM_ISR )
/* Nested interrupt scheme is supported in this port. */
#define ATOMIC_ENTER_CRITICAL() \
UBaseType_t uxCriticalSectionType = portSET_INTERRUPT_MASK_FROM_ISR()
#define ATOMIC_EXIT_CRITICAL() \
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxCriticalSectionType )
#else
/* Nested interrupt scheme is NOT supported in this port. */
#define ATOMIC_ENTER_CRITICAL() portENTER_CRITICAL()
#define ATOMIC_EXIT_CRITICAL() portEXIT_CRITICAL()
#endif /* portSET_INTERRUPT_MASK_FROM_ISR() */
/* Port specific definition -- "always inline".
* Inline is compiler specific, and may not always get inlined depending on your optimization level.
* Also, inline is considerred as performance optimization for atomic.
* Thus, if portFORCE_INLINE is not provided by portmacro.h, instead of resulting error,
* simply define it.
*/
#ifndef portFORCE_INLINE
#define portFORCE_INLINE
#endif
#define ATOMIC_COMPARE_AND_SWAP_SUCCESS 0x1U /**< Compare and swap succeeded, swapped. */
#define ATOMIC_COMPARE_AND_SWAP_FAILURE 0x0U /**< Compare and swap failed, did not swap. */
/*----------------------------- Swap && CAS ------------------------------*/
/**
* Atomic compare-and-swap
*
* @brief Performs an atomic compare-and-swap operation on the specified values.
*
* @param[in, out] pDestination Pointer to memory location from where value is
* to be loaded and checked.
* @param[in] ulExchange If condition meets, write this value to memory.
* @param[in] ulComparand Swap condition.
*
* @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.
*
* @note This function only swaps *pDestination with ulExchange, if previous
* *pDestination value equals ulComparand.
*/
static portFORCE_INLINE uint32_t Atomic_CompareAndSwap_u32(
uint32_t volatile * pDestination,
uint32_t ulExchange,
uint32_t ulComparand )
{
uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
ATOMIC_ENTER_CRITICAL();
if ( *pDestination == ulComparand )
{
*pDestination = ulExchange;
ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;
}
ATOMIC_EXIT_CRITICAL();
return ulReturnValue;
}
/**
* Atomic swap (pointers)
*
* @brief Atomically sets the address pointed to by *ppDestination to the value
* of *pExchange.
*
* @param[in, out] ppDestination Pointer to memory location from where a pointer
* value is to be loaded and written back to.
* @param[in] pExchange Pointer value to be written to *ppDestination.
*
* @return The initial value of *ppDestination.
*/
static portFORCE_INLINE void * Atomic_SwapPointers_p32(
void * volatile * ppDestination,
void * pExchange )
{
void * pReturnValue;
ATOMIC_ENTER_CRITICAL();
pReturnValue = *ppDestination;
*ppDestination = pExchange;
ATOMIC_EXIT_CRITICAL();
return pReturnValue;
}
/**
* Atomic compare-and-swap (pointers)
*
* @brief Performs an atomic compare-and-swap operation on the specified pointer
* values.
*
* @param[in, out] ppDestination Pointer to memory location from where a pointer
* value is to be loaded and checked.
* @param[in] pExchange If condition meets, write this value to memory.
* @param[in] pComparand Swap condition.
*
* @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.
*
* @note This function only swaps *ppDestination with pExchange, if previous
* *ppDestination value equals pComparand.
*/
static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32(
void * volatile * ppDestination,
void * pExchange, void * pComparand )
{
uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
ATOMIC_ENTER_CRITICAL();
if ( *ppDestination == pComparand )
{
*ppDestination = pExchange;
ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;
}
ATOMIC_EXIT_CRITICAL();
return ulReturnValue;
}
/*----------------------------- Arithmetic ------------------------------*/
/**
* Atomic add
*
* @brief Atomically adds count to the value of the specified pointer points to.
*
* @param[in,out] pAddend Pointer to memory location from where value is to be
* loaded and written back to.
* @param[in] ulCount Value to be added to *pAddend.
*
* @return previous *pAddend value.
*/
static portFORCE_INLINE uint32_t Atomic_Add_u32(
uint32_t volatile * pAddend,
uint32_t ulCount )
{
uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL();
ulCurrent = *pAddend;
*pAddend += ulCount;
ATOMIC_EXIT_CRITICAL();
return ulCurrent;
}
/**
* Atomic subtract
*
* @brief Atomically subtracts count from the value of the specified pointer
* pointers to.
*
* @param[in,out] pAddend Pointer to memory location from where value is to be
* loaded and written back to.
* @param[in] ulCount Value to be subtract from *pAddend.
*
* @return previous *pAddend value.
*/
static portFORCE_INLINE uint32_t Atomic_Subtract_u32(
uint32_t volatile * pAddend,
uint32_t ulCount )
{
uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL();
ulCurrent = *pAddend;
*pAddend -= ulCount;
ATOMIC_EXIT_CRITICAL();
return ulCurrent;
}
/**
* Atomic increment
*
* @brief Atomically increments the value of the specified pointer points to.
*
* @param[in,out] pAddend Pointer to memory location from where value is to be
* loaded and written back to.
*
* @return *pAddend value before increment.
*/
static portFORCE_INLINE uint32_t Atomic_Increment_u32( uint32_t volatile * pAddend )
{
uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL();
ulCurrent = *pAddend;
*pAddend += 1;
ATOMIC_EXIT_CRITICAL();
return ulCurrent;
}
/**
* Atomic decrement
*
* @brief Atomically decrements the value of the specified pointer points to
*
* @param[in,out] pAddend Pointer to memory location from where value is to be
* loaded and written back to.
*
* @return *pAddend value before decrement.
*/
static portFORCE_INLINE uint32_t Atomic_Decrement_u32( uint32_t volatile * pAddend )
{
uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL();
ulCurrent = *pAddend;
*pAddend -= 1;
ATOMIC_EXIT_CRITICAL();
return ulCurrent;
}
/*----------------------------- Bitwise Logical ------------------------------*/
/**
* Atomic OR
*
* @brief Performs an atomic OR operation on the specified values.
*
* @param [in, out] pDestination Pointer to memory location from where value is
* to be loaded and written back to.
* @param [in] ulValue Value to be ORed with *pDestination.
*
* @return The original value of *pDestination.
*/
static portFORCE_INLINE uint32_t Atomic_OR_u32(
uint32_t volatile * pDestination,
uint32_t ulValue )
{
uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL();
ulCurrent = *pDestination;
*pDestination |= ulValue;
ATOMIC_EXIT_CRITICAL();
return ulCurrent;
}
/**
* Atomic AND
*
* @brief Performs an atomic AND operation on the specified values.
*
* @param [in, out] pDestination Pointer to memory location from where value is
* to be loaded and written back to.
* @param [in] ulValue Value to be ANDed with *pDestination.
*
* @return The original value of *pDestination.
*/
static portFORCE_INLINE uint32_t Atomic_AND_u32(
uint32_t volatile * pDestination,
uint32_t ulValue )
{
uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL();
ulCurrent = *pDestination;
*pDestination &= ulValue;
ATOMIC_EXIT_CRITICAL();
return ulCurrent;
}
/**
* Atomic NAND
*
* @brief Performs an atomic NAND operation on the specified values.
*
* @param [in, out] pDestination Pointer to memory location from where value is
* to be loaded and written back to.
* @param [in] ulValue Value to be NANDed with *pDestination.
*
* @return The original value of *pDestination.
*/
static portFORCE_INLINE uint32_t Atomic_NAND_u32(
uint32_t volatile * pDestination,
uint32_t ulValue )
{
uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL();
ulCurrent = *pDestination;
*pDestination = ~(ulCurrent & ulValue);
ATOMIC_EXIT_CRITICAL();
return ulCurrent;
}
/**
* Atomic XOR
*
* @brief Performs an atomic XOR operation on the specified values.
*
* @param [in, out] pDestination Pointer to memory location from where value is
* to be loaded and written back to.
* @param [in] ulValue Value to be XORed with *pDestination.
*
* @return The original value of *pDestination.
*/
static portFORCE_INLINE uint32_t Atomic_XOR_u32(
uint32_t volatile * pDestination,
uint32_t ulValue )
{
uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL();
ulCurrent = *pDestination;
*pDestination ^= ulValue;
ATOMIC_EXIT_CRITICAL();
return ulCurrent;
}
#ifdef __cplusplus
}
#endif
#endif /* ATOMIC_H */

View File

@ -1,71 +1,29 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef CO_ROUTINE_H
#define CO_ROUTINE_H

View File

@ -1,71 +1,29 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef DEPRECATED_DEFINITIONS_H
#define DEPRECATED_DEFINITIONS_H
@ -82,12 +40,12 @@ projects should not use them. */
#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT
#include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h"
typedef void ( __interrupt __far *pxISR )(void);
typedef void ( __interrupt __far *pxISR )();
#endif
#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT
#include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h"
typedef void ( __interrupt __far *pxISR )(void);
typedef void ( __interrupt __far *pxISR )();
#endif
#ifdef GCC_MEGA_AVR
@ -255,7 +213,7 @@ projects should not use them. */
FreeRTOSConfig.h when using the Borland compiler. */
#include "frconfig.h"
#include "..\portable\BCC\16BitDOS\PC\prtmacro.h"
typedef void ( __interrupt __far *pxISR )(void);
typedef void ( __interrupt __far *pxISR )();
#endif
#ifdef BCC_FLASH_LITE_186_PORT
@ -263,7 +221,7 @@ projects should not use them. */
FreeRTOSConfig.h when using the Borland compiler. */
#include "frconfig.h"
#include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h"
typedef void ( __interrupt __far *pxISR )(void);
typedef void ( __interrupt __far *pxISR )();
#endif
#ifdef __GNUC__

View File

@ -1,71 +1,29 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef EVENT_GROUPS_H
#define EVENT_GROUPS_H
@ -74,6 +32,7 @@
#error "include FreeRTOS.h" must appear in source files before "include event_groups.h"
#endif
/* FreeRTOS includes. */
#include "timers.h"
#ifdef __cplusplus
@ -115,25 +74,31 @@ extern "C" {
* xEventGroupCreate() returns an EventGroupHandle_t variable that can then
* be used as a parameter to other event group functions.
*
* \defgroup EventGroupHandle_t EventGroupHandle_t
* \ingroup EventGroup
*/
struct EventGroupDef_t;
//typedef struct EventGroupDef_t * EventGroupHandle_t;
typedef void * 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.
* 32 bits if set to 0.
*
* \defgroup EventBits_t EventBits_t
* \ingroup EventGroup
*/
typedef TickType_t EventBits_t;
/**
*
*
* 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 xEventGroupCreate() then the required memory is
* groups is created using xEventGropuCreate() then the required memory is
* automatically dynamically allocated inside the xEventGroupCreate() function.
* (see http://www.freertos.org/a00111.html). If an event group is created
* using xEventGropuCreateStatic() then the application writer must instead
@ -311,6 +276,7 @@ typedef TickType_t EventBits_t;
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/**
*
* Clear bits within an event group. This function cannot be called from an
* interrupt.
*
@ -362,6 +328,7 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
/**
*
* A version of xEventGroupClearBits() that can be called from an interrupt.
*
* Setting bits in an event group is not a deterministic operation because there
@ -370,8 +337,8 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBit
* while interrupts are disabled, so protects event groups that are accessed
* from tasks by suspending the scheduler rather than disabling interrupts. As
* a result event groups cannot be accessed directly from an interrupt service
* routine. Therefore xEventGroupClearBitsFromISR() sends a message to the
* timer task to have the clear operation performed in the context of the timer
* routine. Therefore xEventGroupClearBitsFromISR() sends a message to the
* timer task to have the clear operation performed in the context of the timer
* task.
*
* @param xEventGroup The event group in which the bits are to be cleared.
@ -380,8 +347,8 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBit
* For example, to clear bit 3 only, set uxBitsToClear to 0x08. To clear bit 3
* and bit 0 set uxBitsToClear to 0x09.
*
* @return If the request to execute the function was posted successfully then
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
* @return If the request to execute the function was posted successfully then
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
* if the timer service queue was full.
*
* Example usage:
@ -409,12 +376,13 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBit
* \ingroup EventGroup
*/
#if( configUSE_TRACE_FACILITY == 1 )
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
#else
#define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL )
#endif
/**
*
* Set bits within an event group.
* This function cannot be called from an interrupt. xEventGroupSetBitsFromISR()
* is a version that can be called from an interrupt.
@ -483,12 +451,13 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBit
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION;
/**
*
* A version of xEventGroupSetBits() that can be called from an interrupt.
*
* Setting bits in an event group is not a deterministic operation because there
* are an unknown number of tasks that may be waiting for the bit or bits being
* set. FreeRTOS does not allow nondeterministic operations to be performed in
* interrupts or from critical sections. Therefore xEventGroupSetBitFromISR()
* interrupts or from critical sections. Therefore xEventGroupSetBitsFromISR()
* sends a message to the timer task to have the set operation performed in the
* context of the timer task - where a scheduler lock is used in place of a
* critical section.
@ -509,8 +478,8 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_
* *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the
* example code below.
*
* @return If the request to execute the function was posted successfully then
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
* @return If the request to execute the function was posted successfully then
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
* if the timer service queue was full.
*
* Example usage:
@ -549,12 +518,13 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_
* \ingroup EventGroup
*/
#if( configUSE_TRACE_FACILITY == 1 )
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
#else
#define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken )
#endif
/**
*
* 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
* used to synchronise multiple tasks, where each task has to wait for the other
@ -625,7 +595,7 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_
* // All three tasks reached the synchronisation point before the call
* // to xEventGroupSync() timed out.
* }
* }
* }
* }
*
* void vTask1( void *pvParameters )
@ -663,7 +633,7 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_
* // xEventGroupSync() was called with an indefinite block time, so
* // this task will only reach here if the syncrhonisation was made by all
* // three tasks, so there is no need to test the return value.
* }
* }
* }
*
* @endcode
@ -673,6 +643,7 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t u
/**
*
* Returns the current value of the bits in an event group. This function
* cannot be used from an interrupt.
*
@ -685,6 +656,7 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t u
#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 )
/**
*
* A version of xEventGroupGetBits() that can be called from an ISR.
*
* @param xEventGroup The event group being queried.
@ -693,26 +665,27 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t u
*
* \ingroup EventGroup
*/
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
/**
*
* Delete an event group that was previously created by a call to
* xEventGroupCreate(). Tasks that are blocked on the event group will be
* unblocked and obtain 0 as the event group's value.
*
* @param xEventGroup The event group being deleted.
*/
void vEventGroupDelete( EventGroupHandle_t xEventGroup );
void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
/** @cond */
/* For internal use only. */
void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet );
void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear );
void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION;
void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION;
#if (configUSE_TRACE_FACILITY == 1)
UBaseType_t uxEventGroupGetNumber( void* xEventGroup );
UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) PRIVILEGED_FUNCTION;
void vEventGroupSetNumber( void* xEventGroup, UBaseType_t uxEventGroupNumber ) PRIVILEGED_FUNCTION;
#endif
/** @endcond */

View File

@ -1,71 +1,29 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/*
* This is the list implementation used by the scheduler. While it is tailored
@ -178,52 +136,40 @@ use of FreeRTOS.*/
/*
* Definition of the only type of object that a list can contain.
*/
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. */
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. */
void * configLIST_VOLATILE pvContainer; /*< 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. */
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. */
#if __GNUC_PREREQ(4, 6)
_Static_assert(sizeof(StaticListItem_t) == sizeof(ListItem_t), "StaticListItem_t != ListItem_t");
#endif
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. */
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 __GNUC_PREREQ(4, 6)
_Static_assert(sizeof(StaticMiniListItem_t) == sizeof(MiniListItem_t), "StaticMiniListItem_t != 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. */
configLIST_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. */
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. */
} List_t;
#if __GNUC_PREREQ(4, 6)
_Static_assert(sizeof(StaticList_t) == sizeof(List_t), "StaticList_t != List_t");
#endif
/*
* Access macro to set the owner of a list item. The owner of a list item
* is the object (usually a TCB) that contains the list item.
@ -237,7 +183,7 @@ _Static_assert(sizeof(StaticList_t) == sizeof(List_t), "StaticList_t != List_t")
* Access macro to get the owner of a list item. The owner of a list item
* is the object (usually a TCB) that contains the list item.
*
* \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
* \page listGET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
* \ingroup LinkedList
*/
#define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner )
@ -279,7 +225,7 @@ _Static_assert(sizeof(StaticList_t) == sizeof(List_t), "StaticList_t != List_t")
#define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext )
/*
* Return the list item at the head of the list.
* Return the next list item.
*
* \page listGET_NEXT listGET_NEXT
* \ingroup LinkedList
@ -301,7 +247,7 @@ _Static_assert(sizeof(StaticList_t) == sizeof(List_t), "StaticList_t != List_t")
* \page listLIST_IS_EMPTY listLIST_IS_EMPTY
* \ingroup LinkedList
*/
#define listLIST_IS_EMPTY( pxList ) ( ( BaseType_t ) ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) )
#define listLIST_IS_EMPTY( pxList ) ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE )
/*
* Access macro to return the number of items in the list.
@ -369,7 +315,7 @@ List_t * const pxConstList = ( pxList ); \
* @param pxListItem The list item we want to know if is in the list.
* @return pdTRUE if the list item is in the list, otherwise pdFALSE.
*/
#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( BaseType_t ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) )
#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( ( pxListItem )->pxContainer == ( pxList ) ) ? ( pdTRUE ) : ( pdFALSE ) )
/*
* Return the list a list item is contained within (referenced from).
@ -377,7 +323,7 @@ List_t * const pxConstList = ( pxList ); \
* @param pxListItem The list item being queried.
* @return A pointer to the List_t object that references the pxListItem
*/
#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pvContainer )
#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pxContainer )
/*
* This provides a crude means of knowing if a list has been initialised, as
@ -396,7 +342,7 @@ List_t * const pxConstList = ( pxList ); \
* \page vListInitialise vListInitialise
* \ingroup LinkedList
*/
void vListInitialise( List_t * const pxList );
void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION;
/*
* Must be called before a list item is used. This sets the list container to
@ -407,7 +353,7 @@ void vListInitialise( List_t * const pxList );
* \page vListInitialiseItem vListInitialiseItem
* \ingroup LinkedList
*/
void vListInitialiseItem( ListItem_t * const pxItem );
void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION;
/*
* Insert a list item into a list. The item will be inserted into the list in
@ -420,19 +366,19 @@ void vListInitialiseItem( ListItem_t * const pxItem );
* \page vListInsert vListInsert
* \ingroup LinkedList
*/
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem );
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
/*
* 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 pvIndex is used to walk through a list. Calling
* listGET_OWNER_OF_NEXT_ENTRY increments pvIndex to the next item in the list.
* 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 pvIndex. This means that every other
* 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 pvIndex parameter again points to the item being inserted.
* the pxIndex parameter again points to the item being inserted.
*
* @param pxList The list into which the item is to be inserted.
*
@ -441,7 +387,7 @@ void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem );
* \page vListInsertEnd vListInsertEnd
* \ingroup LinkedList
*/
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem );
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
/*
* Remove an item from a list. The list item has a pointer to the list that
@ -456,7 +402,7 @@ void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem );
* \page uxListRemove uxListRemove
* \ingroup LinkedList
*/
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove );
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION;
#ifdef __cplusplus
}

View File

@ -0,0 +1,702 @@
/*
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/*
* Message buffers build functionality on top of FreeRTOS stream buffers.
* Whereas stream buffers are used to send a continuous stream of data from one
* task or interrupt to another, message buffers are used to send variable
* length discrete messages from one task or interrupt to another. Their
* implementation is light weight, making them particularly suited for interrupt
* to task and core to core communication scenarios.
*
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
* implementation (so also the message buffer implementation, as message buffers
* are built on top of stream buffers) assumes there is only one task or
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader). It is safe for the
* writer and reader to be different tasks or interrupts, but, unlike other
* FreeRTOS objects, it is not safe to have multiple different writers or
* multiple different readers. If there are to be multiple different writers
* then the application writer must place each call to a writing API function
* (such as xMessageBufferSend()) inside a critical section and set the send
* block time to 0. Likewise, if there are to be multiple different readers
* then the application writer must place each call to a reading API function
* (such as xMessageBufferRead()) inside a critical section and set the receive
* timeout to 0.
*
* Message buffers hold variable length messages. To enable that, when a
* message is written to the message buffer an additional sizeof( size_t ) bytes
* are also written to store the message's length (that happens internally, with
* the API function). sizeof( size_t ) is typically 4 bytes on a 32-bit
* architecture, so writing a 10 byte message to a message buffer on a 32-bit
* architecture will actually reduce the available space in the message buffer
* by 14 bytes (10 byte are used by the message, and 4 bytes to hold the length
* of the message).
*/
#ifndef FREERTOS_MESSAGE_BUFFER_H
#define FREERTOS_MESSAGE_BUFFER_H
#ifndef INC_FREERTOS_H
#error "include FreeRTOS.h must appear in source files before include message_buffer.h"
#endif
/* Message buffers are built onto of stream buffers. */
#include "stream_buffer.h"
#if defined( __cplusplus )
extern "C" {
#endif
/**
* 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.
*/
typedef void * MessageBufferHandle_t;
/*-----------------------------------------------------------*/
/**
* Creates a new message buffer using dynamically allocated memory. See
* xMessageBufferCreateStatic() for a version that uses statically allocated
* memory (memory that is allocated at compile time).
*
* configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 or left undefined in
* FreeRTOSConfig.h for xMessageBufferCreate() to be available.
*
* @param xBufferSizeBytes The total number of bytes (not messages) the message
* buffer will be able to hold at any one time. When a message is written to
* the message buffer an additional sizeof( size_t ) bytes are also written to
* store the message's length. sizeof( size_t ) is typically 4 bytes on a
* 32-bit architecture, so on most 32-bit architectures a 10 byte message will
* take up 14 bytes of message buffer space.
*
* @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
* returned indicates that the message buffer has been created successfully -
* the returned value should be stored as the handle to the created message
* buffer.
*
* Example use:
* @code{c}
*
* void vAFunction( void )
* {
* MessageBufferHandle_t xMessageBuffer;
* const size_t xMessageBufferSizeBytes = 100;
*
* // 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.
* xMessageBuffer = xMessageBufferCreate( xMessageBufferSizeBytes );
*
* if( xMessageBuffer == NULL )
* {
* // There was not enough heap memory space available to create the
* // message buffer.
* }
* else
* {
* // The message buffer was created successfully and can now be used.
* }
*
* @endcode
* \ingroup MessageBufferManagement
*/
#define xMessageBufferCreate( xBufferSizeBytes ) ( MessageBufferHandle_t ) xStreamBufferGenericCreate( xBufferSizeBytes, ( size_t ) 0, pdTRUE )
/**
* Creates a new message buffer using statically allocated memory. See
* xMessageBufferCreate() for a version that uses dynamically allocated memory.
*
* @param xBufferSizeBytes The size, in bytes, of the buffer pointed to by the
* pucMessageBufferStorageArea parameter. When a message is written to the
* message buffer an additional sizeof( size_t ) bytes are also written to store
* the message's length. sizeof( size_t ) is typically 4 bytes on a 32-bit
* architecture, so on most 32-bit architecture a 10 byte message will take up
* 14 bytes of message buffer space. The maximum number of bytes that can be
* 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
* 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.
*
* @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.
* #define STORAGE_SIZE_BYTES 1000
*
* // Defines the memory that will actually hold the messages within the message
* // buffer.
* static uint8_t ucStorageBuffer[ STORAGE_SIZE_BYTES ];
*
* // The variable used to hold the message buffer structure.
* StaticMessageBuffer_t xMessageBufferStruct;
*
* void MyFunction( void )
* {
* MessageBufferHandle_t xMessageBuffer;
*
* xMessageBuffer = xMessageBufferCreateStatic( sizeof( ucBufferStorage ),
* ucBufferStorage,
* &xMessageBufferStruct );
*
* // As neither the pucMessageBufferStorageArea or pxStaticMessageBuffer
* // parameters were NULL, xMessageBuffer will not be NULL, and can be used to
* // reference the created message buffer in other message buffer API calls.
*
* // Other code that uses the message buffer can go here.
* }
*
* @endcode
* \ingroup MessageBufferManagement
*/
#define xMessageBufferCreateStatic( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer ) ( MessageBufferHandle_t ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, 0, pdTRUE, pucMessageBufferStorageArea, pxStaticMessageBuffer )
/**
* 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
* buffer.
*
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
* implementation (so also the message buffer implementation, as message buffers
* are built on top of stream buffers) assumes there is only one task or
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader). It is safe for the
* writer and reader to be different tasks or interrupts, but, unlike other
* FreeRTOS objects, it is not safe to have multiple different writers or
* multiple different readers. If there are to be multiple different writers
* then the application writer must place each call to a writing API function
* (such as xMessageBufferSend()) inside a critical section and set the send
* block time to 0. Likewise, if there are to be multiple different readers
* then the application writer must place each call to a reading API function
* (such as xMessageBufferRead()) inside a critical section and set the receive
* block time to 0.
*
* Use xMessageBufferSend() to write to a message buffer from a task. Use
* xMessageBufferSendFromISR() to write to a message buffer from an interrupt
* service routine (ISR).
*
* @param xMessageBuffer The handle of the message buffer to which a message is
* being sent.
*
* @param pvTxData A pointer to the message that is to be copied into the
* message buffer.
*
* @param xDataLengthBytes The length of the message. That is, the number of
* bytes to copy from pvTxData into the message buffer. When a message is
* written to the message buffer an additional sizeof( size_t ) bytes are also
* written to store the message's length. sizeof( size_t ) is typically 4 bytes
* on a 32-bit architecture, so on most 32-bit architecture setting
* xDataLengthBytes to 20 will reduce the free space in the message buffer by 24
* bytes (20 bytes of message data and 4 bytes to hold the message length).
*
* @param xTicksToWait The maximum amount of time the calling task should remain
* in the Blocked state to wait for enough space to become available in the
* message buffer, should the message buffer have insufficient space when
* xMessageBufferSend() is called. The calling task will never block if
* xTicksToWait is zero. The block time is specified in tick periods, so the
* absolute time it represents is dependent on the tick frequency. The macro
* pdMS_TO_TICKS() can be used to convert a time specified in milliseconds into
* a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will cause
* the task to wait indefinitely (without timing out), provided
* INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. Tasks do not use any
* CPU time when they are in the Blocked state.
*
* @return The number of bytes written to the message buffer. If the call to
* xMessageBufferSend() times out before there was enough space to write the
* message into the message buffer then zero is returned. If the call did not
* time out then xDataLengthBytes is returned.
*
* Example use:
* @code{c}
* void vAFunction( MessageBufferHandle_t xMessageBuffer )
* {
* size_t xBytesSent;
* uint8_t ucArrayToSend[] = { 0, 1, 2, 3 };
* char *pcStringToSend = "String to send";
* const TickType_t x100ms = pdMS_TO_TICKS( 100 );
*
* // Send an array to the message buffer, blocking for a maximum of 100ms to
* // wait for enough space to be available in the message buffer.
* xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms );
*
* if( xBytesSent != sizeof( ucArrayToSend ) )
* {
* // The call to xMessageBufferSend() times out before there was enough
* // space in the buffer for the data to be written.
* }
*
* // Send the string to the message buffer. Return immediately if there is
* // not enough space in the buffer.
* xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 );
*
* if( xBytesSent != strlen( pcStringToSend ) )
* {
* // The string could not be added to the message buffer because there was
* // not enough free space in the buffer.
* }
* }
* @endcode
* \ingroup MessageBufferManagement
*/
#define xMessageBufferSend( xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) xStreamBufferSend( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait )
/**
* 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
* buffer's free space, and is copied into the buffer.
*
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
* implementation (so also the message buffer implementation, as message buffers
* are built on top of stream buffers) assumes there is only one task or
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader). It is safe for the
* writer and reader to be different tasks or interrupts, but, unlike other
* FreeRTOS objects, it is not safe to have multiple different writers or
* multiple different readers. If there are to be multiple different writers
* then the application writer must place each call to a writing API function
* (such as xMessageBufferSend()) inside a critical section and set the send
* block time to 0. Likewise, if there are to be multiple different readers
* then the application writer must place each call to a reading API function
* (such as xMessageBufferRead()) inside a critical section and set the receive
* block time to 0.
*
* Use xMessageBufferSend() to write to a message buffer from a task. Use
* xMessageBufferSendFromISR() to write to a message buffer from an interrupt
* service routine (ISR).
*
* @param xMessageBuffer The handle of the message buffer to which a message is
* being sent.
*
* @param pvTxData A pointer to the message that is to be copied into the
* message buffer.
*
* @param xDataLengthBytes The length of the message. That is, the number of
* bytes to copy from pvTxData into the message buffer. When a message is
* written to the message buffer an additional sizeof( size_t ) bytes are also
* written to store the message's length. sizeof( size_t ) is typically 4 bytes
* on a 32-bit architecture, so on most 32-bit architecture setting
* xDataLengthBytes to 20 will reduce the free space in the message buffer by 24
* bytes (20 bytes of message data and 4 bytes to hold the message length).
*
* @param pxHigherPriorityTaskWoken It is possible that a message buffer will
* have a task blocked on it waiting for data. Calling
* xMessageBufferSendFromISR() can make data available, and so cause a task that
* was waiting for data to leave the Blocked state. If calling
* xMessageBufferSendFromISR() causes a task to leave the Blocked state, and the
* unblocked task has a priority higher than the currently executing task (the
* task that was interrupted), then, internally, xMessageBufferSendFromISR()
* will set *pxHigherPriorityTaskWoken to pdTRUE. If
* xMessageBufferSendFromISR() sets this value to pdTRUE, then normally a
* context switch should be performed before the interrupt is exited. This will
* ensure that the interrupt returns directly to the highest priority Ready
* state task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it
* is passed into the function. See the code example below for an example.
*
* @return The number of bytes actually written to the message buffer. If the
* message buffer didn't have enough free space for the message to be stored
* then 0 is returned, otherwise xDataLengthBytes is returned.
*
* Example use:
* @code{c}
* // A message buffer that has already been created.
* MessageBufferHandle_t xMessageBuffer;
*
* void vAnInterruptServiceRoutine( void )
* {
* size_t xBytesSent;
* char *pcStringToSend = "String to send";
* BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
*
* // Attempt to send the string to the message buffer.
* xBytesSent = xMessageBufferSendFromISR( xMessageBuffer,
* ( void * ) pcStringToSend,
* strlen( pcStringToSend ),
* &xHigherPriorityTaskWoken );
*
* if( xBytesSent != strlen( pcStringToSend ) )
* {
* // The string could not be added to the message buffer because there was
* // not enough free space in the buffer.
* }
*
* // If xHigherPriorityTaskWoken was set to pdTRUE inside
* // xMessageBufferSendFromISR() then a task that has a priority above the
* // 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 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.
* portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
* }
* @endcode
* \ingroup MessageBufferManagement
*/
#define xMessageBufferSendFromISR( xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) xStreamBufferSendFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken )
/**
* Receives a discrete message from a message buffer. Messages can be of
* variable length and are copied out of the buffer.
*
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
* implementation (so also the message buffer implementation, as message buffers
* are built on top of stream buffers) assumes there is only one task or
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader). It is safe for the
* writer and reader to be different tasks or interrupts, but, unlike other
* FreeRTOS objects, it is not safe to have multiple different writers or
* multiple different readers. If there are to be multiple different writers
* then the application writer must place each call to a writing API function
* (such as xMessageBufferSend()) inside a critical section and set the send
* block time to 0. Likewise, if there are to be multiple different readers
* then the application writer must place each call to a reading API function
* (such as xMessageBufferRead()) inside a critical section and set the receive
* block time to 0.
*
* Use xMessageBufferReceive() to read from a message buffer from a task. Use
* xMessageBufferReceiveFromISR() to read from a message buffer from an
* interrupt service routine (ISR).
*
* @param xMessageBuffer The handle of the message buffer from which a message
* is being received.
*
* @param pvRxData A pointer to the buffer into which the received message is
* to be copied.
*
* @param xBufferLengthBytes The length of the buffer pointed to by the pvRxData
* parameter. This sets the maximum length of the message that can be received.
* If xBufferLengthBytes is too small to hold the next message then the message
* will be left in the message buffer and 0 will be returned.
*
* @param xTicksToWait The maximum amount of time the task should remain in the
* Blocked state to wait for a message, should the message buffer be empty.
* xMessageBufferReceive() will return immediately if xTicksToWait is zero and
* the message buffer is empty. The block time is specified in tick periods, so
* the absolute time it represents is dependent on the tick frequency. The
* macro pdMS_TO_TICKS() can be used to convert a time specified in milliseconds
* into a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will
* cause the task to wait indefinitely (without timing out), provided
* INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. Tasks do not use any
* CPU time when they are in the Blocked state.
*
* @return The length, in bytes, of the message read from the message buffer, if
* any. If xMessageBufferReceive() times out before a message became available
* then zero is returned. If the length of the message is greater than
* xBufferLengthBytes then the message will be left in the message buffer and
* zero is returned.
*
* Example use:
* @code{c}
* void vAFunction( MessageBuffer_t xMessageBuffer )
* {
* uint8_t ucRxData[ 20 ];
* size_t xReceivedBytes;
* const TickType_t xBlockTime = pdMS_TO_TICKS( 20 );
*
* // Receive the next message from the message buffer. Wait in the Blocked
* // state (so not using any CPU processing time) for a maximum of 100ms for
* // a message to become available.
* xReceivedBytes = xMessageBufferReceive( xMessageBuffer,
* ( void * ) ucRxData,
* sizeof( ucRxData ),
* xBlockTime );
*
* if( xReceivedBytes > 0 )
* {
* // A ucRxData contains a message that is xReceivedBytes long. Process
* // the message here....
* }
* }
* @endcode
* \ingroup MessageBufferManagement
*/
#define xMessageBufferReceive( xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) xStreamBufferReceive( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait )
/**
* 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
* copied out of the buffer.
*
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
* implementation (so also the message buffer implementation, as message buffers
* are built on top of stream buffers) assumes there is only one task or
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader). It is safe for the
* writer and reader to be different tasks or interrupts, but, unlike other
* FreeRTOS objects, it is not safe to have multiple different writers or
* multiple different readers. If there are to be multiple different writers
* then the application writer must place each call to a writing API function
* (such as xMessageBufferSend()) inside a critical section and set the send
* block time to 0. Likewise, if there are to be multiple different readers
* then the application writer must place each call to a reading API function
* (such as xMessageBufferRead()) inside a critical section and set the receive
* block time to 0.
*
* Use xMessageBufferReceive() to read from a message buffer from a task. Use
* xMessageBufferReceiveFromISR() to read from a message buffer from an
* interrupt service routine (ISR).
*
* @param xMessageBuffer The handle of the message buffer from which a message
* is being received.
*
* @param pvRxData A pointer to the buffer into which the received message is
* to be copied.
*
* @param xBufferLengthBytes The length of the buffer pointed to by the pvRxData
* parameter. This sets the maximum length of the message that can be received.
* If xBufferLengthBytes is too small to hold the next message then the message
* will be left in the message buffer and 0 will be returned.
*
* @param pxHigherPriorityTaskWoken It is possible that a message buffer will
* have a task blocked on it waiting for space to become available. Calling
* xMessageBufferReceiveFromISR() can make space available, and so cause a task
* that is waiting for space to leave the Blocked state. If calling
* xMessageBufferReceiveFromISR() causes a task to leave the Blocked state, and
* the unblocked task has a priority higher than the currently executing task
* (the task that was interrupted), then, internally,
* xMessageBufferReceiveFromISR() will set *pxHigherPriorityTaskWoken to pdTRUE.
* If xMessageBufferReceiveFromISR() sets this value to pdTRUE, then normally a
* context switch should be performed before the interrupt is exited. That will
* ensure the interrupt returns directly to the highest priority Ready state
* task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it is
* passed into the function. See the code example below for an example.
*
* @return The length, in bytes, of the message read from the message buffer, if
* any.
*
* Example use:
* @code{c}
* // A message buffer that has already been created.
* MessageBuffer_t xMessageBuffer;
*
* void vAnInterruptServiceRoutine( void )
* {
* uint8_t ucRxData[ 20 ];
* size_t xReceivedBytes;
* BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
*
* // Receive the next message from the message buffer.
* xReceivedBytes = xMessageBufferReceiveFromISR( xMessageBuffer,
* ( void * ) ucRxData,
* sizeof( ucRxData ),
* &xHigherPriorityTaskWoken );
*
* if( xReceivedBytes > 0 )
* {
* // A ucRxData contains a message that is xReceivedBytes long. Process
* // the message here....
* }
*
* // If xHigherPriorityTaskWoken was set to pdTRUE inside
* // xMessageBufferReceiveFromISR() then a task that has a priority above the
* // 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 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.
* portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
* }
* @endcode
* \ingroup MessageBufferManagement
*/
#define xMessageBufferReceiveFromISR( xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) xStreamBufferReceiveFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken )
/**
* Deletes a message buffer that was previously created using a call to
* xMessageBufferCreate() or xMessageBufferCreateStatic(). If the message
* buffer was created using dynamic memory (that is, by xMessageBufferCreate()),
* then the allocated memory is freed.
*
* A message buffer handle must not be used after the message buffer has been
* deleted.
*
* @param xMessageBuffer The handle of the message buffer to be deleted.
*
*/
#define vMessageBufferDelete( xMessageBuffer ) vStreamBufferDelete( ( StreamBufferHandle_t ) xMessageBuffer )
/**
* 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
* by a message being removed from the message buffer.
*
* @param xMessageBuffer The handle of the message buffer being queried.
*
* @return If the message buffer referenced by xMessageBuffer is full then
* pdTRUE is returned. Otherwise pdFALSE is returned.
*/
#define xMessageBufferIsFull( xMessageBuffer ) xStreamBufferIsFull( ( StreamBufferHandle_t ) xMessageBuffer )
/**
* Tests to see if a message buffer is empty (does not contain any messages).
*
* @param xMessageBuffer The handle of the message buffer being queried.
*
* @return If the message buffer referenced by xMessageBuffer is empty then
* pdTRUE is returned. Otherwise pdFALSE is returned.
*
*/
#define xMessageBufferIsEmpty( xMessageBuffer ) xStreamBufferIsEmpty( ( StreamBufferHandle_t ) xMessageBuffer )
/**
* Resets a message buffer to its initial empty state, discarding any message it
* contained.
*
* A message buffer can only be reset if there are no tasks blocked on it.
*
* @param xMessageBuffer The handle of the message buffer being reset.
*
* @return If the message buffer was reset then pdPASS is returned. If the
* message buffer could not be reset because either there was a task blocked on
* the message queue to wait for space to become available, or to wait for a
* a message to be available, then pdFAIL is returned.
*
* \ingroup MessageBufferManagement
*/
#define xMessageBufferReset( xMessageBuffer ) xStreamBufferReset( ( StreamBufferHandle_t ) xMessageBuffer )
/**
* Returns the number of bytes of free space in the message buffer.
*
* @param xMessageBuffer The handle of the message buffer being queried.
*
* @return The number of bytes that can be written to the message buffer before
* the message buffer would be full. When a message is written to the message
* buffer an additional sizeof( size_t ) bytes are also written to store the
* message's length. sizeof( size_t ) is typically 4 bytes on a 32-bit
* architecture, so if xMessageBufferSpacesAvailable() returns 10, then the size
* of the largest message that can be written to the message buffer is 6 bytes.
*
* \ingroup MessageBufferManagement
*/
#define xMessageBufferSpaceAvailable( xMessageBuffer ) xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer )
#define xMessageBufferSpacesAvailable( xMessageBuffer ) xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer ) /* Corrects typo in original macro name. */
/**
* 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.
*
* @param xMessageBuffer The handle of the message buffer being queried.
*
* @return The length (in bytes) of the next message in the message buffer, or 0
* if the message buffer is empty.
*
* \ingroup MessageBufferManagement
*/
#define xMessageBufferNextLengthBytes( xMessageBuffer ) xStreamBufferNextMessageLengthBytes( ( StreamBufferHandle_t ) xMessageBuffer ) PRIVILEGED_FUNCTION;
/**
* For advanced users only.
*
* The sbSEND_COMPLETED() macro is called from within the FreeRTOS APIs when
* data is sent to a message buffer or stream buffer. If there was a task that
* was blocked on the message or stream buffer waiting for data to arrive then
* the sbSEND_COMPLETED() macro sends a notification to the task to remove it
* from the Blocked state. xMessageBufferSendCompletedFromISR() does the same
* thing. It is provided to enable application writers to implement their own
* version of sbSEND_COMPLETED(), and MUST NOT BE USED AT ANY OTHER TIME.
*
* See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
* additional information.
*
* @param xMessageBuffer The handle of the stream buffer to which data was
* written.
*
* @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
* initialised to pdFALSE before it is passed into
* xMessageBufferSendCompletedFromISR(). If calling
* xMessageBufferSendCompletedFromISR() removes a task from the Blocked state,
* and the task has a priority above the priority of the currently running task,
* then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
* context switch should be performed before exiting the ISR.
*
* @return If a task was removed from the Blocked state then pdTRUE is returned.
* Otherwise pdFALSE is returned.
*
* \ingroup StreamBufferManagement
*/
#define xMessageBufferSendCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) xStreamBufferSendCompletedFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pxHigherPriorityTaskWoken )
/**
* For advanced users only.
*
* The sbRECEIVE_COMPLETED() macro is called from within the FreeRTOS APIs when
* data is read out of a message buffer or stream buffer. If there was a task
* that was blocked on the message or stream buffer waiting for data to arrive
* then the sbRECEIVE_COMPLETED() macro sends a notification to the task to
* remove it from the Blocked state. xMessageBufferReceiveCompletedFromISR()
* does the same thing. It is provided to enable application writers to
* implement their own version of sbRECEIVE_COMPLETED(), and MUST NOT BE USED AT
* ANY OTHER TIME.
*
* See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
* additional information.
*
* @param xMessageBuffer The handle of the stream buffer from which data was
* read.
*
* @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
* initialised to pdFALSE before it is passed into
* xMessageBufferReceiveCompletedFromISR(). If calling
* xMessageBufferReceiveCompletedFromISR() removes a task from the Blocked state,
* and the task has a priority above the priority of the currently running task,
* then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
* context switch should be performed before exiting the ISR.
*
* @return If a task was removed from the Blocked state then pdTRUE is returned.
* Otherwise pdFALSE is returned.
*
* \ingroup StreamBufferManagement
*/
#define xMessageBufferReceiveCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) xStreamBufferReceiveCompletedFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pxHigherPriorityTaskWoken )
#if defined( __cplusplus )
} /* extern "C" */
#endif
#endif /* !defined( FREERTOS_MESSAGE_BUFFER_H ) */

View File

@ -1,71 +1,29 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef MPU_WRAPPERS_H
#define MPU_WRAPPERS_H
@ -79,68 +37,139 @@ only for ports that are using the MPU. */
those files. */
#ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#define xTaskGenericCreate MPU_xTaskGenericCreate
#define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions
#define vTaskDelete MPU_vTaskDelete
#define vTaskDelayUntil MPU_vTaskDelayUntil
#define vTaskDelay MPU_vTaskDelay
#define uxTaskPriorityGet MPU_uxTaskPriorityGet
#define vTaskPrioritySet MPU_vTaskPrioritySet
#define eTaskGetState MPU_eTaskGetState
#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 vTaskList MPU_vTaskList
#define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats
#define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag
#define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag
#define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook
#define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark
#define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle
#define xTaskGetSchedulerState MPU_xTaskGetSchedulerState
#define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle
#define uxTaskGetSystemState MPU_uxTaskGetSystemState
/*
* Map standard (non MPU) API functions to equivalents that start
* "MPU_". This will cause the application code to call the MPU_
* version, which wraps the non-MPU version with privilege promoting
* then demoting code, so the kernel code always runs will full
* privileges.
*/
#define xQueueGenericCreate MPU_xQueueGenericCreate
#define xQueueCreateMutex MPU_xQueueCreateMutex
#define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive
#define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive
#define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore
#define xQueueGenericSend MPU_xQueueGenericSend
#define xQueueAltGenericSend MPU_xQueueAltGenericSend
#define xQueueAltGenericReceive MPU_xQueueAltGenericReceive
#define xQueueGenericReceive MPU_xQueueGenericReceive
#define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting
#define vQueueDelete MPU_vQueueDelete
#define xQueueGenericReset MPU_xQueueGenericReset
#define xQueueCreateSet MPU_xQueueCreateSet
#define xQueueSelectFromSet MPU_xQueueSelectFromSet
#define xQueueAddToSet MPU_xQueueAddToSet
#define xQueueRemoveFromSet MPU_xQueueRemoveFromSet
#define xQueuePeekFromISR MPU_xQueuePeekFromISR
#define xQueueGetMutexHolder MPU_xQueueGetMutexHolder
/* Map standard tasks.h API functions to the MPU equivalents. */
#define xTaskCreate MPU_xTaskCreate
#define xTaskCreateStatic MPU_xTaskCreateStatic
#define xTaskCreateRestricted MPU_xTaskCreateRestricted
#define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions
#define vTaskDelete MPU_vTaskDelete
#define vTaskDelay MPU_vTaskDelay
#define vTaskDelayUntil MPU_vTaskDelayUntil
#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 xTaskNotifyWait MPU_xTaskNotifyWait
#define ulTaskNotifyTake MPU_ulTaskNotifyTake
#define xTaskNotifyStateClear MPU_xTaskNotifyStateClear
#define xTaskCatchUpTicks MPU_xTaskCatchUpTicks
#define pvPortMalloc MPU_pvPortMalloc
#define vPortFree MPU_vPortFree
#define xPortGetFreeHeapSize MPU_xPortGetFreeHeapSize
#define vPortInitialiseBlocks MPU_vPortInitialiseBlocks
#define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle
#define vTaskSetTimeOutState MPU_vTaskSetTimeOutState
#define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut
#define xTaskGetSchedulerState MPU_xTaskGetSchedulerState
#if configQUEUE_REGISTRY_SIZE > 0
#define vQueueAddToRegistry MPU_vQueueAddToRegistry
#define vQueueUnregisterQueue MPU_vQueueUnregisterQueue
/* 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 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
#if( configQUEUE_REGISTRY_SIZE > 0 )
#define vQueueAddToRegistry MPU_vQueueAddToRegistry
#define vQueueUnregisterQueue MPU_vQueueUnregisterQueue
#define pcQueueGetName MPU_pcQueueGetName
#endif
/* Remove the privileged function macro. */
/* 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 xTimerGetPeriod MPU_xTimerGetPeriod
#define xTimerGetExpiryTime MPU_xTimerGetExpiryTime
#define xTimerGenericCommand MPU_xTimerGenericCommand
/* 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
/* 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
/* Remove the privileged function macro, but keep the PRIVILEGED_DATA
macro so applications can place data in privileged access sections
(useful when using statically allocated objects). */
#define PRIVILEGED_FUNCTION
#define PRIVILEGED_DATA __attribute__((section("privileged_data")))
#define FREERTOS_SYSTEM_CALL
#else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
/* Ensure API functions go in the privileged execution section. */
#define PRIVILEGED_FUNCTION __attribute__((section("privileged_functions")))
#define PRIVILEGED_DATA __attribute__((section("privileged_data")))
#define FREERTOS_SYSTEM_CALL __attribute__((section( "freertos_system_calls")))
#endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
@ -148,6 +177,7 @@ only for ports that are using the MPU. */
#define PRIVILEGED_FUNCTION
#define PRIVILEGED_DATA
#define FREERTOS_SYSTEM_CALL
#define portUSING_MPU_WRAPPERS 0
#endif /* portUSING_MPU_WRAPPERS */

View File

@ -1,71 +1,29 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/*-----------------------------------------------------------
* Portable layer API. Each function must be defined for each port.
@ -86,7 +44,6 @@ specific constants has been moved into the deprecated_definitions.h header
file. */
#include "deprecated_definitions.h"
/* If portENTER_CRITICAL is not defined then including deprecated_definitions.h
did not result in a portmacro.h header file being included - and it should be
included here. In this case the path to the correct portmacro.h header file
@ -95,8 +52,16 @@ must be set in the compiler's include path. */
#include "freertos/portmacro.h"
#endif
#if portBYTE_ALIGNMENT == 32
#define portBYTE_ALIGNMENT_MASK ( 0x001f )
#endif
#if portBYTE_ALIGNMENT == 16
#define portBYTE_ALIGNMENT_MASK ( 0x000f )
#endif
#if portBYTE_ALIGNMENT == 8
#define portBYTE_ALIGNMENT_MASK ( 0x0007U )
#define portBYTE_ALIGNMENT_MASK ( 0x0007 )
#endif
#if portBYTE_ALIGNMENT == 4
@ -119,15 +84,19 @@ must be set in the compiler's include path. */
#define portNUM_CONFIGURABLE_REGIONS 1
#endif
#ifndef portHAS_STACK_OVERFLOW_CHECKING
#define portHAS_STACK_OVERFLOW_CHECKING 0
#endif
#ifndef portARCH_NAME
#define portARCH_NAME NULL
#endif
#ifdef __cplusplus
extern "C" {
#endif
#include "mpu_wrappers.h"
#include "esp_system.h"
#include "hal/cpu_hal.h"
#include "xt_instr_macros.h"
/*
* Setup the stack of a new task so it is ready to be placed under the
@ -136,11 +105,70 @@ extern "C" {
*
*/
#if( portUSING_MPU_WRAPPERS == 1 )
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION;
#if( portHAS_STACK_OVERFLOW_CHECKING == 1 )
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION;
#else
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION;
#endif
#else
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION;
#if( portHAS_STACK_OVERFLOW_CHECKING == 1 )
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION;
#else
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION;
#endif
#endif
#ifdef configUSE_FREERTOS_PROVIDED_HEAP
/* Used by heap_5.c to define the start address and size of each memory region
that together comprise the total FreeRTOS heap space. */
typedef struct HeapRegion
{
uint8_t *pucStartAddress;
size_t xSizeInBytes;
} HeapRegion_t;
/* 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. */
} HeapStats_t;
/*
* Used to define multiple heap regions for use by heap_5.c. This function
* must be called before any calls to pvPortMalloc() - not creating a task,
* queue, semaphore, mutex, software timer, event group, etc. will result in
* pvPortMalloc being called.
*
* pxHeapRegions passes in an array of HeapRegion_t structures - each of which
* defines a region of memory that can be used as the heap. The array is
* terminated by a HeapRegions_t structure that has a size of 0. The region
* with the lowest start address must appear first in the array.
*/
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION;
/*
* Returns a HeapStats_t structure filled with information about the current
* heap state.
*/
void vPortGetHeapStats( HeapStats_t *pxHeapStats );
/*
* Map to the memory management routines required for the port.
*/
void *pvPortMalloc( 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;
#else // configUSE_FREERTOS_PROVIDED_HEAP
/*
* Map to the memory management routines required for the port.
*
@ -153,6 +181,8 @@ extern "C" {
#define xPortGetFreeHeapSize esp_get_free_heap_size
#define xPortGetMinimumEverFreeHeapSize esp_get_minimum_free_heap_size
#endif
/*
* Setup the hardware ready for the scheduler to take control. This generally
* sets up a tick interrupt and sets timers for the correct tick frequency.
@ -166,76 +196,9 @@ BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION;
*/
void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
/*
* Send an interrupt to another core in order to make the task running
* on it yield for a higher-priority task.
*/
void vPortYieldOtherCore( BaseType_t coreid) PRIVILEGED_FUNCTION;
/*
Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack
watchpoint around.
*/
void vPortSetStackWatchpoint( void* pxStackStart );
/*
* This function will be called in High prio ISRs. Returns true if the current core was in ISR context
* before calling into high prio ISR context.
*/
BaseType_t xPortInterruptedFromISRContext(void);
/*
* The structures and methods of manipulating the MPU are contained within the
* port layer.
*
* Fills the xMPUSettings structure with the memory region information
* contained in xRegions.
*/
#if( portUSING_MPU_WRAPPERS == 1 )
struct xMEMORY_REGION;
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t usStackDepth ) PRIVILEGED_FUNCTION;
void vPortReleaseTaskMPUSettings( xMPU_SETTINGS *xMPUSettings );
#endif
/* Multi-core: get current core ID */
static inline uint32_t IRAM_ATTR xPortGetCoreID(void) {
return cpu_hal_get_core_id();
}
/* Get tick rate per second */
uint32_t xPortGetTickRateHz(void);
static inline bool IRAM_ATTR xPortCanYield(void)
{
uint32_t ps_reg = 0;
//Get the current value of PS (processor status) register
RSR(PS, ps_reg);
/*
* intlevel = (ps_reg & 0xf);
* excm = (ps_reg >> 4) & 0x1;
* CINTLEVEL is max(excm * EXCMLEVEL, INTLEVEL), where EXCMLEVEL is 3.
* However, just return true, only intlevel is zero.
*/
return ((ps_reg & PS_INTLEVEL_MASK) == 0);
}
#ifdef __cplusplus
}
#endif
static inline void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set)
{
#if defined(CONFIG_ESP32_SPIRAM_SUPPORT)
compare_and_set_extram(addr, compare, set);
#endif
}
#endif /* PORTABLE_H */

View File

@ -1,42 +0,0 @@
/*******************************************************************************
// Copyright (c) 2003-2015 Cadence Design Systems, Inc.
//
// 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.
--------------------------------------------------------------------------------
/*
* This utility helps tracing the entering and exiting from tasks. It maintains a circular buffer
* of tasks in the order they execute, and their execution time.
* In order to enable it, set configUSE_TRACE_FACILITY_2 to 1 in FreeRTOSConfig.h.
* You will also need to download the FreeRTOS_trace patch that contains
* porttrace.c and the complete version of porttrace.h
*/
#ifndef PORTTRACE_H
#define PORTTRACE_H
#if configUSE_TRACE_FACILITY_2
#error "You need to download the FreeRTOS_trace patch that overwrites this file"
#endif
#define porttracePrint(nelements)
#define porttraceStamp(stamp, count_incr)
#endif /* PORTTRACE_H */

View File

@ -1,71 +1,29 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef PROJDEFS_H
#define PROJDEFS_H
@ -76,9 +34,17 @@
*/
typedef void (*TaskFunction_t)( void * );
/* Converts a time in milliseconds to a time in ticks. */
#define pdMS_TO_TICKS( xTimeInMs ) ( ( ( TickType_t ) ( xTimeInMs ) * configTICK_RATE_HZ ) / ( TickType_t ) 1000 )
#define pdTICKS_TO_MS( xTicks ) ( ( uint32_t ) ( xTicks ) * 1000 / configTICK_RATE_HZ )
/* 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 ) 1000 ) )
#endif
#ifndef pdTICKS_TO_MS
#define pdTICKS_TO_MS( xTicks ) ( ( uint32_t ) ( xTicks ) * 1000 / configTICK_RATE_HZ )
#endif
#define pdFALSE ( ( BaseType_t ) 0 )
#define pdTRUE ( ( BaseType_t ) 1 )
@ -88,7 +54,7 @@ typedef void (*TaskFunction_t)( void * );
#define errQUEUE_EMPTY ( ( BaseType_t ) 0 )
#define errQUEUE_FULL ( ( BaseType_t ) 0 )
/* Error definitions. */
/* FreeRTOS error definitions. */
#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 )
#define errQUEUE_BLOCKED ( -4 )
#define errQUEUE_YIELD ( -5 )
@ -104,6 +70,59 @@ typedef void (*TaskFunction_t)( void * );
#define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL
#endif
/* The following errno values are used by FreeRTOS+ components, not FreeRTOS
itself. */
#define pdFREERTOS_ERRNO_NONE 0 /* No errors */
#define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */
#define pdFREERTOS_ERRNO_EINTR 4 /* Interrupted system call */
#define pdFREERTOS_ERRNO_EIO 5 /* I/O error */
#define pdFREERTOS_ERRNO_ENXIO 6 /* No such device or address */
#define pdFREERTOS_ERRNO_EBADF 9 /* Bad file number */
#define pdFREERTOS_ERRNO_EAGAIN 11 /* No more processes */
#define pdFREERTOS_ERRNO_EWOULDBLOCK 11 /* Operation would block */
#define pdFREERTOS_ERRNO_ENOMEM 12 /* Not enough memory */
#define pdFREERTOS_ERRNO_EACCES 13 /* Permission denied */
#define pdFREERTOS_ERRNO_EFAULT 14 /* Bad address */
#define pdFREERTOS_ERRNO_EBUSY 16 /* Mount device busy */
#define pdFREERTOS_ERRNO_EEXIST 17 /* File exists */
#define pdFREERTOS_ERRNO_EXDEV 18 /* Cross-device link */
#define pdFREERTOS_ERRNO_ENODEV 19 /* No such device */
#define pdFREERTOS_ERRNO_ENOTDIR 20 /* Not a directory */
#define pdFREERTOS_ERRNO_EISDIR 21 /* Is a directory */
#define pdFREERTOS_ERRNO_EINVAL 22 /* Invalid argument */
#define pdFREERTOS_ERRNO_ENOSPC 28 /* No space left on device */
#define pdFREERTOS_ERRNO_ESPIPE 29 /* Illegal seek */
#define pdFREERTOS_ERRNO_EROFS 30 /* Read only file system */
#define pdFREERTOS_ERRNO_EUNATCH 42 /* Protocol driver not attached */
#define pdFREERTOS_ERRNO_EBADE 50 /* Invalid exchange */
#define pdFREERTOS_ERRNO_EFTYPE 79 /* Inappropriate file type or format */
#define pdFREERTOS_ERRNO_ENMFILE 89 /* No more files */
#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_ENOBUFS 105 /* No buffer space available */
#define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */
#define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */
#define pdFREERTOS_ERRNO_ETIMEDOUT 116 /* Connection timed out */
#define pdFREERTOS_ERRNO_EINPROGRESS 119 /* Connection already in progress */
#define pdFREERTOS_ERRNO_EALREADY 120 /* Socket already connected */
#define pdFREERTOS_ERRNO_EADDRNOTAVAIL 125 /* Address not available */
#define pdFREERTOS_ERRNO_EISCONN 127 /* Socket is already connected */
#define pdFREERTOS_ERRNO_ENOTCONN 128 /* Socket is not connected */
#define pdFREERTOS_ERRNO_ENOMEDIUM 135 /* No medium inserted */
#define pdFREERTOS_ERRNO_EILSEQ 138 /* An invalid UTF-16 sequence was encountered. */
#define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */
/* The following endian values are used by FreeRTOS+ components, not FreeRTOS
itself. */
#define pdFREERTOS_LITTLE_ENDIAN 0
#define pdFREERTOS_BIG_ENDIAN 1
/* Re-defining endian values for generic naming. */
#define pdLITTLE_ENDIAN pdFREERTOS_LITTLE_ENDIAN
#define pdBIG_ENDIAN pdFREERTOS_BIG_ENDIAN
#endif /* PROJDEFS_H */

View File

@ -1,71 +1,29 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef QUEUE_H
@ -79,29 +37,32 @@
extern "C" {
#endif
#include "task.h"
/**
* Type by which queues are referenced. For example, a call to xQueueCreate()
* returns an QueueHandle_t variable that can then be used as a parameter to
* xQueueSend(), xQueueReceive(), etc.
*/
typedef void * QueueHandle_t;
struct QueueDefinition; /* Using old naming convention so as not to break kernel aware debuggers. */
typedef struct QueueDefinition * QueueHandle_t;
/**
* Type by which queue sets are referenced. For example, a call to
* xQueueCreateSet() returns an xQueueSet variable that can then be used as a
* parameter to xQueueSelectFromSet(), xQueueAddToSet(), etc.
*/
typedef void * QueueSetHandle_t;
typedef struct QueueDefinition * QueueSetHandle_t;
/**
* Queue sets can contain both queues and semaphores, so the
* QueueSetMemberHandle_t is defined as a type to be used where a parameter or
* return value can be either an QueueHandle_t or an SemaphoreHandle_t.
*/
typedef void * QueueSetMemberHandle_t;
typedef struct QueueDefinition * QueueSetMemberHandle_t;
/** @cond */
/* For internal use only. */
#define queueSEND_TO_BACK ( ( BaseType_t ) 0 )
#define queueSEND_TO_FRONT ( ( BaseType_t ) 1 )
@ -244,8 +205,6 @@ typedef void * QueueSetMemberHandle_t;
#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* This is a macro that calls xQueueGenericSend().
*
* 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
* routine. See xQueueSendFromISR () for an alternative which may be used
@ -613,8 +572,6 @@ typedef void * QueueSetMemberHandle_t;
BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION;
/**
* This is a macro that calls the xQueueGenericReceive() function.
*
* 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
* provided. The number of bytes copied into the buffer was defined when
@ -697,7 +654,7 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQ
* @endcode
* \ingroup QueueManagement
*/
#define xQueuePeek( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE )
BaseType_t xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/**
* A version of xQueuePeek() that can be called from an interrupt service
@ -725,16 +682,6 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQ
BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION;
/**
* queue. h
* <pre>
BaseType_t xQueueReceive(
QueueHandle_t xQueue,
void *pvBuffer,
TickType_t xTicksToWait
);</pre>
*
* This is a macro that calls the xQueueGenericReceive() function.
*
* 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
* was defined when the queue was created.
@ -814,96 +761,7 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) PRIV
* @endcode
* \ingroup QueueManagement
*/
#define xQueueReceive( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE )
/**
* It is preferred that the macro xQueueReceive() be used rather than calling
* this function directly.
*
* 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
* was defined when the queue was created.
*
* This function must not be used in an interrupt service routine. See
* xQueueReceiveFromISR for an alternative that can.
*
* @param xQueue The handle to the queue from which the item is to be
* received.
*
* @param pvBuffer Pointer to the buffer into which the received item will
* be copied.
*
* @param xTicksToWait The maximum amount of time the task should block
* waiting for an item to receive should the queue be empty at the time
* of the call. The time is defined in tick periods so the constant
* portTICK_PERIOD_MS should be used to convert to real time if this is required.
* xQueueGenericReceive() will return immediately if the queue is empty and
* xTicksToWait is 0.
*
* @param xJustPeek When set to true, the item received from the queue is not
* actually removed from the queue - meaning a subsequent call to
* xQueueReceive() will return the same item. When set to false, the item
* being received from the queue is also removed from the queue.
*
* @return pdTRUE if an item was successfully received from the queue,
* otherwise pdFALSE.
*
* Example usage:
* @code{c}
* struct AMessage
* {
* char ucMessageID;
* char ucData[ 20 ];
* } xMessage;
*
* QueueHandle_t xQueue;
*
* // Task to create a queue and post a value.
* void vATask( void *pvParameters )
* {
* struct AMessage *pxMessage;
*
* // Create a queue capable of containing 10 pointers to AMessage structures.
* // These should be passed by pointer as they contain a lot of data.
* xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
* if( xQueue == 0 )
* {
* // Failed to create the queue.
* }
*
* // ...
*
* // Send a pointer to a struct AMessage object. Don't block if the
* // queue is already full.
* pxMessage = & xMessage;
* xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
*
* // ... Rest of task code.
* }
*
* // Task to receive from the queue.
* void vADifferentTask( void *pvParameters )
* {
* struct AMessage *pxRxedMessage;
*
* if( xQueue != 0 )
* {
* // Receive a message on the created queue. Block for 10 ticks if a
* // message is not immediately available.
* if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
* {
* // pcRxedMessage now points to the struct AMessage variable posted
* // by vATask.
* }
* }
*
* // ... Rest of task code.
* }
* @endcode
* \ingroup QueueManagement
*/
BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek ) PRIVILEGED_FUNCTION;
BaseType_t xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/**
* Return the number of messages stored in a queue.
@ -999,7 +857,7 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
#define xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT )
/**
/**
* This is a macro that calls xQueueGenericSendFromISR().
*
* Post an item to the back of a queue. It is safe to use this macro from
@ -1346,39 +1204,16 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherP
*/
BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
/**@{*/
/**
/*
* 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.
*/
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;
/**@}*/
/** @cond */
/**
* xQueueAltGenericSend() is an alternative version of xQueueGenericSend().
* Likewise xQueueAltGenericReceive() is an alternative version of
* xQueueGenericReceive().
*
* The source code that implements the alternative (Alt) API is much
* simpler because it executes everything from within a critical section.
* This is the approach taken by many other RTOSes, but FreeRTOS.org has the
* preferred fully featured API too. The fully featured API has more
* complex code that takes longer to execute, but makes much less use of
* critical sections. Therefore the alternative API sacrifices interrupt
* responsiveness to gain execution speed, whereas the fully featured API
* sacrifices execution speed to ensure better interrupt responsiveness.
*/
BaseType_t xQueueAltGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition );
BaseType_t xQueueAltGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking );
#define xQueueAltSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT )
#define xQueueAltSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
#define xQueueAltReceive( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE )
#define xQueueAltPeek( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE )
/*
* The functions defined above are for passing data to and from tasks. The
* functions below are the equivalents for passing data to and from
* co-routines.
@ -1392,7 +1227,7 @@ BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseTyp
BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait );
BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait );
/*
/**
* For internal use only. Use xSemaphoreCreateMutex(),
* xSemaphoreCreateCounting() or xSemaphoreGetMutexHolder() instead of calling
* these functions directly.
@ -1401,24 +1236,22 @@ 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;
void* xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION;
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;
/*
/**
* For internal use only. Use xSemaphoreTakeMutexRecursive() or
* xSemaphoreGiveMutexRecursive() instead of calling these functions directly.
*/
BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) PRIVILEGED_FUNCTION;
BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION;
/** @endcond */
/**
* Reset a queue back to its original empty state. pdPASS is returned if the
* queue is successfully reset. pdFAIL is returned if the queue could not be
* reset because there are tasks blocked on the queue waiting to either
* receive from the queue or send to the queue.
*
* @param xQueue The queue to reset
* @return always returns pdPASS
* 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 )
@ -1439,13 +1272,13 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) PRIVILEGED_FUNCTION
* 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 *pcName ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
#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. */
#endif
/**
@ -1458,13 +1291,11 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) PRIVILEGED_FUNCTION
*
* @param xQueue The handle of the queue being removed from the registry.
*/
#if configQUEUE_REGISTRY_SIZE > 0
#if( configQUEUE_REGISTRY_SIZE > 0 )
void vQueueUnregisterQueue( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
#endif
/**
* @note This function has been back ported from FreeRTOS v9.0.0
*
* The queue registry is provided as a means for kernel aware debuggers to
* locate queues, semaphores and mutexes. Call pcQueueGetName() to look
* up and return the name of a queue in the queue registry from the queue's
@ -1476,7 +1307,7 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) 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; /**lint !e971 Unqualified char types are allowed for strings and single characters only. */
#endif
/**
@ -1632,12 +1463,14 @@ QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const Ti
QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION;
/** @cond */
/* Not public API functions. */
void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait, 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;
/** @endcond */
#ifdef __cplusplus

View File

@ -1,71 +1,29 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef SEMAPHORE_H
#define SEMAPHORE_H
@ -84,6 +42,13 @@ typedef QueueHandle_t SemaphoreHandle_t;
/** @cond */
/**
* semphr. h
* <pre>vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )</pre>
*
* In many usage scenarios it is faster and more memory efficient to use a
* direct to task notification in place of a binary semaphore!
* http://www.freertos.org/RTOS-task-notifications.html
*
* This old vSemaphoreCreateBinary() macro is now deprecated in favour of the
* xSemaphoreCreateBinary() function. Note that binary semaphores created using
* the vSemaphoreCreateBinary() macro are created in a state such that the
@ -160,11 +125,6 @@ typedef QueueHandle_t SemaphoreHandle_t;
* created using xSemaphoreCreateBinary() are created in a state such that the
* the semaphore must first be 'given' before it can be 'taken'.
*
* Function that creates a semaphore by using the existing queue mechanism.
* The queue length is 1 as this is a binary semaphore. The data size is 0
* as nothing is actually stored - all that is important is whether the queue is
* empty or full (the binary semaphore is available or not).
*
* This type of semaphore can be used for pure synchronisation between tasks or
* between an interrupt and a task. The semaphore need not be given back once
* obtained, so one task/interrupt can continuously 'give' the semaphore while
@ -172,7 +132,8 @@ typedef QueueHandle_t SemaphoreHandle_t;
* semaphore does not use a priority inheritance mechanism. For an alternative
* that does use priority inheritance see xSemaphoreCreateMutex().
*
* @return Handle to the created semaphore.
* @return Handle to the created semaphore, or NULL if the memory required to
* hold the semaphore's data structures could not be allocated.
*
* Example usage:
* @code{c}
@ -255,7 +216,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
/**
* <i>Macro</i> to obtain a semaphore. The semaphore must have previously been
* created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or
* created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or
* xSemaphoreCreateCounting().
*
* @param xSemaphore A handle to the semaphore being taken - obtained when
@ -311,7 +272,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
* @endcode
* \ingroup Semaphores
*/
#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE )
#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueSemaphoreTake( ( xSemaphore ), ( xBlockTime ) )
/**
* <i>Macro</i> to recursively obtain, or 'take', a mutex type semaphore.
@ -417,7 +378,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
/**
* <i>Macro</i> to release a semaphore. The semaphore must have previously been
* created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or
* created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or
* xSemaphoreCreateCounting(). and obtained using sSemaphoreTake().
*
* This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for
@ -475,6 +436,9 @@ typedef QueueHandle_t SemaphoreHandle_t;
#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
/**
* semphr. h
* <pre>xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex )</pre>
*
* <i>Macro</i> to recursively release, or 'give', a mutex type semaphore.
* The mutex must have previously been created using a call to
* xSemaphoreCreateRecursiveMutex();
@ -573,7 +537,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
/**
* <i>Macro</i> to release a semaphore. The semaphore must have previously been
* created with a call to vSemaphoreCreateBinary() or xSemaphoreCreateCounting().
* created with a call to xSemaphoreCreateBinary() or xSemaphoreCreateCounting().
*
* Mutex type semaphores (those created using a call to xSemaphoreCreateMutex())
* must not be used with this macro.
@ -583,7 +547,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
* @param xSemaphore A handle to the semaphore being released. This is the
* handle returned when the semaphore was created.
*
* @param[out] pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set
* @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set
* *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task
* to unblock, and the unblocked task has a priority higher than the currently
* running task. If xSemaphoreGiveFromISR() sets this value to pdTRUE then
@ -656,7 +620,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
/**
* <i>Macro</i> to take a semaphore from an ISR. The semaphore must have
* previously been created with a call to vSemaphoreCreateBinary() or
* previously been created with a call to xSemaphoreCreateBinary() or
* xSemaphoreCreateCounting().
*
* Mutex type semaphores (those created using a call to xSemaphoreCreateMutex())
@ -704,7 +668,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
*
* Mutex type semaphores cannot be used from within interrupt service routines.
*
* See vSemaphoreCreateBinary() for an alternative implementation that can be
* See xSemaphoreCreateBinary() for an alternative implementation that can be
* used for pure synchronisation (where one task or interrupt always 'gives' the
* semaphore and another always 'takes' the semaphore) and from within interrupt
* service routines.
@ -1106,6 +1070,18 @@ typedef QueueHandle_t SemaphoreHandle_t;
#define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) )
/**
*
* 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 ) )
/**
* semphr.h
* <pre>UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore );</pre>
*
* If the semaphore is a counting semaphore then uxSemaphoreGetCount() returns
* its current count value. If the semaphore is a binary semaphore then
* uxSemaphoreGetCount() returns 1 if the semaphore is available, and 0 if the

View File

@ -1,71 +1,29 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef STACK_MACROS_H
#define STACK_MACROS_H
@ -178,7 +136,6 @@
}
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
/*-----------------------------------------------------------*/
#endif /* STACK_MACROS_H */

View File

@ -0,0 +1,745 @@
/*
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/*
* Stream buffers are used to send a continuous stream of data from one task or
* interrupt to another. Their implementation is light weight, making them
* particularly suited for interrupt to task and core to core communication
* scenarios.
*
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
* implementation (so also the message buffer implementation, as message buffers
* are built on top of stream buffers) assumes there is only one task or
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader). It is safe for the
* writer and reader to be different tasks or interrupts, but, unlike other
* FreeRTOS objects, it is not safe to have multiple different writers or
* multiple different readers. If there are to be multiple different writers
* then the application writer must place each call to a writing API function
* (such as xStreamBufferSend()) inside a critical section and set the send
* block time to 0. Likewise, if there are to be multiple different readers
* then the application writer must place each call to a reading API function
* (such as xStreamBufferRead()) inside a critical section section and set the
* receive block time to 0.
*
*/
#ifndef STREAM_BUFFER_H
#define STREAM_BUFFER_H
#ifndef INC_FREERTOS_H
#error "include FreeRTOS.h must appear in source files before include stream_buffer.h"
#endif
#if defined( __cplusplus )
extern "C" {
#endif
/**
* Type by which stream buffers are referenced. For example, a call to
* xStreamBufferCreate() returns an StreamBufferHandle_t variable that can
* then be used as a parameter to xStreamBufferSend(), xStreamBufferReceive(),
* etc.
*/
struct StreamBufferDef_t;
typedef struct StreamBufferDef_t * StreamBufferHandle_t;
/**
* Creates a new stream buffer using dynamically allocated memory. See
* xStreamBufferCreateStatic() for a version that uses statically allocated
* memory (memory that is allocated at compile time).
*
* configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 or left undefined in
* FreeRTOSConfig.h for xStreamBufferCreate() to be available.
*
* @param xBufferSizeBytes The total number of bytes the stream buffer will be
* able to hold at any one time.
*
* @param xTriggerLevelBytes The number of bytes that must be in the stream
* buffer before a task that is blocked on the stream buffer to wait for data is
* moved out of the blocked state. For example, if a task is blocked on a read
* of an empty stream buffer that has a trigger level of 1 then the task will be
* unblocked when a single byte is written to the buffer or the task's block
* time expires. As another example, if a task is blocked on a read of an empty
* stream buffer that has a trigger level of 10 then the task will not be
* unblocked until the stream buffer contains at least 10 bytes or the task's
* block time expires. If a reading task's block time expires before the
* trigger level is reached then the task will still receive however many bytes
* are actually available. Setting a trigger level of 0 will result in a
* trigger level of 1 being used. It is not valid to specify a trigger level
* that is greater than the buffer size.
*
* @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
* returned indicates that the stream buffer has been created successfully -
* the returned value should be stored as the handle to the created stream
* buffer.
*
* Example use:
* @code{c}
*
* void vAFunction( void )
* {
* StreamBufferHandle_t xStreamBuffer;
* const size_t xStreamBufferSizeBytes = 100, xTriggerLevel = 10;
*
* // Create a stream buffer that can hold 100 bytes. The memory used to hold
* // both the stream buffer structure and the data in the stream buffer is
* // allocated dynamically.
* xStreamBuffer = xStreamBufferCreate( xStreamBufferSizeBytes, xTriggerLevel );
*
* if( xStreamBuffer == NULL )
* {
* // There was not enough heap memory space available to create the
* // stream buffer.
* }
* else
* {
* // The stream buffer was created successfully and can now be used.
* }
* }
* @endcode
* \ingroup StreamBufferManagement
*/
#define xStreamBufferCreate( xBufferSizeBytes, xTriggerLevelBytes ) xStreamBufferGenericCreate( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE )
/**
* Creates a new stream buffer using statically allocated memory. See
* xStreamBufferCreate() for a version that uses dynamically allocated memory.
*
* configSUPPORT_STATIC_ALLOCATION must be set to 1 in FreeRTOSConfig.h for
* xStreamBufferCreateStatic() to be available.
*
* @param xBufferSizeBytes The size, in bytes, of the buffer pointed to by the
* pucStreamBufferStorageArea parameter.
*
* @param xTriggerLevelBytes The number of bytes that must be in the stream
* buffer before a task that is blocked on the stream buffer to wait for data is
* moved out of the blocked state. For example, if a task is blocked on a read
* of an empty stream buffer that has a trigger level of 1 then the task will be
* unblocked when a single byte is written to the buffer or the task's block
* time expires. As another example, if a task is blocked on a read of an empty
* stream buffer that has a trigger level of 10 then the task will not be
* unblocked until the stream buffer contains at least 10 bytes or the task's
* block time expires. If a reading task's block time expires before the
* trigger level is reached then the task will still receive however many bytes
* are actually available. Setting a trigger level of 0 will result in a
* trigger level of 1 being used. It is not valid to specify a trigger level
* 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
* 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.
*
* @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.
* #define STORAGE_SIZE_BYTES 1000
*
* // Defines the memory that will actually hold the streams within the stream
* // buffer.
* static uint8_t ucStorageBuffer[ STORAGE_SIZE_BYTES ];
*
* // The variable used to hold the stream buffer structure.
* StaticStreamBuffer_t xStreamBufferStruct;
*
* void MyFunction( void )
* {
* StreamBufferHandle_t xStreamBuffer;
* const size_t xTriggerLevel = 1;
*
* xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucBufferStorage ),
* xTriggerLevel,
* ucBufferStorage,
* &xStreamBufferStruct );
*
* // As neither the pucStreamBufferStorageArea or pxStaticStreamBuffer
* // parameters were NULL, xStreamBuffer will not be NULL, and can be used to
* // reference the created stream buffer in other stream buffer API calls.
*
* // Other code that uses the stream buffer can go here.
* }
*
* @endcode
* \ingroup StreamBufferManagement
*/
#define xStreamBufferCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE, pucStreamBufferStorageArea, pxStaticStreamBuffer )
/**
* Sends bytes to a stream buffer. The bytes are copied into the stream buffer.
*
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
* implementation (so also the message buffer implementation, as message buffers
* are built on top of stream buffers) assumes there is only one task or
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader). It is safe for the
* writer and reader to be different tasks or interrupts, but, unlike other
* FreeRTOS objects, it is not safe to have multiple different writers or
* multiple different readers. If there are to be multiple different writers
* then the application writer must place each call to a writing API function
* (such as xStreamBufferSend()) inside a critical section and set the send
* block time to 0. Likewise, if there are to be multiple different readers
* then the application writer must place each call to a reading API function
* (such as xStreamBufferRead()) inside a critical section and set the receive
* block time to 0.
*
* Use xStreamBufferSend() to write to a stream buffer from a task. Use
* xStreamBufferSendFromISR() to write to a stream buffer from an interrupt
* service routine (ISR).
*
* @param xStreamBuffer The handle of the stream buffer to which a stream is
* being sent.
*
* @param pvTxData A pointer to the buffer that holds the bytes to be copied
* into the stream buffer.
*
* @param xDataLengthBytes The maximum number of bytes to copy from pvTxData
* into the stream buffer.
*
* @param xTicksToWait The maximum amount of time the task should remain in the
* Blocked state to wait for enough space to become available in the stream
* buffer, should the stream buffer contain too little space to hold the
* another xDataLengthBytes bytes. The block time is specified in tick periods,
* so the absolute time it represents is dependent on the tick frequency. The
* macro pdMS_TO_TICKS() can be used to convert a time specified in milliseconds
* into a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will
* cause the task to wait indefinitely (without timing out), provided
* INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. If a task times out
* before it can write all xDataLengthBytes into the buffer it will still write
* as many bytes as possible. A task does not use any CPU time when it is in
* the blocked state.
*
* @return The number of bytes written to the stream buffer. If a task times
* out before it can write all xDataLengthBytes into the buffer it will still
* write as many bytes as possible.
*
* Example use:
* @code{c}
* void vAFunction( StreamBufferHandle_t xStreamBuffer )
* {
* size_t xBytesSent;
* uint8_t ucArrayToSend[] = { 0, 1, 2, 3 };
* char *pcStringToSend = "String to send";
* const TickType_t x100ms = pdMS_TO_TICKS( 100 );
*
* // Send an array to the stream buffer, blocking for a maximum of 100ms to
* // wait for enough space to be available in the stream buffer.
* xBytesSent = xStreamBufferSend( xStreamBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms );
*
* if( xBytesSent != sizeof( ucArrayToSend ) )
* {
* // The call to xStreamBufferSend() times out before there was enough
* // space in the buffer for the data to be written, but it did
* // successfully write xBytesSent bytes.
* }
*
* // Send the string to the stream buffer. Return immediately if there is not
* // enough space in the buffer.
* xBytesSent = xStreamBufferSend( xStreamBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 );
*
* if( xBytesSent != strlen( pcStringToSend ) )
* {
* // The entire string could not be added to the stream buffer because
* // there was not enough free space in the buffer, but xBytesSent bytes
* // were sent. Could try again to send the remaining bytes.
* }
* }
* @endcode
* \ingroup StreamBufferManagement
*/
size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
const void *pvTxData,
size_t xDataLengthBytes,
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/**
* Interrupt safe version of the API function that sends a stream of bytes to
* the stream buffer.
*
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
* implementation (so also the message buffer implementation, as message buffers
* are built on top of stream buffers) assumes there is only one task or
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader). It is safe for the
* writer and reader to be different tasks or interrupts, but, unlike other
* FreeRTOS objects, it is not safe to have multiple different writers or
* multiple different readers. If there are to be multiple different writers
* then the application writer must place each call to a writing API function
* (such as xStreamBufferSend()) inside a critical section and set the send
* block time to 0. Likewise, if there are to be multiple different readers
* then the application writer must place each call to a reading API function
* (such as xStreamBufferRead()) inside a critical section and set the receive
* block time to 0.
*
* Use xStreamBufferSend() to write to a stream buffer from a task. Use
* xStreamBufferSendFromISR() to write to a stream buffer from an interrupt
* service routine (ISR).
*
* @param xStreamBuffer The handle of the stream buffer to which a stream is
* being sent.
*
* @param pvTxData A pointer to the data that is to be copied into the stream
* buffer.
*
* @param xDataLengthBytes The maximum number of bytes to copy from pvTxData
* into the stream buffer.
*
* @param pxHigherPriorityTaskWoken It is possible that a stream buffer will
* have a task blocked on it waiting for data. Calling
* xStreamBufferSendFromISR() can make data available, and so cause a task that
* was waiting for data to leave the Blocked state. If calling
* xStreamBufferSendFromISR() causes a task to leave the Blocked state, and the
* unblocked task has a priority higher than the currently executing task (the
* task that was interrupted), then, internally, xStreamBufferSendFromISR()
* will set *pxHigherPriorityTaskWoken to pdTRUE. If
* xStreamBufferSendFromISR() sets this value to pdTRUE, then normally a
* context switch should be performed before the interrupt is exited. This will
* ensure that the interrupt returns directly to the highest priority Ready
* state task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it
* is passed into the function. See the example code below for an example.
*
* @return The number of bytes actually written to the stream buffer, which will
* be less than xDataLengthBytes if the stream buffer didn't have enough free
* space for all the bytes to be written.
*
* Example use:
* @code{c}
* //A stream buffer that has already been created.
* StreamBufferHandle_t xStreamBuffer;
*
* void vAnInterruptServiceRoutine( void )
* {
* size_t xBytesSent;
* char *pcStringToSend = "String to send";
* BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
*
* // Attempt to send the string to the stream buffer.
* xBytesSent = xStreamBufferSendFromISR( xStreamBuffer,
* ( void * ) pcStringToSend,
* strlen( pcStringToSend ),
* &xHigherPriorityTaskWoken );
*
* if( xBytesSent != strlen( pcStringToSend ) )
* {
* // There was not enough free space in the stream buffer for the entire
* // string to be written, ut xBytesSent bytes were written.
* }
*
* // If xHigherPriorityTaskWoken was set to pdTRUE inside
* // xStreamBufferSendFromISR() then a task that has a priority above the
* // 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
* // 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 );
* }
* @endcode
* \ingroup StreamBufferManagement
*/
size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
const void *pvTxData,
size_t xDataLengthBytes,
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
/**
* Receives bytes from a stream buffer.
*
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
* implementation (so also the message buffer implementation, as message buffers
* are built on top of stream buffers) assumes there is only one task or
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader). It is safe for the
* writer and reader to be different tasks or interrupts, but, unlike other
* FreeRTOS objects, it is not safe to have multiple different writers or
* multiple different readers. If there are to be multiple different writers
* then the application writer must place each call to a writing API function
* (such as xStreamBufferSend()) inside a critical section and set the send
* block time to 0. Likewise, if there are to be multiple different readers
* then the application writer must place each call to a reading API function
* (such as xStreamBufferRead()) inside a critical section and set the receive
* block time to 0.
*
* Use xStreamBufferReceive() to read from a stream buffer from a task. Use
* xStreamBufferReceiveFromISR() to read from a stream buffer from an
* interrupt service routine (ISR).
*
* @param xStreamBuffer The handle of the stream buffer from which bytes are to
* be received.
*
* @param pvRxData A pointer to the buffer into which the received bytes will be
* copied.
*
* @param xBufferLengthBytes The length of the buffer pointed to by the
* pvRxData parameter. This sets the maximum number of bytes to receive in one
* call. xStreamBufferReceive will return as many bytes as possible up to a
* maximum set by xBufferLengthBytes.
*
* @param xTicksToWait The maximum amount of time the task should remain in the
* Blocked state to wait for data to become available if the stream buffer is
* empty. xStreamBufferReceive() will return immediately if xTicksToWait is
* zero. The block time is specified in tick periods, so the absolute time it
* represents is dependent on the tick frequency. The macro pdMS_TO_TICKS() can
* be used to convert a time specified in milliseconds into a time specified in
* ticks. Setting xTicksToWait to portMAX_DELAY will cause the task to wait
* indefinitely (without timing out), provided INCLUDE_vTaskSuspend is set to 1
* in FreeRTOSConfig.h. A task does not use any CPU time when it is in the
* Blocked state.
*
* @return The number of bytes actually read from the stream buffer, which will
* be less than xBufferLengthBytes if the call to xStreamBufferReceive() timed
* out before xBufferLengthBytes were available.
*
* Example use:
* @code{c}
* void vAFunction( StreamBuffer_t xStreamBuffer )
* {
* uint8_t ucRxData[ 20 ];
* size_t xReceivedBytes;
* const TickType_t xBlockTime = pdMS_TO_TICKS( 20 );
*
* // Receive up to another sizeof( ucRxData ) bytes from the stream buffer.
* // Wait in the Blocked state (so not using any CPU processing time) for a
* // maximum of 100ms for the full sizeof( ucRxData ) number of bytes to be
* // available.
* xReceivedBytes = xStreamBufferReceive( xStreamBuffer,
* ( void * ) ucRxData,
* sizeof( ucRxData ),
* xBlockTime );
*
* if( xReceivedBytes > 0 )
* {
* // A ucRxData contains another xRecievedBytes bytes of data, which can
* // be processed here....
* }
* }
* @endcode
* \ingroup StreamBufferManagement
*/
size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
void *pvRxData,
size_t xBufferLengthBytes,
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/**
* An interrupt safe version of the API function that receives bytes from a
* stream buffer.
*
* Use xStreamBufferReceive() to read bytes from a stream buffer from a task.
* Use xStreamBufferReceiveFromISR() to read bytes from a stream buffer from an
* interrupt service routine (ISR).
*
* @param xStreamBuffer The handle of the stream buffer from which a stream
* is being received.
*
* @param pvRxData A pointer to the buffer into which the received bytes are
* copied.
*
* @param xBufferLengthBytes The length of the buffer pointed to by the
* pvRxData parameter. This sets the maximum number of bytes to receive in one
* call. xStreamBufferReceive will return as many bytes as possible up to a
* maximum set by xBufferLengthBytes.
*
* @param pxHigherPriorityTaskWoken It is possible that a stream buffer will
* have a task blocked on it waiting for space to become available. Calling
* xStreamBufferReceiveFromISR() can make space available, and so cause a task
* that is waiting for space to leave the Blocked state. If calling
* xStreamBufferReceiveFromISR() causes a task to leave the Blocked state, and
* the unblocked task has a priority higher than the currently executing task
* (the task that was interrupted), then, internally,
* xStreamBufferReceiveFromISR() will set *pxHigherPriorityTaskWoken to pdTRUE.
* If xStreamBufferReceiveFromISR() sets this value to pdTRUE, then normally a
* context switch should be performed before the interrupt is exited. That will
* ensure the interrupt returns directly to the highest priority Ready state
* task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it is
* passed into the function. See the code example below for an example.
*
* @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;
*
* void vAnInterruptServiceRoutine( void )
* {
* uint8_t ucRxData[ 20 ];
* size_t xReceivedBytes;
* BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
*
* // Receive the next stream from the stream buffer.
* xReceivedBytes = xStreamBufferReceiveFromISR( xStreamBuffer,
* ( void * ) ucRxData,
* sizeof( ucRxData ),
* &xHigherPriorityTaskWoken );
*
* if( xReceivedBytes > 0 )
* {
* // ucRxData contains xReceivedBytes read from the stream buffer.
* // Process the stream here....
* }
*
* // If xHigherPriorityTaskWoken was set to pdTRUE inside
* // xStreamBufferReceiveFromISR() then a task that has a priority above the
* // 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
* // 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 );
* }
* @endcode
* \ingroup StreamBufferManagement
*/
size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
void *pvRxData,
size_t xBufferLengthBytes,
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
/**
* Deletes a stream buffer that was previously created using a call to
* xStreamBufferCreate() or xStreamBufferCreateStatic(). If the stream
* buffer was created using dynamic memory (that is, by xStreamBufferCreate()),
* then the allocated memory is freed.
*
* A stream buffer handle must not be used after the stream buffer has been
* deleted.
*
* @param xStreamBuffer The handle of the stream buffer to be deleted.
*
* \ingroup StreamBufferManagement
*/
void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/**
* 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.
*
* @param xStreamBuffer The handle of the stream buffer being queried.
*
* @return If the stream buffer is full then pdTRUE is returned. Otherwise
* pdFALSE is returned.
*
* \ingroup StreamBufferManagement
*/
BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/**
* Queries a stream buffer to see if it is empty. A stream buffer is empty if
* it does not contain any data.
*
* @param xStreamBuffer The handle of the stream buffer being queried.
*
* @return If the stream buffer is empty then pdTRUE is returned. Otherwise
* pdFALSE is returned.
*
* \ingroup StreamBufferManagement
*/
BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/**
* 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
* are no tasks blocked waiting to either send to or receive from the stream
* buffer.
*
* @param xStreamBuffer The handle of the stream buffer being reset.
*
* @return If the stream buffer is reset then pdPASS is returned. If there was
* a task blocked waiting to send to or read from the stream buffer then the
* stream buffer is not reset and pdFAIL is returned.
*
* \ingroup StreamBufferManagement
*/
BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/**
* 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
* is full.
*
* @param xStreamBuffer The handle of the stream buffer being queried.
*
* @return The number of bytes that can be written to the stream buffer before
* the stream buffer would be full.
*
* \defgroup xStreamBufferSpacesAvailable xStreamBufferSpacesAvailable
* \ingroup StreamBufferManagement
*/
size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/**
* 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
* buffer would be empty.
*
* @param xStreamBuffer The handle of the stream buffer being queried.
*
* @return The number of bytes that can be read from the stream buffer before
* the stream buffer would be empty.
*
* \defgroup xStreamBufferBytesAvailable xStreamBufferBytesAvailable
* \ingroup StreamBufferManagement
*/
size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/**
* 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
* wait for data is moved out of the blocked state. For example, if a task is
* blocked on a read of an empty stream buffer that has a trigger level of 1
* then the task will be unblocked when a single byte is written to the buffer
* or the task's block time expires. As another example, if a task is blocked
* on a read of an empty stream buffer that has a trigger level of 10 then the
* task will not be unblocked until the stream buffer contains at least 10 bytes
* or the task's block time expires. If a reading task's block time expires
* before the trigger level is reached then the task will still receive however
* many bytes are actually available. Setting a trigger level of 0 will result
* in a trigger level of 1 being used. It is not valid to specify a trigger
* level that is greater than the buffer size.
*
* A trigger level is set when the stream buffer is created, and can be modified
* using xStreamBufferSetTriggerLevel().
*
* @param xStreamBuffer The handle of the stream buffer being updated.
*
* @param xTriggerLevel The new trigger level for the stream buffer.
*
* @return If xTriggerLevel was less than or equal to the stream buffer's length
* then the trigger level will be updated and pdTRUE is returned. Otherwise
* pdFALSE is returned.
*
* \ingroup StreamBufferManagement
*/
BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel ) PRIVILEGED_FUNCTION;
/**
* For advanced users only.
*
* The sbSEND_COMPLETED() macro is called from within the FreeRTOS APIs when
* data is sent to a message buffer or stream buffer. If there was a task that
* was blocked on the message or stream buffer waiting for data to arrive then
* the sbSEND_COMPLETED() macro sends a notification to the task to remove it
* from the Blocked state. xStreamBufferSendCompletedFromISR() does the same
* thing. It is provided to enable application writers to implement their own
* version of sbSEND_COMPLETED(), and MUST NOT BE USED AT ANY OTHER TIME.
*
* 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
* written.
*
* @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
* initialised to pdFALSE before it is passed into
* xStreamBufferSendCompletedFromISR(). If calling
* xStreamBufferSendCompletedFromISR() removes a task from the Blocked state,
* and the task has a priority above the priority of the currently running task,
* then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
* context switch should be performed before exiting the ISR.
*
* @return If a task was removed from the Blocked state then pdTRUE is returned.
* Otherwise pdFALSE is returned.
*
* \ingroup StreamBufferManagement
*/
BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
/**
* For advanced users only.
*
* The sbRECEIVE_COMPLETED() macro is called from within the FreeRTOS APIs when
* data is read out of a message buffer or stream buffer. If there was a task
* that was blocked on the message or stream buffer waiting for data to arrive
* then the sbRECEIVE_COMPLETED() macro sends a notification to the task to
* remove it from the Blocked state. xStreamBufferReceiveCompletedFromISR()
* does the same thing. It is provided to enable application writers to
* implement their own version of sbRECEIVE_COMPLETED(), and MUST NOT BE USED AT
* ANY OTHER TIME.
*
* 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
* read.
*
* @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
* initialised to pdFALSE before it is passed into
* xStreamBufferReceiveCompletedFromISR(). If calling
* xStreamBufferReceiveCompletedFromISR() removes a task from the Blocked state,
* and the task has a priority above the priority of the currently running task,
* then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
* context switch should be performed before exiting the ISR.
*
* @return If a task was removed from the Blocked state then pdTRUE is returned.
* Otherwise pdFALSE is returned.
*
* \ingroup StreamBufferManagement
*/
BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
/** @cond */
/* Functions below here are not part of the public API. */
StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer ) PRIVILEGED_FUNCTION;
StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer,
uint8_t * const pucStreamBufferStorageArea,
StaticStreamBuffer_t * const pxStaticStreamBuffer ) PRIVILEGED_FUNCTION;
size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
#if( configUSE_TRACE_FACILITY == 1 )
void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer, UBaseType_t uxStreamBufferNumber ) PRIVILEGED_FUNCTION;
UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
#endif
/** @endcond */
#if defined( __cplusplus )
}
#endif
#endif /* !defined( STREAM_BUFFER_H ) */

File diff suppressed because it is too large Load Diff

View File

@ -1,71 +1,29 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef TIMERS_H
@ -75,10 +33,10 @@
#error "include FreeRTOS.h must appear in source files before include timers.h"
#endif
/*lint -e537 This headers are only multiply included if the application code
/*lint -save -e537 This headers are only multiply included if the application code
happens to also be including task.h. */
#include "task.h"
/*lint +e537 */
/*lint -restore */
#ifdef __cplusplus
extern "C" {
@ -115,14 +73,15 @@ or interrupt version of the queue send function should be used. */
* reference the subject timer in calls to other software timer API functions
* (for example, xTimerStart(), xTimerReset(), etc.).
*/
typedef void * TimerHandle_t;
/**
struct tmrTimerControl; /* The old naming convention is used to prevent breaking kernel aware debuggers. */
//typedef struct tmrTimerControl * TimerHandle_t;
typedef void* TimerHandle_t;
/*
* Defines the prototype to which timer callback functions must conform.
*/
typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer );
/**
/*
* Defines the prototype to which functions used with the
* xTimerPendFunctionCallFromISR() function must conform.
*/
@ -260,11 +219,11 @@ typedef void (*PendedFunction_t)( void *, uint32_t );
* @endcode
*/
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
TimerHandle_t xTimerCreate( const char * const pcTimerName,
TimerHandle_t xTimerCreate( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const TickType_t xTimerPeriodInTicks,
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION;
#endif
/**
@ -388,18 +347,20 @@ typedef void (*PendedFunction_t)( void *, uint32_t );
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction,
StaticTimer_t *pxTimerBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
#endif /* configSUPPORT_STATIC_ALLOCATION */
StaticTimer_t *pxTimerBuffer ) PRIVILEGED_FUNCTION;
#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* void *pvTimerGetTimerID( TimerHandle_t xTimer );
*
* Returns the ID assigned to the timer.
*
* IDs are assigned to timers using the pvTimerID parameter of the call to
* xTimerCreated() that was used to create the timer.
* xTimerCreated() that was used to create the timer, and by calling the
* vTimerSetTimerID() API function.
*
* If the same callback function is assigned to multiple timers then the timer
* ID can be used within the callback function to identify which timer actually
* expired.
* ID can be used as time specific (timer local) storage.
*
* @param xTimer The timer being queried.
*
@ -409,9 +370,11 @@ typedef void (*PendedFunction_t)( void *, uint32_t );
*
* See the xTimerCreate() API function example usage scenario.
*/
void *pvTimerGetTimerID( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
void *pvTimerGetTimerID( const TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
/**
* void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID );
*
* Sets the ID assigned to the timer.
*
* IDs are assigned to timers using the pvTimerID parameter of the call to
@ -431,12 +394,12 @@ void *pvTimerGetTimerID( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ) PRIVILEGED_FUNCTION;
/**
* BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer );
*
* Queries a timer to see if it is active or dormant.
*
* A timer will be dormant if:
*
* 1) It has been created but not started, or
*
* 2) It is an expired one-shot timer that has not been restarted.
*
* Timers are created in the dormant state. The xTimerStart(), xTimerReset(),
@ -474,31 +437,11 @@ BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
* Simply returns the handle of the timer service/daemon task. It it not valid
* to call xTimerGetTimerDaemonTaskHandle() before the scheduler has been started.
*/
TaskHandle_t xTimerGetTimerDaemonTaskHandle( void );
TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
/**
* Returns the period of a timer.
* BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait );
*
* @param xTimer The handle of the timer being queried.
*
* @return The period of the timer in ticks.
*/
TickType_t xTimerGetPeriod( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
/**
* Returns the time in ticks at which the timer will expire. If this is less
* than the current tick count then the expiry time has overflowed from the
* current time.
*
* @param xTimer The handle of the timer being queried.
*
* @return If the timer is running then the time in ticks at which the timer
* will next expire is returned. If the timer is not running then the return
* value is undefined.
*/
TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
/**
* Timer functionality is provided by a timer service/daemon task. Many of the
* public FreeRTOS timer API functions send commands to the timer service task
* through a queue called the timer command queue. The timer command queue is
@ -813,7 +756,7 @@ TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
*
* // Starting the scheduler will start the timer running as it has already
* // been set into the active state.
* xTaskStartScheduler();
* vTaskStartScheduler();
*
* // Should not reach here.
* for( ;; );
@ -1200,7 +1143,7 @@ TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
* }
* @endcode
*/
BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken );
BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
/**
* Used to defer the execution of a function to the RTOS daemon task (the timer
@ -1228,18 +1171,64 @@ BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void
* timer daemon task, otherwise pdFALSE is returned.
*
*/
BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait );
BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/**
* const char * const pcTimerGetName( TimerHandle_t xTimer );
*
* Returns the name that was assigned to a timer when the timer was created.
*
* @param xTimer The handle of the timer being queried.
*
* @return The name assigned to the timer specified by the xTimer parameter.
*/
const char * pcTimerGetTimerName( TimerHandle_t xTimer ); /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
/**
* void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload );
*
* Updates a timer to be either an autoreload 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 updated.
*
* @param uxAutoReload If uxAutoReload 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
* enter the dormant state after it expires.
*/
void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload ) PRIVILEGED_FUNCTION;
/**
* TickType_t xTimerGetPeriod( TimerHandle_t xTimer );
*
* Returns the period of a timer.
*
* @param xTimer The handle of the timer being queried.
*
* @return The period of the timer in ticks.
*/
TickType_t xTimerGetPeriod( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
/**
* TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer );
*
* Returns the time in ticks at which the timer will expire. If this is less
* than the current tick count then the expiry time has overflowed from the
* current time.
*
* @param xTimer The handle of the timer being queried.
*
* @return If the timer is running then the time in ticks at which the timer
* will next expire is returned. If the timer is not running then the return
* value is undefined.
*/
TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
/** @cond */
/*
* Functions beyond this part are not part of the public API and are intended
* for use by the kernel only.
@ -1247,6 +1236,11 @@ const char * pcTimerGetTimerName( TimerHandle_t xTimer ); /*lint !e971 Unqualifi
BaseType_t xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION;
BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
#if( configUSE_TRACE_FACILITY == 1 )
void vTimerSetTimerNumber( TimerHandle_t xTimer, UBaseType_t uxTimerNumber ) PRIVILEGED_FUNCTION;
UBaseType_t uxTimerGetTimerNumber( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
#endif
/** @endcond */
#ifdef __cplusplus

View File

@ -1,440 +1,21 @@
The FreeRTOS.org source code is licensed by the *modified* GNU General Public
License (GPL), text provided below. A special exception to the GPL is
included to allow you to distribute a combined work that includes FreeRTOS
without being obliged to provide the source code for any proprietary
components. See the licensing section of http://www.FreeRTOS.org for full
details. The exception text is also included at the bottom of this file.
The FreeRTOS download also includes demo application source code, some of
which is provided by third parties AND IS LICENSED SEPARATELY FROM FREERTOS.
For the avoidance of any doubt refer to the comment included at the top
of each source and header file for license and copyright information.
This is a list of files for which Real Time Engineers Ltd are not the
copyright owner and are NOT COVERED BY THE GPL.
1) Various header files provided by silicon manufacturers and tool vendors
that define processor specific memory addresses and utility macros.
Permission has been granted by the various copyright holders for these
files to be included in the FreeRTOS download. Users must ensure license
conditions are adhered to for any use other than compilation of the
FreeRTOS demo applications.
2) The uIP TCP/IP stack the copyright of which is held by Adam Dunkels.
Users must ensure the open source license conditions stated at the top
of each uIP source file is understood and adhered to.
3) The lwIP TCP/IP stack the copyright of which is held by the Swedish
Institute of Computer Science. Users must ensure the open source license
conditions stated at the top of each lwIP source file is understood and
adhered to.
4) Various peripheral driver source files and binaries provided by silicon
manufacturers and tool vendors. Permission has been granted by the
various copyright holders for these files to be included in the FreeRTOS
download. Users must ensure license conditions are adhered to for any
use other than compilation of the FreeRTOS demo applications.
5) The files contained within FreeRTOS\Demo\WizNET_DEMO_TERN_186\tern_code,
which are slightly modified versions of code provided by and copyright to
Tern Inc.
Errors and omissions should be reported to Richard Barry, contact details for
whom can be obtained from http://www.FreeRTOS.org.
The GPL license text follows.
A special exception to the GPL is included to allow you to distribute a
combined work that includes FreeRTOS without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details. The exception text is also
included at the bottom of this file.
--------------------------------------------------------------------
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License** as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
----------------------------------------------------------------------------
The FreeRTOS GPL Exception Text:
Any FreeRTOS source code, whether modified or in it's original release form,
or whether in whole or in part, can only be distributed by you under the terms
of the GNU General Public License plus this exception. An independent module is
a module which is not derived from or based on FreeRTOS.
Clause 1:
Linking FreeRTOS statically or dynamically with other modules is making a
combined work based on FreeRTOS. Thus, the terms and conditions of the GNU
General Public License cover the whole combination.
As a special exception, the copyright holder of FreeRTOS gives you permission
to link FreeRTOS with independent modules that communicate with FreeRTOS
solely through the FreeRTOS API interface, regardless of the license terms of
these independent modules, and to copy and distribute the resulting combined
work under terms of your choice, provided that
+ Every copy of the combined work is accompanied by a written statement that
details to the recipient the version of FreeRTOS used and an offer by yourself
to provide the FreeRTOS source code (including any modifications you may have
made) should the recipient request it.
+ The combined work is not itself an RTOS, scheduler, kernel or related product.
+ The independent modules add significant and primary functionality to FreeRTOS
and do not merely extend the existing functionality already present in FreeRTOS.
Clause 2:
FreeRTOS may not be used for any competitive or comparative purpose, including the
publication of any form of run time or compile time metric, without the express
permission of Real Time Engineers Ltd. (this is the norm within the industry and
is intended to ensure information accuracy).
MIT License
Copyright (C) 2017 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.

View File

@ -1,71 +1,29 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#include <stdlib.h>
@ -82,7 +40,7 @@ void vListInitialise( List_t * const 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 The mini list structure is used as the list end to save RAM. This is checked and valid. */
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. */
/* The list end value is the highest possible value in the list to
ensure it remains at the end of the list. */
@ -90,8 +48,8 @@ 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 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 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 ); /*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->uxNumberOfItems = ( UBaseType_t ) 0U;
@ -105,7 +63,7 @@ void vListInitialise( List_t * const pxList )
void vListInitialiseItem( ListItem_t * const pxItem )
{
/* Make sure the list item is not recorded as being on a list. */
pxItem->pvContainer = NULL;
pxItem->pxContainer = NULL;
/* Write known values into the list item if
configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
@ -129,11 +87,15 @@ ListItem_t * const pxIndex = pxList->pxIndex;
listGET_OWNER_OF_NEXT_ENTRY(). */
pxNewListItem->pxNext = pxIndex;
pxNewListItem->pxPrevious = pxIndex->pxPrevious;
/* Only used during decision coverage testing. */
mtCOVERAGE_TEST_DELAY();
pxIndex->pxPrevious->pxNext = pxNewListItem;
pxIndex->pxPrevious = pxNewListItem;
/* Remember which list the item is in. */
pxNewListItem->pvContainer = ( void * ) pxList;
pxNewListItem->pxContainer = pxList;
( pxList->uxNumberOfItems )++;
}
@ -153,7 +115,7 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
/* Insert the new list item into the list, sorted in xItemValue order.
If the list already contains a list item with the same item value then the
new list item should be placed after it. This ensures that TCB's which are
new list item should be placed after it. This ensures that TCBs which are
stored in ready lists (all of which have the same xItemValue value) get a
share of the CPU. However, if the xItemValue is the same as the back marker
the iteration loop below will not end. Therefore the value is checked
@ -166,18 +128,18 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
{
/* *** NOTE ***********************************************************
If you find your application is crashing here then likely causes are
listed below. In addition see http://www.freertos.org/FAQHelp.html for
listed below. In addition see https://www.freertos.org/FAQHelp.html for
more tips, and ensure configASSERT() is defined!
http://www.freertos.org/a00110.html#configASSERT
https://www.freertos.org/a00110.html#configASSERT
1) Stack overflow -
see http://www.freertos.org/Stacks-and-stack-overflow-checking.html
see https://www.freertos.org/Stacks-and-stack-overflow-checking.html
2) Incorrect interrupt priority assignment, especially on Cortex-M
parts where numerically high priority values denote low actual
interrupt priorities, which can seem counter intuitive. See
http://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition
https://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition
of configMAX_SYSCALL_INTERRUPT_PRIORITY on
http://www.freertos.org/a00110.html
https://www.freertos.org/a00110.html
3) Calling an API function from within a critical section or when
the scheduler is suspended, or calling an API function that does
not end in "FromISR" from an interrupt.
@ -186,7 +148,7 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
before vTaskStartScheduler() has been called?).
**********************************************************************/
for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
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. */
{
/* There is nothing to do here, just iterating to the wanted
insertion position. */
@ -200,7 +162,7 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
/* Remember which list the item is in. This allows fast removal of the
item later. */
pxNewListItem->pvContainer = ( void * ) pxList;
pxNewListItem->pxContainer = pxList;
( pxList->uxNumberOfItems )++;
}
@ -210,11 +172,14 @@ UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
/* The list item knows which list it is in. Obtain the list from the list
item. */
List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;
List_t * const pxList = pxItemToRemove->pxContainer;
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
/* Only used during decision coverage testing. */
mtCOVERAGE_TEST_DELAY();
/* Make sure the index is left pointing to a valid item. */
if(pxList->pxIndex == pxItemToRemove)
{
@ -225,7 +190,7 @@ List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;
mtCOVERAGE_TEST_MARKER();
}
pxItemToRemove->pvContainer = NULL;
pxItemToRemove->pxContainer = NULL;
( pxList->uxNumberOfItems )--;
return pxList->uxNumberOfItems;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -125,7 +125,7 @@ TEST_CASE("FreeRTOS Event Group Sync", "[freertos]")
}
/*-----------------Test case for event group trace facilities-----------------*/
#ifdef CONFIG_FREERTOS_USE_TRACE_FACILITY
#ifdef CONFIG_FREERTOS_USE_TRACE_FACILITY
/*
* Test event group Trace Facility functions such as
* xEventGroupClearBitsFromISR(), xEventGroupSetBitsFromISR()
@ -217,5 +217,4 @@ TEST_CASE("FreeRTOS Event Group ISR", "[freertos]")
vSemaphoreDelete(done_sem);
vTaskDelay(10); //Give time for idle task to clear up deleted tasks
}
#endif //CONFIG_FREERTOS_USE_TRACE_FACILITY

View File

@ -29,8 +29,10 @@ void test_task_get_state(void* arg)
void blocked_task(void *arg)
{
uint32_t notify_value;
while(1){
vTaskDelay(portMAX_DELAY);
xTaskNotifyWait(0, 0xFFFFFFFF, &notify_value, portMAX_DELAY);
}
}

View File

@ -0,0 +1,103 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/stream_buffer.h"
#include "freertos/message_buffer.h"
#include "unity.h"
#include "test_utils.h"
typedef struct {
StreamBufferHandle_t sb;
SemaphoreHandle_t end_test;
bool send_fail;
bool receive_fail;
bool produce_isr;
}test_context;
static void producer_task(void *arg)
{
test_context *tc = arg;
uint8_t produced = 0;
printf("Starting sender task... \n");
while(produced < 100) {
if(!tc->produce_isr) {
BaseType_t result = xStreamBufferSend(tc->sb, &produced, 1, 0);
if(!result) {
tc->send_fail = true;
xSemaphoreGive(tc->end_test);
vTaskDelete(NULL);
} else {
produced++;
}
}
vTaskDelay(1);
}
tc->send_fail = false;
vTaskDelete(NULL);
}
static void receiver_task(void *arg)
{
test_context *tc = arg;
uint8_t expected_consumed = 0;
printf("Starting receiver task... \n");
for(;;){
uint8_t read_byte = 0xFF;
uint32_t result = xStreamBufferReceive(tc->sb, &read_byte, 1, 1000);
if((read_byte != expected_consumed) || !result) {
tc->receive_fail = true;
xSemaphoreGive(tc->end_test);
vTaskDelete(NULL);
} else {
expected_consumed++;
if(expected_consumed == 99) {
break;
}
}
}
tc->receive_fail = false;
xSemaphoreGive(tc->end_test);
vTaskDelete(NULL);
}
TEST_CASE("Send-receive stream buffer test", "[freertos]")
{
BaseType_t result;
test_context tc;
tc.sb = xStreamBufferCreate(128, 1);
tc.end_test = xSemaphoreCreateBinary();
TEST_ASSERT(tc.sb);
TEST_ASSERT(tc.end_test);
tc.send_fail = false;
tc.receive_fail = false;
tc.produce_isr = false;
result = xTaskCreatePinnedToCore(producer_task, "sender", 4096, &tc, UNITY_FREERTOS_PRIORITY + 2, NULL, 0);
TEST_ASSERT(result == pdTRUE);
result = xTaskCreatePinnedToCore(receiver_task, "receiver", 4096, &tc, UNITY_FREERTOS_PRIORITY + 1, NULL, 1);
TEST_ASSERT(result == pdTRUE);
result = xSemaphoreTake(tc.end_test, 2000);
TEST_ASSERT(result == pdTRUE);
vTaskDelay(1);
TEST_ASSERT(tc.send_fail == false);
TEST_ASSERT(tc.receive_fail == false);
vStreamBufferDelete(tc.sb);
vSemaphoreDelete(tc.end_test);
}

View File

@ -61,7 +61,7 @@ static void counter_task_fn(void *vp_config)
TEST_CASE("Scheduler disabled can handle a pending context switch on resume", "[freertos]")
{
isr_count = 0;
isr_semaphore = xSemaphoreCreateMutex();
isr_semaphore = xSemaphoreCreateBinary();
TaskHandle_t counter_task;
intr_handle_t isr_handle = NULL;

View File

@ -68,3 +68,20 @@ TEST_CASE("Recurring FreeRTOS timers", "[freertos]")
TEST_ASSERT( xTimerDelete(recurring, 1) );
}
#ifdef CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION
TEST_CASE("Static timer creation", "[freertos]")
{
StaticTimer_t static_timer;
TimerHandle_t created_timer;
volatile int count = 0;
created_timer = xTimerCreateStatic("oneshot", 100 / portTICK_PERIOD_MS,
pdTRUE,
(void *)&count,
timer_callback,
&static_timer);
TEST_ASSERT_NOT_NULL(created_timer);
}
#endif

View File

@ -1,71 +1,29 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/* Standard includes. */
#include <stdlib.h>
@ -79,17 +37,16 @@ task.h is included from an application file. */
#include "task.h"
#include "queue.h"
#include "timers.h"
#include "portmacro.h"
#if ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 0 )
#error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available.
#endif
/* Lint e961 and e750 are suppressed as a MISRA exception justified because 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. */
/* 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
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. */
/* This entire source file will be skipped if the application is not configured
@ -101,22 +58,29 @@ configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
/* Misc definitions. */
#define tmrNO_DELAY ( TickType_t ) 0U
/* The name assigned to the timer service task. This can be overridden by
defining trmTIMER_SERVICE_TASK_NAME in FreeRTOSConfig.h. */
#ifndef configTIMER_SERVICE_TASK_NAME
#define configTIMER_SERVICE_TASK_NAME "Tmr Svc"
#endif
/* 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 )
/* The definition of the timers themselves. */
typedef struct tmrTimerControl
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. */
UBaseType_t uxAutoReload; /*<< Set to pdTRUE if the timer should be automatically restarted once expired. Set to pdFALSE if the timer is, in effect, a one-shot timer. */
void *pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */
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 */
#endif
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
uint8_t ucStaticallyAllocated; /*<< Set to pdTRUE if the timer was created statically so no attempt is made to free the memory again if the timer is later deleted. */
#endif
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
@ -159,12 +123,15 @@ typedef struct tmrTimerQueueMessage
} u;
} DaemonTaskMessage_t;
/*lint -e956 A manual analysis and inspection has been used to determine which
static variables must be declared volatile. */
/*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. */
timer service task is allowed to access these lists.
xActiveTimerList1 and xActiveTimerList2 could be at function scope but that
breaks some kernel aware debuggers, and debuggers that reply on removing the
static qualifier. */
PRIVILEGED_DATA static List_t xActiveTimerList1;
PRIVILEGED_DATA static List_t xActiveTimerList2;
PRIVILEGED_DATA static List_t *pxCurrentTimerList;
@ -172,20 +139,25 @@ PRIVILEGED_DATA static List_t *pxOverflowTimerList;
/* A queue that is used to send commands to the timer service task. */
PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;
PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;
/* Mux. We use a single mux for all the timers for now. ToDo: maybe increase granularity here? */
PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED;
#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )
PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;
#endif
/*lint +e956 */
/*lint -restore */
/*-----------------------------------------------------------*/
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
/* If static allocation is supported then the application must provide the
following callback function - which enables the application to optionally
provide the memory that will be used by the timer task as the task's stack
and TCB. */
extern void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize );
#endif
/*
* Initialise the infrastructure used by the timer service task if it has not
* been initialised already.
@ -197,13 +169,13 @@ static void prvCheckForValidListAndQueue( void ) PRIVILEGED_FUNCTION;
* task. Other tasks communicate with the timer service task using the
* xTimerQueue queue.
*/
static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION;
static portTASK_FUNCTION_PROTO( prvTimerTask, pvParameters ) PRIVILEGED_FUNCTION;
/*
* Called by the timer service task to interpret and process a command it
* received on the timer queue.
*/
static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION;
static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION;
/*
* Insert the timer into either xActiveTimerList1, or xActiveTimerList2,
@ -241,18 +213,18 @@ static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIV
* If a timer has expired, process it. Otherwise, block the timer service task
* until either a timer does expire or a command is received.
*/
static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, const BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION;
static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION;
/*
* 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,
static void prvInitialiseNewTimer( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const TickType_t xTimerPeriodInTicks,
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction,
Timer_t *pxNewTimer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
Timer_t *pxNewTimer ) PRIVILEGED_FUNCTION;
/*-----------------------------------------------------------*/
BaseType_t xTimerCreateTimerTask( void )
@ -263,29 +235,41 @@ BaseType_t xReturn = pdFAIL;
configUSE_TIMERS is set to 1. Check that the infrastructure used by the
timer service task has been created/initialised. If timers have already
been created then the initialisation will already have been performed. */
/* For now, the timer task will be fixed to core 0. This means whatever process
running on whatever core schedules the timer, the timer callback function
will *ALWAYS* run on core 0. */
prvCheckForValidListAndQueue();
if( xTimerQueue != NULL )
{
/* Although static allocation has been backported from FreeRTOS v9.0.0,
the timer task is still allocated dynamically. The actual timers
however can be allocated statically.*/
#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )
#if( configSUPPORT_STATIC_ALLOCATION == 1 && configSUPPORT_STATIC_ALLOCATION == 0 )
{
/* Create the timer task, storing its handle in xTimerTaskHandle so
it can be returned by the xTimerGetTimerDaemonTaskHandle() function. */
xReturn = xTaskCreatePinnedToCore( prvTimerTask, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, &xTimerTaskHandle, 0 );
StaticTask_t *pxTimerTaskTCBBuffer = NULL;
StackType_t *pxTimerTaskStackBuffer = NULL;
uint32_t ulTimerTaskStackSize;
vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer, &pxTimerTaskStackBuffer, &ulTimerTaskStackSize );
xTimerTaskHandle = xTaskCreateStaticPinnedToCore( prvTimerTask,
configTIMER_SERVICE_TASK_NAME,
ulTimerTaskStackSize,
NULL,
( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,
pxTimerTaskStackBuffer,
pxTimerTaskTCBBuffer,
0 );
if( xTimerTaskHandle != NULL )
{
xReturn = pdPASS;
}
}
#else
{
/* Create the timer task without storing its handle. */
xReturn = xTaskCreatePinnedToCore( prvTimerTask, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, NULL, 0 );
xReturn = xTaskCreatePinnedToCore( prvTimerTask,
configTIMER_SERVICE_TASK_NAME,
configTIMER_TASK_STACK_DEPTH,
NULL,
( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,
&xTimerTaskHandle, 0 );
}
#endif
#endif /* configSUPPORT_STATIC_ALLOCATION */
}
else
{
@ -299,44 +283,39 @@ BaseType_t xReturn = pdFAIL;
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
TimerHandle_t xTimerCreate( const char * const pcTimerName,
TimerHandle_t xTimerCreate( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const TickType_t xTimerPeriodInTicks,
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
TimerCallbackFunction_t pxCallbackFunction )
{
Timer_t *pxNewTimer;
pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) );
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. */
if( pxNewTimer != NULL )
{
/* Status is thus far zero as the timer is not created statically
and has not been started. The autoreload bit may get set in
prvInitialiseNewTimer. */
pxNewTimer->ucStatus = 0x00;
prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
{
/* Timers can be created statically or dynamically, so note this
timer was created dynamically in case the timer is later
deleted. */
pxNewTimer->ucStaticallyAllocated = pdFALSE;
}
#endif /* configSUPPORT_STATIC_ALLOCATION */
}
return pxNewTimer;
}
#endif /* configSUPPORT_STATIC_ALLOCATION */
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
TimerHandle_t xTimerCreateStatic( const char * const pcTimerName,
TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const TickType_t xTimerPeriodInTicks,
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction,
StaticTimer_t *pxTimerBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
StaticTimer_t *pxTimerBuffer )
{
Timer_t *pxNewTimer;
@ -344,7 +323,7 @@ BaseType_t xReturn = pdFAIL;
{
/* Sanity check that the size of the structure used to declare a
variable of type StaticTimer_t equals the size of the real timer
structures. */
structure. */
volatile size_t xSize = sizeof( StaticTimer_t );
configASSERT( xSize == sizeof( Timer_t ) );
( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */
@ -353,19 +332,16 @@ BaseType_t xReturn = pdFAIL;
/* A pointer to a StaticTimer_t structure MUST be provided, use it. */
configASSERT( pxTimerBuffer );
pxNewTimer = ( Timer_t * ) pxTimerBuffer; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
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. */
if( pxNewTimer != NULL )
{
prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );
/* Timers can be created statically or dynamically so note this
timer was created statically in case it is later deleted. The
autoreload bit may get set in prvInitialiseNewTimer(). */
pxNewTimer->ucStatus = tmrSTATUS_IS_STATICALLY_ALLOCATED;
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
{
/* Timers can be created statically or dynamically so note this
timer was created statically in case it is later deleted. */
pxNewTimer->ucStaticallyAllocated = pdTRUE;
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );
}
return pxNewTimer;
@ -374,12 +350,12 @@ BaseType_t xReturn = pdFAIL;
#endif /* configSUPPORT_STATIC_ALLOCATION */
/*-----------------------------------------------------------*/
static void prvInitialiseNewTimer( const char * const pcTimerName,
static void prvInitialiseNewTimer( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const TickType_t xTimerPeriodInTicks,
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction,
Timer_t *pxNewTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
Timer_t *pxNewTimer )
{
/* 0 is not a valid value for xTimerPeriodInTicks. */
configASSERT( ( xTimerPeriodInTicks > 0 ) );
@ -394,10 +370,13 @@ static void prvInitialiseNewTimer( const char * const pcTimerName,
parameters. */
pxNewTimer->pcTimerName = pcTimerName;
pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;
pxNewTimer->uxAutoReload = uxAutoReload;
pxNewTimer->pvTimerID = pvTimerID;
pxNewTimer->pxCallbackFunction = pxCallbackFunction;
vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );
if( uxAutoReload != pdFALSE )
{
pxNewTimer->ucStatus |= tmrSTATUS_IS_AUTORELOAD;
}
traceTIMER_CREATE( pxNewTimer );
}
}
@ -408,6 +387,8 @@ BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommand
BaseType_t xReturn = pdFAIL;
DaemonTaskMessage_t xMessage;
configASSERT( xTimer );
/* Send a message to the timer service task to perform a particular action
on a particular timer definition. */
if( xTimerQueue != NULL )
@ -415,7 +396,7 @@ DaemonTaskMessage_t xMessage;
/* Send a command to the timer service task to start the xTimer timer. */
xMessage.xMessageID = xCommandID;
xMessage.u.xTimerParameters.xMessageValue = xOptionalValue;
xMessage.u.xTimerParameters.pxTimer = ( Timer_t * ) xTimer;
xMessage.u.xTimerParameters.pxTimer = xTimer;
if( xCommandID < tmrFIRST_FROM_ISR_COMMAND )
{
@ -444,43 +425,60 @@ DaemonTaskMessage_t xMessage;
}
/*-----------------------------------------------------------*/
#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )
TaskHandle_t xTimerGetTimerDaemonTaskHandle( void )
{
/* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been
started, then xTimerTaskHandle will be NULL. */
configASSERT( ( xTimerTaskHandle != NULL ) );
return xTimerTaskHandle;
}
#endif
TaskHandle_t xTimerGetTimerDaemonTaskHandle( void )
{
/* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been
started, then xTimerTaskHandle will be NULL. */
configASSERT( ( xTimerTaskHandle != NULL ) );
return xTimerTaskHandle;
}
/*-----------------------------------------------------------*/
TickType_t xTimerGetPeriod( TimerHandle_t xTimer )
{
Timer_t *pxTimer = ( Timer_t * ) xTimer;
Timer_t *pxTimer = xTimer;
configASSERT( xTimer );
return pxTimer->xTimerPeriodInTicks;
configASSERT( xTimer );
return pxTimer->xTimerPeriodInTicks;
}
/*-----------------------------------------------------------*/
void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload )
{
Timer_t * pxTimer = xTimer;
configASSERT( xTimer );
taskENTER_CRITICAL( &xTimerMux);
{
if( uxAutoReload != pdFALSE )
{
pxTimer->ucStatus |= tmrSTATUS_IS_AUTORELOAD;
}
else
{
pxTimer->ucStatus &= ~tmrSTATUS_IS_AUTORELOAD;
}
}
taskEXIT_CRITICAL( &xTimerMux);
}
/*-----------------------------------------------------------*/
TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer )
{
Timer_t * pxTimer = ( Timer_t * ) xTimer;
Timer_t * pxTimer = xTimer;
TickType_t xReturn;
configASSERT( xTimer );
xReturn = listGET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ) );
return xReturn;
configASSERT( xTimer );
xReturn = listGET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ) );
return xReturn;
}
/*-----------------------------------------------------------*/
const char * pcTimerGetTimerName( TimerHandle_t xTimer )
{
Timer_t *pxTimer = ( Timer_t * ) xTimer;
const char * pcTimerGetName( TimerHandle_t xTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
{
Timer_t *pxTimer = xTimer;
configASSERT( xTimer );
return pxTimer->pcTimerName;
}
/*-----------------------------------------------------------*/
@ -488,7 +486,7 @@ Timer_t *pxTimer = ( Timer_t * ) xTimer;
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 );
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. */
/* Remove the timer from the list of active timers. A check has already
been performed to ensure the list is not empty. */
@ -497,12 +495,12 @@ Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTi
/* 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->uxAutoReload == ( UBaseType_t ) pdTRUE )
if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 )
{
/* 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 ) == pdTRUE )
if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) != pdFALSE )
{
/* The timer expired before it was added to the active timer
list. Reload it now. */
@ -517,6 +515,7 @@ Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTi
}
else
{
pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;
mtCOVERAGE_TEST_MARKER();
}
@ -525,7 +524,7 @@ Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTi
}
/*-----------------------------------------------------------*/
static void prvTimerTask( void *pvParameters )
static portTASK_FUNCTION( prvTimerTask, pvParameters )
{
TickType_t xNextExpireTime;
BaseType_t xListWasEmpty;
@ -533,6 +532,18 @@ BaseType_t xListWasEmpty;
/* Just to avoid compiler warnings. */
( 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();
}
#endif /* configUSE_DAEMON_TASK_STARTUP_HOOK */
for( ;; )
{
/* Query the timers list to see if it contains any timers, and if so,
@ -549,12 +560,12 @@ BaseType_t xListWasEmpty;
}
/*-----------------------------------------------------------*/
static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, const BaseType_t xListWasEmpty )
static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty )
{
TickType_t xTimeNow;
BaseType_t xTimerListsWereSwitched;
vTaskSuspendAll();
taskENTER_CRITICAL( &xTimerMux);
{
/* Obtain the time now to make an assessment as to whether the timer
has expired or not. If obtaining the time causes the lists to switch
@ -567,7 +578,7 @@ BaseType_t xTimerListsWereSwitched;
/* The tick count has not overflowed, has the timer expired? */
if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) )
{
( void ) xTaskResumeAll();
taskEXIT_CRITICAL( &xTimerMux);
prvProcessExpiredTimer( xNextExpireTime, xTimeNow );
}
else
@ -578,25 +589,28 @@ BaseType_t xTimerListsWereSwitched;
received - whichever comes first. The following line cannot
be reached unless xNextExpireTime > xTimeNow, except in the
case when the current timer list is empty. */
vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ) );
if( xListWasEmpty != pdFALSE )
{
/* The current timer list is empty - is the overflow list
also empty? */
xListWasEmpty = listLIST_IS_EMPTY( pxOverflowTimerList );
}
if( xTaskResumeAll() == pdFALSE )
{
/* Yield to wait for either a command to arrive, or the
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. */
portYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ), xListWasEmpty );
taskEXIT_CRITICAL( &xTimerMux);
/* Yield to wait for either a command to arrive, or the
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. */
portYIELD_WITHIN_API();
}
}
else
{
( void ) xTaskResumeAll();
taskEXIT_CRITICAL( &xTimerMux);
}
}
}
@ -662,7 +676,7 @@ BaseType_t xProcessTimerNow = pdFALSE;
{
/* Has the expiry time elapsed between the command to start/reset a
timer was issued, and the time the command was processed? */
if( ( xTimeNow - xCommandTime ) >= pxTimer->xTimerPeriodInTicks )
if( ( ( TickType_t ) ( xTimeNow - xCommandTime ) ) >= pxTimer->xTimerPeriodInTicks ) /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
{
/* The time between a command being issued and the command being
processed actually exceeds the timers period. */
@ -731,7 +745,7 @@ TickType_t xTimeNow;
software timer. */
pxTimer = xMessage.u.xTimerParameters.pxTimer;
if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE )
if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) /*lint !e961. The cast is only redundant when NULL is passed into the macro. */
{
/* The timer is in a list, remove it. */
( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
@ -754,19 +768,20 @@ TickType_t xTimeNow;
switch( xMessage.xMessageID )
{
case tmrCOMMAND_START :
case tmrCOMMAND_START_FROM_ISR :
case tmrCOMMAND_RESET :
case tmrCOMMAND_RESET_FROM_ISR :
case tmrCOMMAND_START_FROM_ISR :
case tmrCOMMAND_RESET :
case tmrCOMMAND_RESET_FROM_ISR :
case tmrCOMMAND_START_DONT_TRACE :
/* Start or restart a timer. */
if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) == pdTRUE )
pxTimer->ucStatus |= 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->uxAutoReload == ( UBaseType_t ) pdTRUE )
if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 )
{
xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY );
configASSERT( xResult );
@ -785,48 +800,48 @@ TickType_t xTimeNow;
case tmrCOMMAND_STOP :
case tmrCOMMAND_STOP_FROM_ISR :
/* The timer has already been removed from the active list.
There is nothing to do here. */
/* The timer has already been removed from the active list. */
pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;
break;
case tmrCOMMAND_CHANGE_PERIOD :
case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR :
pxTimer->ucStatus |= tmrSTATUS_IS_ACTIVE;
pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue;
configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) );
/* The new period does not really have a reference, and can be
longer or shorter than the old one. The command time is
therefore set to the current time, and as the period cannot be
zero the next expiry time can only be in the future, meaning
(unlike for the xTimerStart() case above) there is no fail case
that needs to be handled here. */
/* The new period does not really have a reference, and can
be longer or shorter than the old one. The command time is
therefore set to the current time, and as the period cannot
be zero the next expiry time can only be in the future,
meaning (unlike for the xTimerStart() case above) there is
no fail case that needs to be handled here. */
( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow );
break;
case tmrCOMMAND_DELETE :
/* The timer has already been removed from the active list,
just free up the memory if the memory was dynamically
allocated. */
#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
{
/* The timer can only have been allocated dynamically -
free it again. */
vPortFree( pxTimer );
}
#elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
{
/* The timer could have been allocated statically or
dynamically, so check before attempting to free the
memory. */
if( pxTimer->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
/* 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
{
mtCOVERAGE_TEST_MARKER();
pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;
}
}
#else
{
/* 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;
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
break;
@ -855,7 +870,7 @@ BaseType_t xResult;
xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );
/* Remove the timer from the list. */
pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );
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 );
@ -864,7 +879,7 @@ BaseType_t xResult;
have not yet been switched. */
pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )
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
@ -903,14 +918,10 @@ static void prvCheckForValidListAndQueue( void )
/* Check that the list from which active timers are referenced, and the
queue used to communicate with the timer service, have been
initialised. */
/* Erm, yes, this is a problem. We can't lock until the lock is initialized, and we can't initialize the lock
atomically because we don't have a lock yet... I'm pretty sure doubly-initializing a lock on 2 cpus
is no problem in the current implementation, but this is not a nice way to solve things. ToDo - improve. */
if( xTimerQueue == NULL ) vPortCPUInitializeMutex( &xTimerMux );
taskENTER_CRITICAL( &xTimerMux );
taskENTER_CRITICAL( &xTimerMux);
{
if( xTimerQueue == NULL )
{
@ -918,8 +929,21 @@ static void prvCheckForValidListAndQueue( void )
vListInitialise( &xActiveTimerList2 );
pxCurrentTimerList = &xActiveTimerList1;
pxOverflowTimerList = &xActiveTimerList2;
xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) );
configASSERT( xTimerQueue );
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
{
/* The timer queue is allocated statically in case
configSUPPORT_DYNAMIC_ALLOCATION is 0. */
static StaticQueue_t xStaticTimerQueue; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */
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. */
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 ) );
}
#endif
#if ( configQUEUE_REGISTRY_SIZE > 0 )
{
@ -939,48 +963,63 @@ static void prvCheckForValidListAndQueue( void )
mtCOVERAGE_TEST_MARKER();
}
}
taskEXIT_CRITICAL( &xTimerMux );
taskEXIT_CRITICAL( &xTimerMux);
}
/*-----------------------------------------------------------*/
BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer )
{
BaseType_t xTimerIsInActiveList;
Timer_t *pxTimer = ( Timer_t * ) xTimer;
BaseType_t xReturn;
Timer_t *pxTimer = xTimer;
configASSERT( xTimer );
/* Is the timer in the list of active timers? */
taskENTER_CRITICAL( &xTimerMux );
taskENTER_CRITICAL( &xTimerMux);
{
/* Checking to see if it is in the NULL list in effect checks to see if
it is referenced from either the current or the overflow timer lists in
one go, but the logic has to be reversed, hence the '!'. */
xTimerIsInActiveList = ( BaseType_t ) !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) );
if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0 )
{
xReturn = pdFALSE;
}
else
{
xReturn = pdTRUE;
}
}
taskEXIT_CRITICAL( &xTimerMux );
taskEXIT_CRITICAL( &xTimerMux);
return xTimerIsInActiveList;
return xReturn;
} /*lint !e818 Can't be pointer to const due to the typedef. */
/*-----------------------------------------------------------*/
void *pvTimerGetTimerID( const TimerHandle_t xTimer )
{
Timer_t * const pxTimer = ( Timer_t * ) xTimer;
Timer_t * const pxTimer = xTimer;
void *pvReturn;
return pxTimer->pvTimerID;
configASSERT( xTimer );
taskENTER_CRITICAL( &xTimerMux);
{
pvReturn = pxTimer->pvTimerID;
}
taskEXIT_CRITICAL( &xTimerMux);
return pvReturn;
}
/*-----------------------------------------------------------*/
void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID )
{
Timer_t * const pxTimer = ( Timer_t * ) xTimer;
Timer_t * const pxTimer = xTimer;
configASSERT( xTimer );
configASSERT( xTimer );
//taskENTER_CRITICAL(); //Atomic instruction, critical not necessary
//{
pxTimer->pvTimerID = pvNewID;
//}
//taskEXIT_CRITICAL();
taskENTER_CRITICAL( &xTimerMux);
{
pxTimer->pvTimerID = pvNewID;
}
taskEXIT_CRITICAL( &xTimerMux);
}
/*-----------------------------------------------------------*/
@ -1037,6 +1076,26 @@ Timer_t * const pxTimer = ( Timer_t * ) xTimer;
#endif /* INCLUDE_xTimerPendFunctionCall */
/*-----------------------------------------------------------*/
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxTimerGetTimerNumber( TimerHandle_t xTimer )
{
return ( ( Timer_t * ) xTimer )->uxTimerNumber;
}
#endif /* configUSE_TRACE_FACILITY */
/*-----------------------------------------------------------*/
#if ( configUSE_TRACE_FACILITY == 1 )
void vTimerSetTimerNumber( TimerHandle_t xTimer, UBaseType_t uxTimerNumber )
{
( ( Timer_t * ) xTimer )->uxTimerNumber = uxTimerNumber;
}
#endif /* configUSE_TRACE_FACILITY */
/*-----------------------------------------------------------*/
/* This entire source file will be skipped if the application is not configured
to include software timer functionality. If you want to include software timer
functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */

View File

@ -84,10 +84,10 @@
#define portNUM_PROCESSORS 1
#endif
#define XT_USE_THREAD_SAFE_CLIB 0
#define configASSERT_2 0
#define portUSING_MPU_WRAPPERS 0
#define configUSE_MUTEX 1
#define XT_USE_THREAD_SAFE_CLIB 0
#define configASSERT_2 0
#define portUSING_MPU_WRAPPERS 0
#define configUSE_MUTEX 1
#undef XT_USE_SWPRI
#if CONFIG_FREERTOS_CORETIMER_0
@ -96,7 +96,7 @@
#define XT_TIMER_INDEX 1
#endif
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS
#define configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS 1
#ifndef __ASSEMBLER__
@ -171,7 +171,7 @@ int xt_clock_freq(void) __attribute__((deprecated));
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 1
#define configUSE_TICK_HOOK 1
#define configRECORD_STACK_HIGH_ADDRESS 1
#define configTICK_RATE_HZ ( CONFIG_FREERTOS_HZ )
/* Default clock rate for simulator */
@ -256,8 +256,6 @@ int xt_clock_freq(void) __attribute__((deprecated));
#endif
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )

View File

@ -72,6 +72,7 @@ extern "C" {
#ifndef __ASSEMBLER__
#include <sdkconfig.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
@ -82,11 +83,16 @@ extern "C" {
#include <xtensa/xtruntime.h>
#include "esp_private/crosscore_int.h"
#include "esp_timer.h" /* required for FreeRTOS run time stats */
#include "esp_system.h"
#include "esp_newlib.h"
#include "soc/spinlock.h"
#include <esp_heap_caps.h>
#include "esp_rom_sys.h"
#include "sdkconfig.h"
#include "freertos/xtensa_api.h"
#include "esp_system.h"
#include "soc/cpu.h"
#include <limits.h>
#ifdef CONFIG_LEGACY_INCLUDE_COMMON_HEADERS
#include "soc/soc_memory_layout.h"
@ -127,18 +133,10 @@ typedef unsigned portBASE_TYPE UBaseType_t;
// portbenchmark
#include "portbenchmark.h"
#include "sdkconfig.h"
#include "esp_attr.h"
static inline uint32_t xPortGetCoreID(void);
// Critical section management. NW-TODO: replace XTOS_SET_INTLEVEL with more efficient version, if any?
// These cannot be nested. They should be used with a lot of care and cannot be called from interrupt level.
//
// Only applies to one CPU. See notes above & below for reasons not to use these.
#define portDISABLE_INTERRUPTS() do { XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); portbenchmarkINTERRUPT_DISABLE(); } while (0)
#define portENABLE_INTERRUPTS() do { portbenchmarkINTERRUPT_RESTORE(0); XTOS_SET_INTLEVEL(0); } while (0)
// Cleaner solution allows nested interrupts disabling and restoring via local registers or stack.
// They can be called from interrupts too.
// WARNING: Only applies to current CPU. See notes above.
@ -172,48 +170,45 @@ This all assumes that interrupts are either entirely disabled or enabled. Interr
will break this scheme.
Remark: For the ESP32, portENTER_CRITICAL and portENTER_CRITICAL_ISR both alias vTaskEnterCritical, meaning
that either function can be called both from ISR as well as task context. This is not standard FreeRTOS
that either function can be called both from ISR as well as task context. This is not standard FreeRTOS
behaviour; please keep this in mind if you need any compatibility with other FreeRTOS implementations.
*/
/* "mux" data structure (spinlock) */
typedef struct {
spinlock_t spinlock;
} portMUX_TYPE;
typedef spinlock_t portMUX_TYPE;
#define portMUX_FREE_VAL SPINLOCK_FREE
#define portMUX_NO_TIMEOUT SPINLOCK_WAIT_FOREVER /* When passed for 'timeout_cycles', spin forever if necessary */
#define portMUX_TRY_LOCK SPINLOCK_NO_WAIT /* Try to acquire the spinlock a single time only */
#define portMUX_INITIALIZER_UNLOCKED {.spinlock=SPINLOCK_INITIALIZER}
#define portASSERT_IF_IN_ISR() vPortAssertIfInISR()
void vPortAssertIfInISR(void);
#define portMUX_INITIALIZER_UNLOCKED SPINLOCK_INITIALIZER
#define portCRITICAL_NESTING_IN_TCB 0
static inline void __attribute__((always_inline)) vPortCPUInitializeMutex(portMUX_TYPE *mux)
{
spinlock_initialize(&mux->spinlock);
spinlock_initialize(mux);
}
static inline void __attribute__((always_inline)) vPortCPUAcquireMutex(portMUX_TYPE *mux)
{
spinlock_acquire(&mux->spinlock, portMUX_NO_TIMEOUT);
spinlock_acquire(mux, portMUX_NO_TIMEOUT);
}
static inline bool __attribute__((always_inline)) vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout)
{
return (spinlock_acquire(&mux->spinlock, timeout));
return (spinlock_acquire(mux, timeout));
}
static inline void __attribute__((always_inline)) vPortCPUReleaseMutex(portMUX_TYPE *mux)
{
spinlock_release(&mux->spinlock);
spinlock_release(mux);
}
void vPortEnterCritical(portMUX_TYPE *mux);
void vPortExitCritical(portMUX_TYPE *mux);
#define portASSERT_IF_IN_ISR() vPortAssertIfInISR()
void vPortAssertIfInISR(void);
/*
* Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs
* aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.
@ -246,8 +241,8 @@ static inline void __attribute__((always_inline)) vPortExitCriticalCompliance(po
/* Calling port*_CRITICAL from ISR context would cause an assert failure.
* If the parent function is called from both ISR and Non-ISR context then call port*_CRITICAL_SAFE
*/
#define portENTER_CRITICAL(mux) vPortEnterCriticalCompliance(mux)
#define portEXIT_CRITICAL(mux) vPortExitCriticalCompliance(mux)
#define portENTER_CRITICAL(mux) vPortEnterCriticalCompliance(mux)
#define portEXIT_CRITICAL(mux) vPortExitCriticalCompliance(mux)
#else
#define portENTER_CRITICAL(mux) vPortEnterCritical(mux)
#define portEXIT_CRITICAL(mux) vPortExitCritical(mux)
@ -276,6 +271,7 @@ static inline void __attribute__((always_inline)) vPortExitCriticalSafe(portMUX_
#define portENTER_CRITICAL_SAFE(mux) vPortEnterCriticalSafe(mux)
#define portEXIT_CRITICAL_SAFE(mux) vPortExitCriticalSafe(mux)
/*
* Wrapper for the Xtensa compare-and-set instruction. This subroutine will atomically compare
* *addr to 'compare'. If *addr == compare, *addr is set to *set. *set is updated with the previous
@ -289,6 +285,14 @@ static inline void __attribute__((always_inline)) uxPortCompareSet(volatile uint
compare_and_set_native(addr, compare, set);
}
// Critical section management. NW-TODO: replace XTOS_SET_INTLEVEL with more efficient version, if any?
// These cannot be nested. They should be used with a lot of care and cannot be called from interrupt level.
//
// Only applies to one CPU. See notes above & below for reasons not to use these.
#define portDISABLE_INTERRUPTS() do { XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); portbenchmarkINTERRUPT_DISABLE(); } while (0)
#define portENABLE_INTERRUPTS() do { portbenchmarkINTERRUPT_RESTORE(0); XTOS_SET_INTLEVEL(0); } while (0)
// These FreeRTOS versions are similar to the nested versions above
#define portSET_INTERRUPT_MASK_FROM_ISR() portENTER_CRITICAL_NESTED()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(state) portEXIT_CRITICAL_NESTED(state)
@ -297,10 +301,26 @@ static inline void __attribute__((always_inline)) uxPortCompareSet(volatile uint
//the stack memory to always be internal.
#define portTcbMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
#define portStackMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
#define pvPortMallocTcbMem(size) heap_caps_malloc(size, portTcbMemoryCaps)
#define pvPortMallocStackMem(size) heap_caps_malloc(size, portStackMemoryCaps)
//xTaskCreateStatic uses these functions to check incoming memory.
#define portVALID_TCB_MEM(ptr) (esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr))
#ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
#define portVALID_STACK_MEM(ptr) esp_ptr_byte_accessible(ptr)
#else
#define portVALID_STACK_MEM(ptr) (esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr))
#endif
static inline void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set)
{
#ifdef CONFIG_SPIRAM
compare_and_set_extram(addr, compare, set);
#endif
}
/*-----------------------------------------------------------*/
/* Architecture specifics. */
@ -397,13 +417,11 @@ extern void esp_vApplicationTickHook( void );
#define vApplicationTickHook esp_vApplicationTickHook
#endif /* !CONFIG_FREERTOS_LEGACY_HOOKS */
void _xt_coproc_release(volatile void * coproc_sa_base);
void vApplicationSleep( TickType_t xExpectedIdleTime );
void vPortSetStackWatchpoint( void* pxStackStart );
#define portSUPPRESS_TICKS_AND_SLEEP( idleTime ) vApplicationSleep( idleTime )
/*-----------------------------------------------------------*/
void _xt_coproc_release(volatile void * coproc_sa_base);
/* Architecture specific optimisations. */
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
@ -423,7 +441,68 @@ void vPortSetStackWatchpoint( void* pxStackStart );
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/*-----------------------------------------------------------*/
/*
* Send an interrupt to another core in order to make the task running
* on it yield for a higher-priority task.
*/
void vPortYieldOtherCore( BaseType_t coreid) ;
/*
Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack
watchpoint around.
*/
void vPortSetStackWatchpoint( void* pxStackStart );
/*
* Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs
* aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.
*/
BaseType_t xPortInIsrContext(void);
/*
* This function will be called in High prio ISRs. Returns true if the current core was in ISR context
* before calling into high prio ISR context.
*/
BaseType_t xPortInterruptedFromISRContext(void);
/*
* The structures and methods of manipulating the MPU are contained within the
* port layer.
*
* Fills the xMPUSettings structure with the memory region information
* contained in xRegions.
*/
#if( portUSING_MPU_WRAPPERS == 1 )
struct xMEMORY_REGION;
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t usStackDepth ) PRIVILEGED_FUNCTION;
void vPortReleaseTaskMPUSettings( xMPU_SETTINGS *xMPUSettings );
#endif
/* Multi-core: get current core ID */
static inline uint32_t IRAM_ATTR xPortGetCoreID(void) {
return cpu_hal_get_core_id();
}
/* Get tick rate per second */
uint32_t xPortGetTickRateHz(void);
static inline bool IRAM_ATTR xPortCanYield(void)
{
uint32_t ps_reg = 0;
//Get the current value of PS (processor status) register
RSR(PS, ps_reg);
/*
* intlevel = (ps_reg & 0xf);
* excm = (ps_reg >> 4) & 0x1;
* CINTLEVEL is max(excm * EXCMLEVEL, INTLEVEL), where EXCMLEVEL is 3.
* However, just return true, only intlevel is zero.
*/
return ((ps_reg & PS_INTLEVEL_MASK) == 0);
}
// porttrace
#if configUSE_TRACE_FACILITY_2

View File

@ -1,2 +1,2 @@
/* This header file has been moved, please include <xtensa/xtensa_context.h> in future */
#include <xtensa/xtensa_context.h>
#include <xtensa/xtensa_context.h>

View File

@ -109,7 +109,6 @@
#include "esp_intr_alloc.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "esp_compiler.h"
#include "esp_task_wdt.h"
#include "esp_task.h"
@ -290,6 +289,7 @@ void vPortEndScheduler( void )
{
/* It is unlikely that the Xtensa port will get stopped. If required simply
disable the tick interrupt here. */
abort();
}
/*-----------------------------------------------------------*/
@ -619,4 +619,4 @@ void esp_startup_start_app(void)
ESP_LOGI(TAG, "Starting scheduler on PRO CPU.");
vTaskStartScheduler();
}
}

View File

@ -1,7 +1,8 @@
set(srcs
"heap_caps.c"
"heap_caps_init.c"
"multi_heap.c")
"multi_heap.c"
"heap_tlsf.c")
if(NOT CONFIG_HEAP_POISONING_DISABLED)
list(APPEND srcs "multi_heap_poisoning.c")

View File

@ -2,7 +2,7 @@
# Component Makefile
#
COMPONENT_OBJS := heap_caps_init.o heap_caps.o multi_heap.o
COMPONENT_OBJS := heap_caps_init.o heap_caps.o multi_heap.o heap_tlsf.o
ifndef CONFIG_HEAP_POISONING_DISABLED
COMPONENT_OBJS += multi_heap_poisoning.o

View File

@ -598,6 +598,11 @@ IRAM_ATTR void *heap_caps_aligned_alloc(size_t alignment, size_t size, int caps)
return NULL;
}
IRAM_ATTR void heap_caps_aligned_free(void *ptr)
{
heap_caps_free(ptr);
}
void *heap_caps_aligned_calloc(size_t alignment, size_t n, size_t size, uint32_t caps)
{
size_t size_bytes;
@ -611,15 +616,4 @@ void *heap_caps_aligned_calloc(size_t alignment, size_t n, size_t size, uint32_t
}
return ptr;
}
IRAM_ATTR void heap_caps_aligned_free(void *ptr)
{
if (ptr == NULL) {
return;
}
heap_t *heap = find_containing_heap(ptr);
assert(heap != NULL && "free() target pointer is outside heap areas");
multi_heap_aligned_free(heap->heap, ptr);
}
}

867
components/heap/heap_tlsf.c Normal file
View File

@ -0,0 +1,867 @@
/*
** Two Level Segregated Fit memory allocator, version 3.1.
** Written by Matthew Conte
** http://tlsf.baisoku.org
**
** Based on the original documentation by Miguel Masmano:
** http://www.gii.upv.es/tlsf/main/docs
**
** This implementation was written to the specification
** of the document, therefore no GPL restrictions apply.
**
** Copyright (c) 2006-2016, Matthew Conte
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the copyright holder nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL MATTHEW CONTE BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "multi_heap_config.h"
#include "multi_heap.h"
#include "multi_heap_internal.h"
#include "heap_tlsf.h"
/*
** Architecture-specific bit manipulation routines.
**
** TLSF achieves O(1) cost for malloc and free operations by limiting
** the search for a free block to a free list of guaranteed size
** adequate to fulfill the request, combined with efficient free list
** queries using bitmasks and architecture-specific bit-manipulation
** routines.
**
** Most modern processors provide instructions to count leading zeroes
** in a word, find the lowest and highest set bit, etc. These
** specific implementations will be used when available, falling back
** to a reasonably efficient generic implementation.
**
** NOTE: TLSF spec relies on ffs/fls returning value 0..31.
** ffs/fls return 1-32 by default, returning 0 for error.
*/
static inline __attribute__((__always_inline__)) int tlsf_ffs(unsigned int word)
{
const unsigned int reverse = word & (~word + 1);
const int bit = 32 - __builtin_clz(reverse);
return bit - 1;
}
static inline __attribute__((__always_inline__)) int tlsf_fls(unsigned int word)
{
const int bit = word ? 32 - __builtin_clz(word) : 0;
return bit - 1;
}
/*
** Set assert macro, if it has not been provided by the user.
*/
#if !defined (tlsf_assert)
#define tlsf_assert assert
#endif
/*
** Static assertion mechanism.
*/
#define _tlsf_glue2(x, y) x ## y
#define _tlsf_glue(x, y) _tlsf_glue2(x, y)
#define tlsf_static_assert(exp) \
typedef char _tlsf_glue(static_assert, __LINE__) [(exp) ? 1 : -1]
/* This code has been tested on 32- and 64-bit (LP/LLP) architectures. */
tlsf_static_assert(sizeof(int) * CHAR_BIT == 32);
tlsf_static_assert(sizeof(size_t) * CHAR_BIT >= 32);
tlsf_static_assert(sizeof(size_t) * CHAR_BIT <= 64);
/* SL_INDEX_COUNT must be <= number of bits in sl_bitmap's storage type. */
tlsf_static_assert(sizeof(unsigned int) * CHAR_BIT >= SL_INDEX_COUNT);
/* Ensure we've properly tuned our sizes. */
tlsf_static_assert(ALIGN_SIZE == SMALL_BLOCK_SIZE / SL_INDEX_COUNT);
static inline __attribute__((__always_inline__)) size_t align_up(size_t x, size_t align)
{
tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two");
return (x + (align - 1)) & ~(align - 1);
}
static inline __attribute__((__always_inline__)) size_t align_down(size_t x, size_t align)
{
tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two");
return x - (x & (align - 1));
}
static inline __attribute__((__always_inline__)) void* align_ptr(const void* ptr, size_t align)
{
const tlsfptr_t aligned =
(tlsf_cast(tlsfptr_t, ptr) + (align - 1)) & ~(align - 1);
tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two");
return tlsf_cast(void*, aligned);
}
/*
** Adjust an allocation size to be aligned to word size, and no smaller
** than internal minimum.
*/
static inline __attribute__((__always_inline__)) size_t adjust_request_size(size_t size, size_t align)
{
size_t adjust = 0;
if (size)
{
const size_t aligned = align_up(size, align);
/* aligned sized must not exceed block_size_max or we'll go out of bounds on sl_bitmap */
if (aligned < block_size_max)
{
adjust = tlsf_max(aligned, block_size_min);
}
}
return adjust;
}
/*
** TLSF utility functions. In most cases, these are direct translations of
** the documentation found in the white paper.
*/
static inline __attribute__((__always_inline__)) void mapping_insert(size_t size, int* fli, int* sli)
{
int fl, sl;
if (size < SMALL_BLOCK_SIZE)
{
/* Store small blocks in first list. */
fl = 0;
sl = tlsf_cast(int, size) >> 2;
}
else
{
fl = tlsf_fls(size);
sl = tlsf_cast(int, size >> (fl - SL_INDEX_COUNT_LOG2)) ^ (1 << SL_INDEX_COUNT_LOG2);
fl -= (FL_INDEX_SHIFT - 1);
}
*fli = fl;
*sli = sl;
}
/* This version rounds up to the next block size (for allocations) */
static inline __attribute__((__always_inline__)) void mapping_search(size_t size, int* fli, int* sli)
{
if (size >= SMALL_BLOCK_SIZE)
{
const size_t round = (1 << (tlsf_fls(size) - SL_INDEX_COUNT_LOG2)) - 1;
size += round;
}
mapping_insert(size, fli, sli);
}
static inline __attribute__((__always_inline__)) block_header_t* search_suitable_block(control_t* control, int* fli, int* sli)
{
int fl = *fli;
int sl = *sli;
/*
** First, search for a block in the list associated with the given
** fl/sl index.
*/
unsigned int sl_map = control->sl_bitmap[fl] & (~0U << sl);
if (!sl_map)
{
/* No block exists. Search in the next largest first-level list. */
const unsigned int fl_map = control->fl_bitmap & (~0U << (fl + 1));
if (!fl_map)
{
/* No free blocks available, memory has been exhausted. */
return 0;
}
fl = tlsf_ffs(fl_map);
*fli = fl;
sl_map = control->sl_bitmap[fl];
}
tlsf_assert(sl_map && "internal error - second level bitmap is null");
sl = tlsf_ffs(sl_map);
*sli = sl;
/* Return the first block in the free list. */
return control->blocks[fl][sl];
}
/* Remove a free block from the free list.*/
static inline __attribute__((__always_inline__)) void remove_free_block(control_t* control, block_header_t* block, int fl, int sl)
{
block_header_t* prev = block->prev_free;
block_header_t* next = block->next_free;
tlsf_assert(prev && "prev_free field can not be null");
tlsf_assert(next && "next_free field can not be null");
next->prev_free = prev;
prev->next_free = next;
/* If this block is the head of the free list, set new head. */
if (control->blocks[fl][sl] == block)
{
control->blocks[fl][sl] = next;
/* If the new head is null, clear the bitmap. */
if (next == &control->block_null)
{
control->sl_bitmap[fl] &= ~(1 << sl);
/* If the second bitmap is now empty, clear the fl bitmap. */
if (!control->sl_bitmap[fl])
{
control->fl_bitmap &= ~(1 << fl);
}
}
}
}
/* Insert a free block into the free block list. */
static inline __attribute__((__always_inline__)) void insert_free_block(control_t* control, block_header_t* block, int fl, int sl)
{
block_header_t* current = control->blocks[fl][sl];
tlsf_assert(current && "free list cannot have a null entry");
tlsf_assert(block && "cannot insert a null entry into the free list");
block->next_free = current;
block->prev_free = &control->block_null;
current->prev_free = block;
tlsf_assert(block_to_ptr(block) == align_ptr(block_to_ptr(block), ALIGN_SIZE)
&& "block not aligned properly");
/*
** Insert the new block at the head of the list, and mark the first-
** and second-level bitmaps appropriately.
*/
control->blocks[fl][sl] = block;
control->fl_bitmap |= (1 << fl);
control->sl_bitmap[fl] |= (1 << sl);
}
/* Remove a given block from the free list. */
static inline __attribute__((__always_inline__)) void block_remove(control_t* control, block_header_t* block)
{
int fl, sl;
mapping_insert(block_size(block), &fl, &sl);
remove_free_block(control, block, fl, sl);
}
/* Insert a given block into the free list. */
static inline __attribute__((__always_inline__)) void block_insert(control_t* control, block_header_t* block)
{
int fl, sl;
mapping_insert(block_size(block), &fl, &sl);
insert_free_block(control, block, fl, sl);
}
static inline __attribute__((__always_inline__)) int block_can_split(block_header_t* block, size_t size)
{
return block_size(block) >= sizeof(block_header_t) + size;
}
/* Split a block into two, the second of which is free. */
static inline __attribute__((__always_inline__)) block_header_t* block_split(block_header_t* block, size_t size)
{
/* Calculate the amount of space left in the remaining block. */
block_header_t* remaining =
offset_to_block(block_to_ptr(block), size - block_header_overhead);
const size_t remain_size = block_size(block) - (size + block_header_overhead);
tlsf_assert(block_to_ptr(remaining) == align_ptr(block_to_ptr(remaining), ALIGN_SIZE)
&& "remaining block not aligned properly");
tlsf_assert(block_size(block) == remain_size + size + block_header_overhead);
block_set_size(remaining, remain_size);
tlsf_assert(block_size(remaining) >= block_size_min && "block split with invalid size");
block_set_size(block, size);
block_mark_as_free(remaining);
return remaining;
}
/* Absorb a free block's storage into an adjacent previous free block. */
static inline __attribute__((__always_inline__)) block_header_t* block_absorb(block_header_t* prev, block_header_t* block)
{
tlsf_assert(!block_is_last(prev) && "previous block can't be last");
/* Note: Leaves flags untouched. */
prev->size += block_size(block) + block_header_overhead;
block_link_next(prev);
#ifdef MULTI_HEAP_POISONING_SLOW
/* next_block header needs to be replaced with a fill pattern */
multi_heap_internal_poison_fill_region(block, sizeof(block_header_t), true /* free */);
#endif
return prev;
}
/* Merge a just-freed block with an adjacent previous free block. */
static inline __attribute__((__always_inline__)) block_header_t* block_merge_prev(control_t* control, block_header_t* block)
{
if (block_is_prev_free(block))
{
block_header_t* prev = block_prev(block);
tlsf_assert(prev && "prev physical block can't be null");
tlsf_assert(block_is_free(prev) && "prev block is not free though marked as such");
block_remove(control, prev);
block = block_absorb(prev, block);
}
return block;
}
/* Merge a just-freed block with an adjacent free block. */
static inline __attribute__((__always_inline__)) block_header_t* block_merge_next(control_t* control, block_header_t* block)
{
block_header_t* next = block_next(block);
tlsf_assert(next && "next physical block can't be null");
if (block_is_free(next))
{
tlsf_assert(!block_is_last(block) && "previous block can't be last");
block_remove(control, next);
block = block_absorb(block, next);
}
return block;
}
/* Trim any trailing block space off the end of a block, return to pool. */
static inline __attribute__((__always_inline__)) void block_trim_free(control_t* control, block_header_t* block, size_t size)
{
tlsf_assert(block_is_free(block) && "block must be free");
if (block_can_split(block, size))
{
block_header_t* remaining_block = block_split(block, size);
block_link_next(block);
block_set_prev_free(remaining_block);
block_insert(control, remaining_block);
}
}
/* Trim any trailing block space off the end of a used block, return to pool. */
static inline __attribute__((__always_inline__)) void block_trim_used(control_t* control, block_header_t* block, size_t size)
{
tlsf_assert(!block_is_free(block) && "block must be used");
if (block_can_split(block, size))
{
/* If the next block is free, we must coalesce. */
block_header_t* remaining_block = block_split(block, size);
block_set_prev_used(remaining_block);
remaining_block = block_merge_next(control, remaining_block);
block_insert(control, remaining_block);
}
}
static inline __attribute__((__always_inline__)) block_header_t* block_trim_free_leading(control_t* control, block_header_t* block, size_t size)
{
block_header_t* remaining_block = block;
if (block_can_split(block, size))
{
/* We want the 2nd block. */
remaining_block = block_split(block, size - block_header_overhead);
block_set_prev_free(remaining_block);
block_link_next(block);
block_insert(control, block);
}
return remaining_block;
}
static inline __attribute__((__always_inline__)) block_header_t* block_locate_free(control_t* control, size_t size)
{
int fl = 0, sl = 0;
block_header_t* block = 0;
if (size)
{
mapping_search(size, &fl, &sl);
/*
** mapping_search can futz with the size, so for excessively large sizes it can sometimes wind up
** with indices that are off the end of the block array.
** So, we protect against that here, since this is the only callsite of mapping_search.
** Note that we don't need to check sl, since it comes from a modulo operation that guarantees it's always in range.
*/
if (fl < FL_INDEX_COUNT)
{
block = search_suitable_block(control, &fl, &sl);
}
}
if (block)
{
tlsf_assert(block_size(block) >= size);
remove_free_block(control, block, fl, sl);
}
return block;
}
static inline __attribute__((__always_inline__)) void* block_prepare_used(control_t* control, block_header_t* block, size_t size)
{
void* p = 0;
if (block)
{
tlsf_assert(size && "size must be non-zero");
block_trim_free(control, block, size);
block_mark_as_used(block);
p = block_to_ptr(block);
}
return p;
}
/* Clear structure and point all empty lists at the null block. */
static void control_construct(control_t* control)
{
int i, j;
control->block_null.next_free = &control->block_null;
control->block_null.prev_free = &control->block_null;
control->fl_bitmap = 0;
for (i = 0; i < FL_INDEX_COUNT; ++i)
{
control->sl_bitmap[i] = 0;
for (j = 0; j < SL_INDEX_COUNT; ++j)
{
control->blocks[i][j] = &control->block_null;
}
}
}
/*
** Debugging utilities.
*/
typedef struct integrity_t
{
int prev_status;
int status;
} integrity_t;
#define tlsf_insist(x) { tlsf_assert(x); if (!(x)) { status--; } }
static void integrity_walker(void* ptr, size_t size, int used, void* user)
{
block_header_t* block = block_from_ptr(ptr);
integrity_t* integ = tlsf_cast(integrity_t*, user);
const int this_prev_status = block_is_prev_free(block) ? 1 : 0;
const int this_status = block_is_free(block) ? 1 : 0;
const size_t this_block_size = block_size(block);
int status = 0;
(void)used;
tlsf_insist(integ->prev_status == this_prev_status && "prev status incorrect");
tlsf_insist(size == this_block_size && "block size incorrect");
integ->prev_status = this_status;
integ->status += status;
}
int tlsf_check(tlsf_t tlsf)
{
int i, j;
control_t* control = tlsf_cast(control_t*, tlsf);
int status = 0;
/* Check that the free lists and bitmaps are accurate. */
for (i = 0; i < FL_INDEX_COUNT; ++i)
{
for (j = 0; j < SL_INDEX_COUNT; ++j)
{
const int fl_map = control->fl_bitmap & (1 << i);
const int sl_list = control->sl_bitmap[i];
const int sl_map = sl_list & (1 << j);
const block_header_t* block = control->blocks[i][j];
/* Check that first- and second-level lists agree. */
if (!fl_map)
{
tlsf_insist(!sl_map && "second-level map must be null");
}
if (!sl_map)
{
tlsf_insist(block == &control->block_null && "block list must be null");
continue;
}
/* Check that there is at least one free block. */
tlsf_insist(sl_list && "no free blocks in second-level map");
tlsf_insist(block != &control->block_null && "block should not be null");
while (block != &control->block_null)
{
int fli, sli;
tlsf_insist(block_is_free(block) && "block should be free");
tlsf_insist(!block_is_prev_free(block) && "blocks should have coalesced");
tlsf_insist(!block_is_free(block_next(block)) && "blocks should have coalesced");
tlsf_insist(block_is_prev_free(block_next(block)) && "block should be free");
tlsf_insist(block_size(block) >= block_size_min && "block not minimum size");
mapping_insert(block_size(block), &fli, &sli);
tlsf_insist(fli == i && sli == j && "block size indexed in wrong list");
block = block->next_free;
}
}
}
return status;
}
#undef tlsf_insist
static void default_walker(void* ptr, size_t size, int used, void* user)
{
(void)user;
printf("\t%p %s size: %x (%p)\n", ptr, used ? "used" : "free", (unsigned int)size, block_from_ptr(ptr));
}
void tlsf_walk_pool(pool_t pool, tlsf_walker walker, void* user)
{
tlsf_walker pool_walker = walker ? walker : default_walker;
block_header_t* block =
offset_to_block(pool, -(int)block_header_overhead);
while (block && !block_is_last(block))
{
pool_walker(
block_to_ptr(block),
block_size(block),
!block_is_free(block),
user);
block = block_next(block);
}
}
size_t tlsf_block_size(void* ptr)
{
size_t size = 0;
if (ptr)
{
const block_header_t* block = block_from_ptr(ptr);
size = block_size(block);
}
return size;
}
int tlsf_check_pool(pool_t pool)
{
/* Check that the blocks are physically correct. */
integrity_t integ = { 0, 0 };
tlsf_walk_pool(pool, integrity_walker, &integ);
return integ.status;
}
/*
** Size of the TLSF structures in a given memory block passed to
** tlsf_create, equal to the size of a control_t
*/
size_t tlsf_size(void)
{
return sizeof(control_t);
}
size_t tlsf_align_size(void)
{
return ALIGN_SIZE;
}
size_t tlsf_block_size_min(void)
{
return block_size_min;
}
size_t tlsf_block_size_max(void)
{
return block_size_max;
}
/*
** Overhead of the TLSF structures in a given memory block passed to
** tlsf_add_pool, equal to the overhead of a free block and the
** sentinel block.
*/
size_t tlsf_pool_overhead(void)
{
return 2 * block_header_overhead;
}
size_t tlsf_alloc_overhead(void)
{
return block_header_overhead;
}
pool_t tlsf_add_pool(tlsf_t tlsf, void* mem, size_t bytes)
{
block_header_t* block;
block_header_t* next;
const size_t pool_overhead = tlsf_pool_overhead();
const size_t pool_bytes = align_down(bytes - pool_overhead, ALIGN_SIZE);
if (((ptrdiff_t)mem % ALIGN_SIZE) != 0)
{
printf("tlsf_add_pool: Memory must be aligned by %u bytes.\n",
(unsigned int)ALIGN_SIZE);
return 0;
}
if (pool_bytes < block_size_min || pool_bytes > block_size_max)
{
#if defined (TLSF_64BIT)
printf("tlsf_add_pool: Memory size must be between 0x%x and 0x%x00 bytes.\n",
(unsigned int)(pool_overhead + block_size_min),
(unsigned int)((pool_overhead + block_size_max) / 256));
#else
printf("tlsf_add_pool: Memory size must be between %u and %u bytes.\n",
(unsigned int)(pool_overhead + block_size_min),
(unsigned int)(pool_overhead + block_size_max));
#endif
return 0;
}
/*
** Create the main free block. Offset the start of the block slightly
** so that the prev_phys_block field falls outside of the pool -
** it will never be used.
*/
block = offset_to_block(mem, -(tlsfptr_t)block_header_overhead);
block_set_size(block, pool_bytes);
block_set_free(block);
block_set_prev_used(block);
block_insert(tlsf_cast(control_t*, tlsf), block);
/* Split the block to create a zero-size sentinel block. */
next = block_link_next(block);
block_set_size(next, 0);
block_set_used(next);
block_set_prev_free(next);
return mem;
}
void tlsf_remove_pool(tlsf_t tlsf, pool_t pool)
{
control_t* control = tlsf_cast(control_t*, tlsf);
block_header_t* block = offset_to_block(pool, -(int)block_header_overhead);
int fl = 0, sl = 0;
tlsf_assert(block_is_free(block) && "block should be free");
tlsf_assert(!block_is_free(block_next(block)) && "next block should not be free");
tlsf_assert(block_size(block_next(block)) == 0 && "next block size should be zero");
mapping_insert(block_size(block), &fl, &sl);
remove_free_block(control, block, fl, sl);
}
/*
** TLSF main interface.
*/
tlsf_t tlsf_create(void* mem)
{
#if _DEBUG
if (test_ffs_fls())
{
return 0;
}
#endif
if (((tlsfptr_t)mem % ALIGN_SIZE) != 0)
{
printf("tlsf_create: Memory must be aligned to %u bytes.\n",
(unsigned int)ALIGN_SIZE);
return 0;
}
control_construct(tlsf_cast(control_t*, mem));
return tlsf_cast(tlsf_t, mem);
}
pool_t tlsf_get_pool(tlsf_t tlsf)
{
return tlsf_cast(pool_t, (char*)tlsf + tlsf_size());
}
tlsf_t tlsf_create_with_pool(void* mem, size_t bytes)
{
tlsf_t tlsf = tlsf_create(mem);
tlsf_add_pool(tlsf, (char*)mem + tlsf_size(), bytes - tlsf_size());
return tlsf;
}
void* tlsf_malloc(tlsf_t tlsf, size_t size)
{
control_t* control = tlsf_cast(control_t*, tlsf);
size_t adjust = adjust_request_size(size, ALIGN_SIZE);
block_header_t* block = block_locate_free(control, adjust);
return block_prepare_used(control, block, adjust);
}
void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t size)
{
control_t* control = tlsf_cast(control_t*, tlsf);
const size_t adjust = adjust_request_size(size, ALIGN_SIZE);
/*
** We must allocate an additional minimum block size bytes so that if
** our free block will leave an alignment gap which is smaller, we can
** trim a leading free block and release it back to the pool. We must
** do this because the previous physical block is in use, therefore
** the prev_phys_block field is not valid, and we can't simply adjust
** the size of that block.
*/
const size_t gap_minimum = sizeof(block_header_t);
const size_t size_with_gap = adjust_request_size(adjust + align + gap_minimum, align);
/*
** If alignment is less than or equals base alignment, we're done.
** If we requested 0 bytes, return null, as tlsf_malloc(0) does.
*/
const size_t aligned_size = (adjust && align > ALIGN_SIZE) ? size_with_gap : adjust;
block_header_t* block = block_locate_free(control, aligned_size);
/* This can't be a static assert. */
tlsf_assert(sizeof(block_header_t) == block_size_min + block_header_overhead);
if (block)
{
void* ptr = block_to_ptr(block);
void* aligned = align_ptr(ptr, align);
size_t gap = tlsf_cast(size_t,
tlsf_cast(tlsfptr_t, aligned) - tlsf_cast(tlsfptr_t, ptr));
/* If gap size is too small, offset to next aligned boundary. */
if (gap && gap < gap_minimum)
{
const size_t gap_remain = gap_minimum - gap;
const size_t offset = tlsf_max(gap_remain, align);
const void* next_aligned = tlsf_cast(void*,
tlsf_cast(tlsfptr_t, aligned) + offset);
aligned = align_ptr(next_aligned, align);
gap = tlsf_cast(size_t,
tlsf_cast(tlsfptr_t, aligned) - tlsf_cast(tlsfptr_t, ptr));
}
if (gap)
{
tlsf_assert(gap >= gap_minimum && "gap size too small");
block = block_trim_free_leading(control, block, gap);
}
}
return block_prepare_used(control, block, adjust);
}
void tlsf_free(tlsf_t tlsf, void* ptr)
{
/* Don't attempt to free a NULL pointer. */
if (ptr)
{
control_t* control = tlsf_cast(control_t*, tlsf);
block_header_t* block = block_from_ptr(ptr);
tlsf_assert(!block_is_free(block) && "block already marked as free");
block_mark_as_free(block);
block = block_merge_prev(control, block);
block = block_merge_next(control, block);
block_insert(control, block);
}
}
/*
** The TLSF block information provides us with enough information to
** provide a reasonably intelligent implementation of realloc, growing or
** shrinking the currently allocated block as required.
**
** This routine handles the somewhat esoteric edge cases of realloc:
** - a non-zero size with a null pointer will behave like malloc
** - a zero size with a non-null pointer will behave like free
** - a request that cannot be satisfied will leave the original buffer
** untouched
** - an extended buffer size will leave the newly-allocated area with
** contents undefined
*/
void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size)
{
control_t* control = tlsf_cast(control_t*, tlsf);
void* p = 0;
/* Zero-size requests are treated as free. */
if (ptr && size == 0)
{
tlsf_free(tlsf, ptr);
}
/* Requests with NULL pointers are treated as malloc. */
else if (!ptr)
{
p = tlsf_malloc(tlsf, size);
}
else
{
block_header_t* block = block_from_ptr(ptr);
block_header_t* next = block_next(block);
const size_t cursize = block_size(block);
const size_t combined = cursize + block_size(next) + block_header_overhead;
const size_t adjust = adjust_request_size(size, ALIGN_SIZE);
tlsf_assert(!block_is_free(block) && "block already marked as free");
/*
** If the next block is used, or when combined with the current
** block, does not offer enough space, we must reallocate and copy.
*/
if (adjust > cursize && (!block_is_free(next) || adjust > combined))
{
p = tlsf_malloc(tlsf, size);
if (p)
{
const size_t minsize = tlsf_min(cursize, size);
memcpy(p, ptr, minsize);
tlsf_free(tlsf, ptr);
}
}
else
{
/* Do we need to expand to the next block? */
if (adjust > cursize)
{
block_merge_next(control, block);
block_mark_as_used(block);
}
/* Trim the resulting block and return the original pointer. */
block_trim_used(control, block, adjust);
p = ptr;
}
}
return p;
}

133
components/heap/heap_tlsf.h Normal file
View File

@ -0,0 +1,133 @@
/*
** Two Level Segregated Fit memory allocator, version 3.1.
** Written by Matthew Conte
** http://tlsf.baisoku.org
**
** Based on the original documentation by Miguel Masmano:
** http://www.gii.upv.es/tlsf/main/docs
**
** This implementation was written to the specification
** of the document, therefore no GPL restrictions apply.
**
** Copyright (c) 2006-2016, Matthew Conte
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the copyright holder nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL MATTHEW CONTE BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <assert.h>
#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include "heap_tlsf_config.h"
#if defined(__cplusplus)
extern "C" {
#endif
/*
** Cast and min/max macros.
*/
#define tlsf_cast(t, exp) ((t) (exp))
#define tlsf_min(a, b) ((a) < (b) ? (a) : (b))
#define tlsf_max(a, b) ((a) > (b) ? (a) : (b))
/* A type used for casting when doing pointer arithmetic. */
typedef ptrdiff_t tlsfptr_t;
typedef struct block_header_t
{
/* Points to the previous physical block. */
struct block_header_t* prev_phys_block;
/* The size of this block, excluding the block header. */
size_t size;
/* Next and previous free blocks. */
struct block_header_t* next_free;
struct block_header_t* prev_free;
} block_header_t;
/* The TLSF control structure. */
typedef struct control_t
{
/* Empty lists point at this block to indicate they are free. */
block_header_t block_null;
/* Bitmaps for free lists. */
unsigned int fl_bitmap;
unsigned int sl_bitmap[FL_INDEX_COUNT];
/* Head of free lists. */
block_header_t* blocks[FL_INDEX_COUNT][SL_INDEX_COUNT];
} control_t;
#include "heap_tlsf_block_functions.h"
/* tlsf_t: a TLSF structure. Can contain 1 to N pools. */
/* pool_t: a block of memory that TLSF can manage. */
typedef void* tlsf_t;
typedef void* pool_t;
/* Create/destroy a memory pool. */
tlsf_t tlsf_create(void* mem);
tlsf_t tlsf_create_with_pool(void* mem, size_t bytes);
pool_t tlsf_get_pool(tlsf_t tlsf);
/* Add/remove memory pools. */
pool_t tlsf_add_pool(tlsf_t tlsf, void* mem, size_t bytes);
void tlsf_remove_pool(tlsf_t tlsf, pool_t pool);
/* malloc/memalign/realloc/free replacements. */
void* tlsf_malloc(tlsf_t tlsf, size_t size);
void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t size);
void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size);
void tlsf_free(tlsf_t tlsf, void* ptr);
/* Returns internal block size, not original request size */
size_t tlsf_block_size(void* ptr);
/* Overheads/limits of internal structures. */
size_t tlsf_size(void);
size_t tlsf_align_size(void);
size_t tlsf_block_size_min(void);
size_t tlsf_block_size_max(void);
size_t tlsf_pool_overhead(void);
size_t tlsf_alloc_overhead(void);
/* Debugging. */
typedef void (*tlsf_walker)(void* ptr, size_t size, int used, void* user);
void tlsf_walk_pool(pool_t pool, tlsf_walker walker, void* user);
/* Returns nonzero if any internal consistency check fails. */
int tlsf_check(tlsf_t tlsf);
int tlsf_check_pool(pool_t pool);
#if defined(__cplusplus)
};
#endif

View File

@ -0,0 +1,172 @@
/*
** Two Level Segregated Fit memory allocator, version 3.1.
** Written by Matthew Conte
** http://tlsf.baisoku.org
**
** Based on the original documentation by Miguel Masmano:
** http://www.gii.upv.es/tlsf/main/docs
**
** This implementation was written to the specification
** of the document, therefore no GPL restrictions apply.
**
** Copyright (c) 2006-2016, Matthew Conte
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the copyright holder nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL MATTHEW CONTE BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
/*
** Data structures and associated constants.
*/
/*
** Since block sizes are always at least a multiple of 4, the two least
** significant bits of the size field are used to store the block status:
** - bit 0: whether block is busy or free
** - bit 1: whether previous block is busy or free
*/
#define block_header_free_bit (1 << 0)
#define block_header_prev_free_bit (1 << 1)
/*
** The size of the block header exposed to used blocks is the size field.
** The prev_phys_block field is stored *inside* the previous free block.
*/
#define block_header_overhead (sizeof(size_t))
/* User data starts directly after the size field in a used block. */
#define block_start_offset (offsetof(block_header_t, size) + sizeof(size_t))
/*
** A free block must be large enough to store its header minus the size of
** the prev_phys_block field, and no larger than the number of addressable
** bits for FL_INDEX.
*/
#define block_size_min (sizeof(block_header_t) - sizeof(block_header_t*))
#define block_size_max (tlsf_cast(size_t, 1) << FL_INDEX_MAX)
/*
** block_header_t member functions.
*/
static inline __attribute__((__always_inline__)) size_t block_size(const block_header_t* block)
{
return block->size & ~(block_header_free_bit | block_header_prev_free_bit);
}
static inline __attribute__((__always_inline__)) void block_set_size(block_header_t* block, size_t size)
{
const size_t oldsize = block->size;
block->size = size | (oldsize & (block_header_free_bit | block_header_prev_free_bit));
}
static inline __attribute__((__always_inline__)) int block_is_last(const block_header_t* block)
{
return block_size(block) == 0;
}
static inline __attribute__((__always_inline__)) int block_is_free(const block_header_t* block)
{
return tlsf_cast(int, block->size & block_header_free_bit);
}
static inline __attribute__((__always_inline__)) void block_set_free(block_header_t* block)
{
block->size |= block_header_free_bit;
}
static inline __attribute__((__always_inline__)) void block_set_used(block_header_t* block)
{
block->size &= ~block_header_free_bit;
}
static inline __attribute__((__always_inline__)) int block_is_prev_free(const block_header_t* block)
{
return tlsf_cast(int, block->size & block_header_prev_free_bit);
}
static inline __attribute__((__always_inline__)) void block_set_prev_free(block_header_t* block)
{
block->size |= block_header_prev_free_bit;
}
static inline __attribute__((__always_inline__)) void block_set_prev_used(block_header_t* block)
{
block->size &= ~block_header_prev_free_bit;
}
static inline __attribute__((__always_inline__)) block_header_t* block_from_ptr(const void* ptr)
{
return tlsf_cast(block_header_t*,
tlsf_cast(unsigned char*, ptr) - block_start_offset);
}
static inline __attribute__((__always_inline__)) void* block_to_ptr(const block_header_t* block)
{
return tlsf_cast(void*,
tlsf_cast(unsigned char*, block) + block_start_offset);
}
/* Return location of next block after block of given size. */
static inline __attribute__((__always_inline__)) block_header_t* offset_to_block(const void* ptr, size_t size)
{
return tlsf_cast(block_header_t*, tlsf_cast(tlsfptr_t, ptr) + size);
}
/* Return location of previous block. */
static inline __attribute__((__always_inline__)) block_header_t* block_prev(const block_header_t* block)
{
return block->prev_phys_block;
}
/* Return location of next existing block. */
static inline __attribute__((__always_inline__)) block_header_t* block_next(const block_header_t* block)
{
block_header_t* next = offset_to_block(block_to_ptr(block),
block_size(block) - block_header_overhead);
return next;
}
/* Link a new block with its physical neighbor, return the neighbor. */
static inline __attribute__((__always_inline__)) block_header_t* block_link_next(block_header_t* block)
{
block_header_t* next = block_next(block);
next->prev_phys_block = block;
return next;
}
static inline __attribute__((__always_inline__)) void block_mark_as_free(block_header_t* block)
{
/* Link the block to the next block, first. */
block_header_t* next = block_link_next(block);
block_set_prev_free(next);
block_set_free(block);
}
static inline __attribute__((__always_inline__)) void block_mark_as_used(block_header_t* block)
{
block_header_t* next = block_next(block);
block_set_prev_used(next);
block_set_used(block);
}

View File

@ -0,0 +1,73 @@
/*
** Two Level Segregated Fit memory allocator, version 3.1.
** Written by Matthew Conte
** http://tlsf.baisoku.org
**
** Based on the original documentation by Miguel Masmano:
** http://www.gii.upv.es/tlsf/main/docs
**
** This implementation was written to the specification
** of the document, therefore no GPL restrictions apply.
**
** Copyright (c) 2006-2016, Matthew Conte
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the copyright holder nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL MATTHEW CONTE BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
enum tlsf_config
{
/* log2 of number of linear subdivisions of block sizes. Larger
** values require more memory in the control structure. Values of
** 4 or 5 are typical.
*/
SL_INDEX_COUNT_LOG2 = 5,
/* All allocation sizes and addresses are aligned to 4 bytes. */
ALIGN_SIZE_LOG2 = 2,
ALIGN_SIZE = (1 << ALIGN_SIZE_LOG2),
/*
** We support allocations of sizes up to (1 << FL_INDEX_MAX) bits.
** However, because we linearly subdivide the second-level lists, and
** our minimum size granularity is 4 bytes, it doesn't make sense to
** create first-level lists for sizes smaller than SL_INDEX_COUNT * 4,
** or (1 << (SL_INDEX_COUNT_LOG2 + 2)) bytes, as there we will be
** trying to split size ranges into more slots than we have available.
** Instead, we calculate the minimum threshold size, and place all
** blocks below that size into the 0th first-level list.
*/
/* Tunning the first level, we can reduce TLSF pool overhead
* in exchange of manage a pool smaller than 4GB
*/
FL_INDEX_MAX = 30,
SL_INDEX_COUNT = (1 << SL_INDEX_COUNT_LOG2),
FL_INDEX_SHIFT = (SL_INDEX_COUNT_LOG2 + ALIGN_SIZE_LOG2),
FL_INDEX_COUNT = (FL_INDEX_MAX - FL_INDEX_SHIFT + 1),
SMALL_BLOCK_SIZE = (1 << FL_INDEX_SHIFT),
};

View File

@ -116,12 +116,18 @@ void *heap_caps_realloc( void *ptr, size_t size, int caps);
*
* @return A pointer to the memory allocated on success, NULL on failure
*
* @note Any memory allocated with heaps_caps_aligned_alloc() MUST
* be freed with heap_caps_aligned_free() and CANNOT be passed to free()
*
*/
void *heap_caps_aligned_alloc(size_t alignment, size_t size, int caps);
/**
* @brief Used to deallocate memory previously allocated with heap_caps_aligned_alloc
*
* @param ptr Pointer to the memory allocated
* @note This function is deprecated, plase consider using heap_caps_free() instead
*/
void __attribute__((deprecated)) heap_caps_aligned_free(void *ptr);
/**
* @brief Allocate a aligned chunk of memory which has the given capabilities. The initialized value in the memory is set to zero.
*
@ -134,20 +140,9 @@ void *heap_caps_aligned_alloc(size_t alignment, size_t size, int caps);
*
* @return A pointer to the memory allocated on success, NULL on failure
*
* @note Any memory allocated with heap_caps_aligned_calloc() MUST
* be freed with heap_caps_aligned_free() and CANNOT be passed to free()
*/
void *heap_caps_aligned_calloc(size_t alignment, size_t n, size_t size, uint32_t caps);
/**
* @brief Used to deallocate memory previously allocated with heap_caps_aligned_alloc
*
* @param ptr Pointer to the memory allocated
* @note This function is aimed to deallocate only memory allocated with
* heap_caps_aligned_alloc, memory allocated with heap_caps_malloc
* MUST not be passed to this function
*/
void heap_caps_aligned_free(void *ptr);
/**
* @brief Allocate a chunk of memory which has the given capabilities. The initialized value in the memory is set to zero.

View File

@ -55,9 +55,9 @@ void *multi_heap_malloc(multi_heap_handle_t heap, size_t size);
*
* @param heap Handle to a registered heap.
* @param p NULL, or a pointer previously returned from multi_heap_aligned_alloc() for the same heap.
* @note This function is deprecated, consider using multi_heap_free() instead
*/
void multi_heap_aligned_free(multi_heap_handle_t heap, void *p);
void __attribute__((deprecated)) multi_heap_aligned_free(multi_heap_handle_t heap, void *p);
/** @brief free() a buffer in a given heap.
*

View File

@ -1,5 +1,6 @@
[mapping:heap]
archive: libheap.a
entries:
heap_tlsf (noflash)
multi_heap (noflash)
multi_heap_poisoning (noflash)

View File

@ -18,6 +18,8 @@
#include <string.h>
#include <stddef.h>
#include <stdio.h>
#include <sys/cdefs.h>
#include "heap_tlsf.h"
#include <multi_heap.h>
#include "multi_heap_internal.h"
@ -36,11 +38,11 @@ void *multi_heap_malloc(multi_heap_handle_t heap, size_t size)
void *multi_heap_aligned_alloc(multi_heap_handle_t heap, size_t size, size_t alignment)
__attribute__((alias("multi_heap_aligned_alloc_impl")));
void multi_heap_free(multi_heap_handle_t heap, void *p)
void multi_heap_aligned_free(multi_heap_handle_t heap, void *p)
__attribute__((alias("multi_heap_free_impl")));
void multi_heap_aligned_free(multi_heap_handle_t heap, void *p)
__attribute__((alias("multi_heap_aligned_free_impl")));
void multi_heap_free(multi_heap_handle_t heap, void *p)
__attribute__((alias("multi_heap_free_impl")));
void *multi_heap_realloc(multi_heap_handle_t heap, void *p, size_t size)
__attribute__((alias("multi_heap_realloc_impl")));
@ -74,302 +76,70 @@ void *multi_heap_get_block_owner(multi_heap_block_handle_t block)
#define ALIGN_UP(X) ALIGN((X)+sizeof(void *)-1)
#define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
struct heap_block;
/* Block in the heap
Heap implementation uses two single linked lists, a block list (all blocks) and a free list (free blocks).
'header' holds a pointer to the next block (used or free) ORed with a free flag (the LSB of the pointer.) is_free() and get_next_block() utility functions allow typed access to these values.
'next_free' is valid if the block is free and is a pointer to the next block in the free list.
*/
typedef struct heap_block {
intptr_t header; /* Encodes next block in heap (used or unused) and also free/used flag */
union {
uint8_t data[1]; /* First byte of data, valid if block is used. Actual size of data is 'block_data_size(block)' */
struct heap_block *next_free; /* Pointer to next free block, valid if block is free */
};
} heap_block_t;
/* These masks apply to the 'header' field of heap_block_t */
#define BLOCK_FREE_FLAG 0x1 /* If set, this block is free & next_free pointer is valid */
#define NEXT_BLOCK_MASK (~3) /* AND header with this mask to get pointer to next block (free or used) */
/* Metadata header for the heap, stored at the beginning of heap space.
'first_block' is a "fake" first block, minimum length, used to provide a pointer to the first used & free block in
the heap. This block is never allocated or merged into an adjacent block.
'last_block' is a pointer to a final free block of length 0, which is added at the end of the heap when it is
registered. This block is also never allocated or merged into an adjacent block.
*/
typedef struct multi_heap_info {
void *lock;
size_t free_bytes;
size_t minimum_free_bytes;
heap_block_t *last_block;
heap_block_t first_block; /* initial 'free block', never allocated */
size_t pool_size;
tlsf_t heap_data;
} heap_t;
/* Given a pointer to the 'data' field of a block (ie the previous malloc/realloc result), return a pointer to the
containing block.
*/
static inline heap_block_t *get_block(const void *data_ptr)
{
return (heap_block_t *)((char *)data_ptr - offsetof(heap_block_t, data));
}
/* Return the next sequential block in the heap.
*/
static inline heap_block_t *get_next_block(const heap_block_t *block)
{
intptr_t next = block->header & NEXT_BLOCK_MASK;
if (next == 0) {
return NULL; /* last_block */
}
assert(next > (intptr_t)block);
return (heap_block_t *)next;
}
/* Return true if this block is free. */
static inline bool is_free(const heap_block_t *block)
static inline bool is_free(const block_header_t *block)
{
return block->header & BLOCK_FREE_FLAG;
}
/* Return true if this block is the first in the heap */
static inline bool is_first_block(const heap_t *heap, const heap_block_t *block)
{
return (block == &heap->first_block);
}
/* Return true if this block is the last_block in the heap
(the only block with no next pointer) */
static inline bool is_last_block(const heap_block_t *block)
{
return (block->header & NEXT_BLOCK_MASK) == 0;
return ((block->size & 0x01) != 0);
}
/* Data size of the block (excludes this block's header) */
static inline size_t block_data_size(const heap_block_t *block)
static inline size_t block_data_size(const block_header_t *block)
{
intptr_t next = (intptr_t)block->header & NEXT_BLOCK_MASK;
intptr_t this = (intptr_t)block;
if (next == 0) {
return 0; /* this is the last block in the heap */
}
return next - this - sizeof(block->header);
return (block->size & ~0x03);
}
/* Check a block is valid for this heap. Used to verify parameters. */
static void assert_valid_block(const heap_t *heap, const heap_block_t *block)
static void assert_valid_block(const heap_t *heap, const block_header_t *block)
{
MULTI_HEAP_ASSERT(block >= &heap->first_block && block <= heap->last_block,
block); // block not in heap
if (heap < (const heap_t *)heap->last_block) {
const heap_block_t *next = get_next_block(block);
MULTI_HEAP_ASSERT(next >= &heap->first_block && next <= heap->last_block, block); // Next block not in heap
if (is_free(block)) {
// Check block->next_free is valid
MULTI_HEAP_ASSERT(block->next_free >= &heap->first_block && block->next_free <= heap->last_block, &block->next_free);
}
}
}
pool_t pool = tlsf_get_pool(heap->heap_data);
void *ptr = block_to_ptr(block);
/* Get the first free block before 'block' in the heap. 'block' can be a free block or in use.
Result is always the closest free block to 'block' in the heap, that is located before 'block'. There may be multiple
allocated blocks between the result and 'block'.
If 'block' is free, the result's 'next_free' pointer will already point to 'block'.
Result will never be NULL, but it may be the header block heap->first_block.
*/
static heap_block_t *get_prev_free_block(heap_t *heap, const heap_block_t *block)
{
assert(!is_first_block(heap, block)); /* can't look for a block before first_block */
for (heap_block_t *b = &heap->first_block; b != NULL && b < block; b = b->next_free) {
MULTI_HEAP_ASSERT(is_free(b), b); // Block should be free
if (b->next_free == NULL || b->next_free >= block) {
if (is_free(block)) {
/* if block is on freelist, 'b' should be the item before it. */
MULTI_HEAP_ASSERT(b->next_free == block, &b->next_free);
}
return b; /* b is the last free block before 'block' */
}
}
abort(); /* There should always be a previous free block, even if it's heap->first_block */
}
/* Merge some block 'a' into the following block 'b'.
If both blocks are free, resulting block is marked free.
If only one block is free, resulting block is marked in use. No data is moved.
This operation may fail if block 'a' is the first block or 'b' is the last block,
the caller should check block_data_size() to know if anything happened here or not.
*/
static heap_block_t *merge_adjacent(heap_t *heap, heap_block_t *a, heap_block_t *b)
{
assert(a < b);
/* Can't merge header blocks, just return the non-header block as-is */
if (is_last_block(b)) {
return a;
}
if (is_first_block(heap, a)) {
return b;
}
MULTI_HEAP_ASSERT(get_next_block(a) == b, a); // Blocks should be in order
bool free = is_free(a) && is_free(b); /* merging two free blocks creates a free block */
if (!free && (is_free(a) || is_free(b))) {
/* only one of these blocks is free, so resulting block will be a used block.
means we need to take the free block out of the free list
*/
heap_block_t *free_block = is_free(a) ? a : b;
heap_block_t *prev_free = get_prev_free_block(heap, free_block);
MULTI_HEAP_ASSERT(free_block->next_free > prev_free, &free_block->next_free); // Next free block should be after prev one
prev_free->next_free = free_block->next_free;
heap->free_bytes -= block_data_size(free_block);
}
a->header = b->header & NEXT_BLOCK_MASK;
MULTI_HEAP_ASSERT(a->header != 0, a);
if (free) {
a->header |= BLOCK_FREE_FLAG;
if (b->next_free != NULL) {
MULTI_HEAP_ASSERT(b->next_free > a, &b->next_free);
MULTI_HEAP_ASSERT(b->next_free > b, &b->next_free);
}
a->next_free = b->next_free;
/* b's header can be put into the pool of free bytes */
heap->free_bytes += sizeof(a->header);
}
#ifdef MULTI_HEAP_POISONING_SLOW
/* b's former block header needs to be replaced with a fill pattern */
multi_heap_internal_poison_fill_region(b, sizeof(heap_block_t), free);
#endif
return a;
}
/* Split a block so it can hold at least 'size' bytes of data, making any spare
space into a new free block.
'block' should be marked in-use when this function is called (implementation detail, this function
doesn't set the next_free pointer).
'prev_free_block' is the free block before 'block', if already known. Can be NULL if not yet known.
(This is a performance optimisation to avoid walking the freelist twice when possible.)
*/
static void split_if_necessary(heap_t *heap, heap_block_t *block, size_t size, heap_block_t *prev_free_block)
{
const size_t block_size = block_data_size(block);
MULTI_HEAP_ASSERT(!is_free(block), block); // split block shouldn't be free
MULTI_HEAP_ASSERT(size <= block_size, block); // size should be valid
size = ALIGN_UP(size);
/* can't split the head or tail block */
assert(!is_first_block(heap, block));
assert(!is_last_block(block));
heap_block_t *new_block = (heap_block_t *)(block->data + size);
heap_block_t *next_block = get_next_block(block);
if (is_free(next_block) && !is_last_block(next_block)) {
/* The next block is free, just extend it upwards. */
new_block->header = next_block->header;
new_block->next_free = next_block->next_free;
if (prev_free_block == NULL) {
prev_free_block = get_prev_free_block(heap, block);
}
/* prev_free_block should point to the next block (which we found to be free). */
MULTI_HEAP_ASSERT(prev_free_block->next_free == next_block,
&prev_free_block->next_free); // free blocks should be in order
/* Note: We have not introduced a new block header, hence the simple math. */
heap->free_bytes += block_size - size;
#ifdef MULTI_HEAP_POISONING_SLOW
/* next_block header needs to be replaced with a fill pattern */
multi_heap_internal_poison_fill_region(next_block, sizeof(heap_block_t), true /* free */);
#endif
} else {
/* Insert a free block between the current and the next one. */
if (block_data_size(block) < size + sizeof(heap_block_t)) {
/* Can't split 'block' if we're not going to get a usable free block afterwards */
return;
}
if (prev_free_block == NULL) {
prev_free_block = get_prev_free_block(heap, block);
}
new_block->header = block->header | BLOCK_FREE_FLAG;
new_block->next_free = prev_free_block->next_free;
/* prev_free_block should point to a free block after new_block */
MULTI_HEAP_ASSERT(prev_free_block->next_free > new_block,
&prev_free_block->next_free); // free blocks should be in order
heap->free_bytes += block_data_size(new_block);
}
block->header = (intptr_t)new_block;
prev_free_block->next_free = new_block;
MULTI_HEAP_ASSERT((ptr >= pool) &&
(ptr < pool + heap->pool_size),
(uintptr_t)ptr);
}
void *multi_heap_get_block_address_impl(multi_heap_block_handle_t block)
{
return ((char *)block + offsetof(heap_block_t, data));
void *ptr = block_to_ptr(block);
return (ptr);
}
size_t multi_heap_get_allocated_size_impl(multi_heap_handle_t heap, void *p)
{
heap_block_t *pb = get_block(p);
assert_valid_block(heap, pb);
MULTI_HEAP_ASSERT(!is_free(pb), pb); // block shouldn't be free
return block_data_size(pb);
return tlsf_block_size(p);
}
multi_heap_handle_t multi_heap_register_impl(void *start_ptr, size_t size)
{
uintptr_t start = ALIGN_UP((uintptr_t)start_ptr);
uintptr_t end = ALIGN((uintptr_t)start_ptr + size);
heap_t *heap = (heap_t *)start;
size = end - start;
if (end < start || size < sizeof(heap_t) + 2*sizeof(heap_block_t)) {
return NULL; /* 'size' is too small to fit a heap here */
assert(start_ptr);
if(size < (tlsf_size() + tlsf_block_size_min() + sizeof(heap_t))) {
//Region too small to be a heap.
return NULL;
}
heap->lock = NULL;
heap->last_block = (heap_block_t *)(end - sizeof(heap_block_t));
/* first 'real' (allocatable) free block goes after the heap structure */
heap_block_t *first_free_block = (heap_block_t *)(start + sizeof(heap_t));
first_free_block->header = (intptr_t)heap->last_block | BLOCK_FREE_FLAG;
first_free_block->next_free = heap->last_block;
heap_t *result = (heap_t *)start_ptr;
size -= sizeof(heap_t);
/* last block is 'free' but has a NULL next pointer */
heap->last_block->header = BLOCK_FREE_FLAG;
heap->last_block->next_free = NULL;
result->heap_data = tlsf_create_with_pool(start_ptr + sizeof(heap_t), size);
if(!result->heap_data) {
return NULL;
}
/* first block also 'free' but has legitimate length,
malloc will never allocate into this block. */
heap->first_block.header = (intptr_t)first_free_block | BLOCK_FREE_FLAG;
heap->first_block.next_free = first_free_block;
/* free bytes is:
- total bytes in heap
- minus heap_t header at top (includes heap->first_block)
- minus header of first_free_block
- minus whole block at heap->last_block
*/
heap->free_bytes = size - sizeof(heap_t) - sizeof(first_free_block->header) - sizeof(heap_block_t);
heap->minimum_free_bytes = heap->free_bytes;
return heap;
result->lock = NULL;
result->free_bytes = size - tlsf_size();
result->pool_size = size;
result->minimum_free_bytes = result->free_bytes;
return result;
}
void multi_heap_set_lock(multi_heap_handle_t heap, void *lock)
@ -389,18 +159,26 @@ void inline multi_heap_internal_unlock(multi_heap_handle_t heap)
multi_heap_block_handle_t multi_heap_get_first_block(multi_heap_handle_t heap)
{
return &heap->first_block;
assert(heap != NULL);
pool_t pool = tlsf_get_pool(heap->heap_data);
block_header_t* block = offset_to_block(pool, -(int)block_header_overhead);
return (multi_heap_block_handle_t)block;
}
multi_heap_block_handle_t multi_heap_get_next_block(multi_heap_handle_t heap, multi_heap_block_handle_t block)
{
heap_block_t *next = get_next_block(block);
/* check for valid free last block to avoid assert in assert_valid_block */
if (next == heap->last_block && is_last_block(next) && is_free(next)) {
assert(heap != NULL);
assert_valid_block(heap, block);
block_header_t* next = block_next(block);
if(block_data_size(next) == 0) {
//Last block:
return NULL;
} else {
return (multi_heap_block_handle_t)next;
}
assert_valid_block(heap, next);
return next;
}
bool multi_heap_is_free(multi_heap_block_handle_t block)
@ -410,355 +188,132 @@ bool multi_heap_is_free(multi_heap_block_handle_t block)
void *multi_heap_malloc_impl(multi_heap_handle_t heap, size_t size)
{
heap_block_t *best_block = NULL;
heap_block_t *prev_free = NULL;
heap_block_t *prev = NULL;
size_t best_size = SIZE_MAX;
size = ALIGN_UP(size);
if (size == 0 || heap == NULL) {
return NULL;
}
multi_heap_internal_lock(heap);
/* Note: this check must be done while holding the lock as both
malloc & realloc may temporarily shrink the free_bytes value
before they split a large block. This can result in false negatives,
especially if the heap is unfragmented.
*/
if (heap->free_bytes < size) {
MULTI_HEAP_UNLOCK(heap->lock);
return NULL;
}
/* Find best free block to perform the allocation in */
prev = &heap->first_block;
for (heap_block_t *b = heap->first_block.next_free; b != NULL; b = b->next_free) {
MULTI_HEAP_ASSERT(b > prev, &prev->next_free); // free blocks should be ascending in address
MULTI_HEAP_ASSERT(is_free(b), b); // block should be free
size_t bs = block_data_size(b);
if (bs >= size && bs < best_size) {
best_block = b;
best_size = bs;
prev_free = prev;
if (bs == size) {
break; /* we've found a perfect sized block */
}
void *result = tlsf_malloc(heap->heap_data, size);
if(result) {
heap->free_bytes -= tlsf_block_size(result);
if (heap->free_bytes < heap->minimum_free_bytes) {
heap->minimum_free_bytes = heap->free_bytes;
}
prev = b;
}
if (best_block == NULL) {
multi_heap_internal_unlock(heap);
return NULL; /* No room in heap */
}
prev_free->next_free = best_block->next_free;
best_block->header &= ~BLOCK_FREE_FLAG;
heap->free_bytes -= block_data_size(best_block);
split_if_necessary(heap, best_block, size, prev_free);
if (heap->free_bytes < heap->minimum_free_bytes) {
heap->minimum_free_bytes = heap->free_bytes;
}
}
multi_heap_internal_unlock(heap);
return best_block->data;
}
void *multi_heap_aligned_alloc_impl(multi_heap_handle_t heap, size_t size, size_t alignment)
{
if (heap == NULL) {
return NULL;
}
if (!size) {
return NULL;
}
if (!alignment) {
return NULL;
}
//Alignment must be a power of two...
if ((alignment & (alignment - 1)) != 0) {
return NULL;
}
uint32_t overhead = (sizeof(uint32_t) + (alignment - 1));
multi_heap_internal_lock(heap);
void *head = multi_heap_malloc_impl(heap, size + overhead);
if (head == NULL) {
multi_heap_internal_unlock(heap);
return NULL;
}
//Lets align our new obtained block address:
//and save information to recover original block pointer
//to allow us to deallocate the memory when needed
void *ptr = (void *)ALIGN_UP_BY((uintptr_t)head + sizeof(uint32_t), alignment);
*((uint32_t *)ptr - 1) = (uint32_t)((uintptr_t)ptr - (uintptr_t)head);
multi_heap_internal_unlock(heap);
return ptr;
}
void multi_heap_aligned_free_impl(multi_heap_handle_t heap, void *p)
{
if (p == NULL) {
return;
}
multi_heap_internal_lock(heap);
uint32_t offset = *((uint32_t *)p - 1);
void *block_head = (void *)((uint8_t *)p - offset);
#ifdef MULTI_HEAP_POISONING_SLOW
multi_heap_internal_poison_fill_region(block_head, multi_heap_get_allocated_size_impl(heap, block_head), true /* free */);
#endif
multi_heap_free_impl(heap, block_head);
multi_heap_internal_unlock(heap);
return result;
}
void multi_heap_free_impl(multi_heap_handle_t heap, void *p)
{
heap_block_t *pb = get_block(p);
if (heap == NULL || p == NULL) {
return;
}
assert_valid_block(heap, p);
multi_heap_internal_lock(heap);
assert_valid_block(heap, pb);
MULTI_HEAP_ASSERT(!is_free(pb), pb); // block should not be free
MULTI_HEAP_ASSERT(!is_last_block(pb), pb); // block should not be last block
MULTI_HEAP_ASSERT(!is_first_block(heap, pb), pb); // block should not be first block
heap_block_t *next = get_next_block(pb);
/* Update freelist pointers */
heap_block_t *prev_free = get_prev_free_block(heap, pb);
// freelist validity check
MULTI_HEAP_ASSERT(prev_free->next_free == NULL || prev_free->next_free > pb, &prev_free->next_free);
pb->next_free = prev_free->next_free;
prev_free->next_free = pb;
/* Mark this block as free */
pb->header |= BLOCK_FREE_FLAG;
heap->free_bytes += block_data_size(pb);
/* Try and merge previous free block into this one */
if (get_next_block(prev_free) == pb) {
pb = merge_adjacent(heap, prev_free, pb);
}
/* If next block is free, try to merge the two */
if (is_free(next)) {
pb = merge_adjacent(heap, pb, next);
}
heap->free_bytes += tlsf_block_size(p);
tlsf_free(heap->heap_data, p);
multi_heap_internal_unlock(heap);
}
void *multi_heap_realloc_impl(multi_heap_handle_t heap, void *p, size_t size)
{
heap_block_t *pb = get_block(p);
void *result;
size = ALIGN_UP(size);
assert(heap != NULL);
if (p == NULL) {
return multi_heap_malloc_impl(heap, size);
}
assert_valid_block(heap, pb);
// non-null realloc arg should be allocated
MULTI_HEAP_ASSERT(!is_free(pb), pb);
if (size == 0) {
/* note: calling multi_free_impl() here as we've already been
through any poison-unwrapping */
multi_heap_free_impl(heap, p);
return NULL;
}
assert_valid_block(heap, p);
if (heap == NULL) {
return NULL;
}
multi_heap_internal_lock(heap);
result = NULL;
if (size <= block_data_size(pb)) {
// Shrinking....
split_if_necessary(heap, pb, size, NULL);
result = pb->data;
}
else if (heap->free_bytes < size - block_data_size(pb)) {
// Growing, but there's not enough total free space in the heap
multi_heap_internal_unlock(heap);
return NULL;
}
// New size is larger than existing block
if (result == NULL) {
// See if we can grow into one or both adjacent blocks
heap_block_t *orig_pb = pb;
size_t orig_size = block_data_size(orig_pb);
heap_block_t *next = get_next_block(pb);
heap_block_t *prev = get_prev_free_block(heap, pb);
// Can only grow into the previous free block if it's adjacent
size_t prev_grow_size = (get_next_block(prev) == pb) ? block_data_size(prev) : 0;
// Can grow into next block? (we may also need to grow into 'prev' to get to our desired size)
if (is_free(next) && (block_data_size(pb) + block_data_size(next) + prev_grow_size >= size)) {
pb = merge_adjacent(heap, pb, next);
}
// Can grow into previous block?
// (try this even if we're already big enough from growing into 'next', as it reduces fragmentation)
if (prev_grow_size > 0 && (block_data_size(pb) + prev_grow_size >= size)) {
pb = merge_adjacent(heap, prev, pb);
// this doesn't guarantee we'll be left with a big enough block, as it's
// possible for the merge to fail if prev == heap->first_block
}
if (block_data_size(pb) >= size) {
memmove(pb->data, orig_pb->data, orig_size);
split_if_necessary(heap, pb, size, NULL);
result = pb->data;
size_t previous_block_size = tlsf_block_size(p);
void *result = tlsf_realloc(heap->heap_data, p, size);
if(result) {
heap->free_bytes += previous_block_size;
heap->free_bytes -= tlsf_block_size(result);
if (heap->free_bytes < heap->minimum_free_bytes) {
heap->minimum_free_bytes = heap->free_bytes;
}
}
if (result == NULL) {
// Need to allocate elsewhere and copy data over
//
// (Calling _impl versions here as we've already been through any
// unwrapping for heap poisoning features.)
result = multi_heap_malloc_impl(heap, size);
if (result != NULL) {
memcpy(result, pb->data, block_data_size(pb));
multi_heap_free_impl(heap, pb->data);
}
}
if (heap->free_bytes < heap->minimum_free_bytes) {
heap->minimum_free_bytes = heap->free_bytes;
}
multi_heap_internal_unlock(heap);
return result;
}
#define FAIL_PRINT(MSG, ...) do { \
if (print_errors) { \
MULTI_HEAP_STDERR_PRINTF(MSG, __VA_ARGS__); \
} \
valid = false; \
} \
while(0)
void *multi_heap_aligned_alloc_impl(multi_heap_handle_t heap, size_t size, size_t alignment)
{
if(heap == NULL) {
return NULL;
}
if(!size) {
return NULL;
}
//Alignment must be a power of two:
if(((alignment & (alignment - 1)) != 0) ||(!alignment)) {
return NULL;
}
multi_heap_internal_lock(heap);
void *result = tlsf_memalign(heap->heap_data, alignment, size);
if(result) {
heap->free_bytes -= tlsf_block_size(result);
if(heap->free_bytes < heap->minimum_free_bytes) {
heap->minimum_free_bytes = heap->free_bytes;
}
}
multi_heap_internal_unlock(heap);
return result;
}
bool multi_heap_check(multi_heap_handle_t heap, bool print_errors)
{
(void)print_errors;
bool valid = true;
size_t total_free_bytes = 0;
assert(heap != NULL);
multi_heap_internal_lock(heap);
heap_block_t *prev = NULL;
heap_block_t *prev_free = NULL;
heap_block_t *expected_free = NULL;
/* note: not using get_next_block() in loop, so that assertions aren't checked here */
for(heap_block_t *b = &heap->first_block; b != NULL; b = (heap_block_t *)(b->header & NEXT_BLOCK_MASK)) {
if (b == prev) {
FAIL_PRINT("CORRUPT HEAP: Block %p points to itself\n", b);
goto done;
}
if (b < prev) {
FAIL_PRINT("CORRUPT HEAP: Block %p is before prev block %p\n", b, prev);
goto done;
}
if (b > heap->last_block || b < &heap->first_block) {
FAIL_PRINT("CORRUPT HEAP: Block %p is outside heap (last valid block %p)\n", b, prev);
goto done;
}
if (is_free(b)) {
if (prev != NULL && is_free(prev) && !is_first_block(heap, prev) && !is_last_block(b)) {
FAIL_PRINT("CORRUPT HEAP: Two adjacent free blocks found, %p and %p\n", prev, b);
}
if (expected_free != NULL && expected_free != b) {
FAIL_PRINT("CORRUPT HEAP: Prev free block %p pointed to next free %p but this free block is %p\n",
prev_free, expected_free, b);
}
prev_free = b;
expected_free = b->next_free;
if (!is_first_block(heap, b)) {
total_free_bytes += block_data_size(b);
}
}
prev = b;
#ifdef MULTI_HEAP_POISONING
if (!is_last_block(b)) {
/* For slow heap poisoning, any block should contain correct poisoning patterns and/or fills */
bool poison_ok;
if (is_free(b) && b != heap->last_block) {
uint32_t block_len = (intptr_t)get_next_block(b) - (intptr_t)b - sizeof(heap_block_t);
poison_ok = multi_heap_internal_check_block_poisoning(&b[1], block_len, true, print_errors);
}
else {
poison_ok = multi_heap_internal_check_block_poisoning(b->data, block_data_size(b), false, print_errors);
}
valid = poison_ok && valid;
}
#endif
} /* for(heap_block_t b = ... */
if (prev != heap->last_block) {
FAIL_PRINT("CORRUPT HEAP: Last block %p not %p\n", prev, heap->last_block);
}
if (!is_free(heap->last_block)) {
FAIL_PRINT("CORRUPT HEAP: Expected prev block %p to be free\n", heap->last_block);
if(tlsf_check(heap->heap_data)) {
valid = false;
}
if (heap->free_bytes != total_free_bytes) {
FAIL_PRINT("CORRUPT HEAP: Expected %u free bytes counted %u\n", (unsigned)heap->free_bytes, (unsigned)total_free_bytes);
if(tlsf_check_pool(tlsf_get_pool(heap->heap_data))) {
valid = false;
}
done:
multi_heap_internal_unlock(heap);
return valid;
}
static void multi_heap_dump_tlsf(void* ptr, size_t size, int used, void* user)
{
(void)user;
MULTI_HEAP_STDERR_PRINTF("Block %p data, size: %d bytes, Free: %s \n",
(void *)ptr,
size,
used ? "No" : "Yes");
}
void multi_heap_dump(multi_heap_handle_t heap)
{
assert(heap != NULL);
multi_heap_internal_lock(heap);
MULTI_HEAP_STDERR_PRINTF("Heap start %p end %p\nFirst free block %p\n", &heap->first_block, heap->last_block, heap->first_block.next_free);
for(heap_block_t *b = &heap->first_block; b != NULL; b = get_next_block(b)) {
MULTI_HEAP_STDERR_PRINTF("Block %p data size 0x%08x bytes next block %p", b, block_data_size(b), get_next_block(b));
if (is_free(b)) {
MULTI_HEAP_STDERR_PRINTF(" FREE. Next free %p\n", b->next_free);
} else {
MULTI_HEAP_STDERR_PRINTF("%s", "\n"); /* C macros & optional __VA_ARGS__ */
}
}
MULTI_HEAP_STDERR_PRINTF("Showing data for heap: %p \n", (void *)heap);
tlsf_walk_pool(tlsf_get_pool(heap->heap_data), multi_heap_dump_tlsf, NULL);
multi_heap_internal_unlock(heap);
}
@ -767,6 +322,7 @@ size_t multi_heap_free_size_impl(multi_heap_handle_t heap)
if (heap == NULL) {
return 0;
}
return heap->free_bytes;
}
@ -775,9 +331,27 @@ size_t multi_heap_minimum_free_size_impl(multi_heap_handle_t heap)
if (heap == NULL) {
return 0;
}
return heap->minimum_free_bytes;
}
static void multi_heap_get_info_tlsf(void* ptr, size_t size, int used, void* user)
{
multi_heap_info_t *info = user;
if(used) {
info->allocated_blocks++;
} else {
info->free_blocks++;
if(size > info->largest_free_block ) {
info->largest_free_block = size;
}
}
info->total_blocks++;
}
void multi_heap_get_info_impl(multi_heap_handle_t heap, multi_heap_info_t *info)
{
memset(info, 0, sizeof(multi_heap_info_t));
@ -787,25 +361,10 @@ void multi_heap_get_info_impl(multi_heap_handle_t heap, multi_heap_info_t *info)
}
multi_heap_internal_lock(heap);
for(heap_block_t *b = get_next_block(&heap->first_block); !is_last_block(b); b = get_next_block(b)) {
info->total_blocks++;
if (is_free(b)) {
size_t s = block_data_size(b);
info->total_free_bytes += s;
if (s > info->largest_free_block) {
info->largest_free_block = s;
}
info->free_blocks++;
} else {
info->total_allocated_bytes += block_data_size(b);
info->allocated_blocks++;
}
}
tlsf_walk_pool(tlsf_get_pool(heap->heap_data), multi_heap_get_info_tlsf, info);
info->total_allocated_bytes = (heap->pool_size - tlsf_size()) - heap->free_bytes;
info->minimum_free_bytes = heap->minimum_free_bytes;
// heap has wrong total size (address printed here is not indicative of the real error)
MULTI_HEAP_ASSERT(info->total_free_bytes == heap->free_bytes, heap);
info->total_free_bytes = heap->free_bytes;
info->largest_free_block = info->largest_free_block ? 1 << (31 - __builtin_clz(info->largest_free_block)) : 0;
multi_heap_internal_unlock(heap);
}

View File

@ -14,7 +14,7 @@
#pragma once
/* Opaque handle to a heap block */
typedef const struct heap_block *multi_heap_block_handle_t;
typedef const struct block_header_t *multi_heap_block_handle_t;
/* Internal definitions for the "implementation" of the multi_heap API,
as defined in multi_heap.c.
@ -27,8 +27,8 @@ typedef const struct heap_block *multi_heap_block_handle_t;
void *multi_heap_malloc_impl(multi_heap_handle_t heap, size_t size);
void *multi_heap_aligned_alloc_impl(multi_heap_handle_t heap, size_t size, size_t alignment);
void multi_heap_free_impl(multi_heap_handle_t heap, void *p);
void multi_heap_aligned_free_impl(multi_heap_handle_t heap, void *p);
void *multi_heap_realloc_impl(multi_heap_handle_t heap, void *p, size_t size);
void *multi_heap_aligned_alloc_impl(multi_heap_handle_t heap, size_t size, size_t alignment);
multi_heap_handle_t multi_heap_register_impl(void *start, size_t size);
void multi_heap_get_info_impl(multi_heap_handle_t heap, multi_heap_info_t *info);
size_t multi_heap_free_size_impl(multi_heap_handle_t heap);

View File

@ -241,21 +241,6 @@ void *multi_heap_malloc(multi_heap_handle_t heap, size_t size)
return data;
}
void multi_heap_aligned_free(multi_heap_handle_t heap, void *p)
{
multi_heap_internal_lock(heap);
poison_head_t *head = verify_allocated_region(p, true);
assert(head != NULL);
#ifdef SLOW
/* replace everything with FREE_FILL_PATTERN, including the poison head/tail */
memset(head, FREE_FILL_PATTERN, head->alloc_size + POISON_OVERHEAD);
#endif
multi_heap_aligned_free_impl(heap, head);
multi_heap_internal_unlock(heap);
}
void multi_heap_free(multi_heap_handle_t heap, void *p)
{
if (p == NULL) {
@ -276,6 +261,11 @@ void multi_heap_free(multi_heap_handle_t heap, void *p)
multi_heap_internal_unlock(heap);
}
void multi_heap_aligned_free(multi_heap_handle_t heap, void *p)
{
multi_heap_free(heap, p);
}
void *multi_heap_realloc(multi_heap_handle_t heap, void *p, size_t size)
{
poison_head_t *head = NULL;
@ -337,17 +327,6 @@ void *multi_heap_get_block_address(multi_heap_block_handle_t block)
return head + sizeof(poison_head_t);
}
size_t multi_heap_get_allocated_size(multi_heap_handle_t heap, void *p)
{
poison_head_t *head = verify_allocated_region(p, true);
assert(head != NULL);
size_t result = multi_heap_get_allocated_size_impl(heap, head);
if (result > 0) {
return result - POISON_OVERHEAD;
}
return 0;
}
void *multi_heap_get_block_owner(multi_heap_block_handle_t block)
{
return MULTI_HEAP_GET_BLOCK_OWNER((poison_head_t*)multi_heap_get_block_address_impl(block));
@ -371,6 +350,14 @@ static inline void subtract_poison_overhead(size_t *arg) {
}
}
size_t multi_heap_get_allocated_size(multi_heap_handle_t heap, void *p)
{
poison_head_t *head = verify_allocated_region(p, true);
assert(head != NULL);
size_t result = multi_heap_get_allocated_size_impl(heap, head);
return result;
}
void multi_heap_get_info(multi_heap_handle_t heap, multi_heap_info_t *info)
{
multi_heap_get_info_impl(heap, info);

View File

@ -11,6 +11,7 @@
#include <stdlib.h>
#include <sys/param.h>
#include <string.h>
#include <malloc.h>
TEST_CASE("Capabilities aligned allocator test", "[heap]")
{
@ -19,7 +20,7 @@ TEST_CASE("Capabilities aligned allocator test", "[heap]")
printf("[ALIGNED_ALLOC] Allocating from default CAP: \n");
for(;alignments <= 1024; alignments++) {
uint8_t *buf = (uint8_t *)heap_caps_aligned_alloc(alignments, (alignments + 137), MALLOC_CAP_DEFAULT);
uint8_t *buf = (uint8_t *)memalign(alignments, (alignments + 137));
if(((alignments & (alignments - 1)) != 0) || (!alignments)) {
TEST_ASSERT( buf == NULL );
//printf("[ALIGNED_ALLOC] alignment: %u is not a power of two, don't allow allocation \n", aligments);
@ -28,7 +29,6 @@ TEST_CASE("Capabilities aligned allocator test", "[heap]")
printf("[ALIGNED_ALLOC] alignment required: %u \n", alignments);
printf("[ALIGNED_ALLOC] address of allocated memory: %p \n\n", (void *)buf);
//Address of obtained block must be aligned with selected value
if((alignments & 0x03) == 0) {
//Alignment is a multiple of four:
TEST_ASSERT(((intptr_t)buf & 0x03) == 0);
@ -41,7 +41,7 @@ TEST_CASE("Capabilities aligned allocator test", "[heap]")
//canary verification will fail:
memset(buf, 0xA5, (alignments + 137));
heap_caps_aligned_free(buf);
free(buf);
}
}
@ -71,10 +71,12 @@ TEST_CASE("Capabilities aligned allocator test", "[heap]")
//Exotic alignments:
TEST_ASSERT(((intptr_t)buf & (alignments - 1)) == 0);
}
//Write some data, if it corrupts memory probably the heap
//canary verification will fail:
memset(buf, 0xA5, (10*1024));
heap_caps_aligned_free(buf);
heap_caps_free(buf);
}
}
#endif
@ -109,7 +111,7 @@ TEST_CASE("Capabilities aligned calloc test", "[heap]")
//canary verification will fail:
memset(buf, 0xA5, (alignments + 137));
heap_caps_aligned_free(buf);
heap_caps_free(buf);
}
}
@ -118,12 +120,12 @@ TEST_CASE("Capabilities aligned calloc test", "[heap]")
memset(&byte_array, 0, sizeof(byte_array));
uint8_t *buf = (uint8_t *)heap_caps_aligned_calloc(1024, 1, 1024, MALLOC_CAP_DEFAULT);
TEST_ASSERT(memcmp(byte_array, buf, sizeof(byte_array)) == 0);
heap_caps_aligned_free(buf);
heap_caps_free(buf);
//Same size, but different chunk:
buf = (uint8_t *)heap_caps_aligned_calloc(1024, 1024, 1, MALLOC_CAP_DEFAULT);
TEST_ASSERT(memcmp(byte_array, buf, sizeof(byte_array)) == 0);
heap_caps_aligned_free(buf);
heap_caps_free(buf);
//Alloc from a non permitted area:
uint32_t *not_permitted_buf = (uint32_t *)heap_caps_aligned_calloc(alignments, 1, (alignments + 137), MALLOC_CAP_32BIT);
@ -154,7 +156,7 @@ TEST_CASE("Capabilities aligned calloc test", "[heap]")
//Write some data, if it corrupts memory probably the heap
//canary verification will fail:
memset(buf, 0xA5, (10*1024));
heap_caps_aligned_free(buf);
heap_caps_free(buf);
}
}
#endif

View File

@ -0,0 +1,108 @@
#include "freertos/FreeRTOS.h"
#include <esp_types.h>
#include <stdio.h>
#include "unity.h"
#include "esp_attr.h"
#include "esp_heap_caps.h"
#include <stdlib.h>
#include <sys/param.h>
#include <string.h>
#include <test_utils.h>
//This test only makes sense with poisoning disabled
#ifndef CONFIG_HEAP_POISONING_COMPREHENSIVE
#define NUM_POINTERS 128
#define ITERATIONS 10000
TEST_CASE("Heap many random allocations timings", "[heap]")
{
void *p[NUM_POINTERS] = { 0 };
size_t s[NUM_POINTERS] = { 0 };
uint32_t cycles_before;
uint64_t alloc_time_average = 0;
uint64_t free_time_average = 0;
uint64_t realloc_time_average = 0;
for (int i = 0; i < ITERATIONS; i++) {
uint8_t n = esp_random() % NUM_POINTERS;
if (esp_random() % 4 == 0) {
/* 1 in 4 iterations, try to realloc the buffer instead
of using malloc/free
*/
size_t new_size = esp_random() % 1024;
cycles_before = portGET_RUN_TIME_COUNTER_VALUE();
void *new_p = heap_caps_realloc(p[n], new_size, MALLOC_CAP_DEFAULT);
realloc_time_average = portGET_RUN_TIME_COUNTER_VALUE() - cycles_before;
printf("realloc %p -> %p (%zu -> %zu) time spent cycles: %lld \n", p[n], new_p, s[n], new_size, realloc_time_average);
heap_caps_check_integrity(MALLOC_CAP_DEFAULT, true);
if (new_size == 0 || new_p != NULL) {
p[n] = new_p;
s[n] = new_size;
if (new_size > 0) {
memset(p[n], n, new_size);
}
}
continue;
}
if (p[n] != NULL) {
if (s[n] > 0) {
/* Verify pre-existing contents of p[n] */
uint8_t compare[s[n]];
memset(compare, n, s[n]);
TEST_ASSERT(( memcmp(compare, p[n], s[n]) == 0 ));
}
TEST_ASSERT(heap_caps_check_integrity(MALLOC_CAP_DEFAULT, true));
cycles_before = portGET_RUN_TIME_COUNTER_VALUE();
heap_caps_free(p[n]);
free_time_average = portGET_RUN_TIME_COUNTER_VALUE() - cycles_before;
printf("freed %p (%zu) time spent cycles: %lld\n", p[n], s[n], free_time_average);
if (!heap_caps_check_integrity(MALLOC_CAP_DEFAULT, true)) {
printf("FAILED iteration %d after freeing %p\n", i, p[n]);
heap_caps_dump(MALLOC_CAP_DEFAULT);
TEST_ASSERT(0);
}
}
s[n] = rand() % 1024;
heap_caps_check_integrity(MALLOC_CAP_DEFAULT, true);
cycles_before = portGET_RUN_TIME_COUNTER_VALUE();
p[n] = heap_caps_malloc(s[n], MALLOC_CAP_DEFAULT);
alloc_time_average = portGET_RUN_TIME_COUNTER_VALUE() - cycles_before;
printf("malloc %p (%zu) time spent cycles: %lld \n", p[n], s[n], alloc_time_average);
if (!heap_caps_check_integrity(MALLOC_CAP_DEFAULT, true)) {
printf("FAILED iteration %d after mallocing %p (%zu bytes)\n", i, p[n], s[n]);
heap_caps_dump(MALLOC_CAP_DEFAULT);
TEST_ASSERT(0);
}
if (p[n] != NULL) {
memset(p[n], n, s[n]);
}
}
for (int i = 0; i < NUM_POINTERS; i++) {
cycles_before = portGET_RUN_TIME_COUNTER_VALUE();
heap_caps_free( p[i]);
free_time_average = portGET_RUN_TIME_COUNTER_VALUE() - cycles_before;
if (!heap_caps_check_integrity(MALLOC_CAP_DEFAULT, true)) {
printf("FAILED during cleanup after freeing %p\n", p[i]);
heap_caps_dump(MALLOC_CAP_DEFAULT);
TEST_ASSERT(0);
}
}
TEST_ASSERT(heap_caps_check_integrity(MALLOC_CAP_DEFAULT, true));
}
#endif

View File

@ -34,8 +34,8 @@ TEST_CASE("Capabilities allocator test", "[heap]")
free32 = heap_caps_get_free_size(MALLOC_CAP_32BIT);
printf("Free 8bit-capable memory (both reduced): %dK, 32-bit capable memory %dK\n", free8, free32);
//Both should have gone down by 10K; 8bit capable ram is also 32-bit capable
TEST_ASSERT(free8<(free8start-10*1024));
TEST_ASSERT(free32<(free32start-10*1024));
TEST_ASSERT(free8<=(free8start-10*1024));
TEST_ASSERT(free32<=(free32start-10*1024));
//Assume we got DRAM back
TEST_ASSERT((((int)m1)&0xFF000000)==0x3F000000);
free(m1);
@ -55,7 +55,7 @@ TEST_CASE("Capabilities allocator test", "[heap]")
free32 = heap_caps_get_free_size(MALLOC_CAP_32BIT);
printf("Free 8bit-capable memory (after 32-bit): %dK, 32-bit capable memory %dK\n", free8, free32);
//Only 32-bit should have gone down by alloc32: 32-bit isn't necessarily 8bit capable
TEST_ASSERT(free32<(free32start-alloc32));
TEST_ASSERT(free32<=(free32start-alloc32));
TEST_ASSERT(free8==free8start);
free(m1);
} else {
@ -121,8 +121,8 @@ TEST_CASE("IRAM_8BIT capability test", "[heap]")
TEST_ASSERT((((int)ptr)&0xFF000000)==0x40000000);
TEST_ASSERT(heap_caps_get_free_size(MALLOC_CAP_IRAM_8BIT) == (free_size - largest_free_size));
TEST_ASSERT(heap_caps_get_free_size(MALLOC_CAP_32BIT) == (free_size32 - largest_free_size));
TEST_ASSERT(heap_caps_get_free_size(MALLOC_CAP_IRAM_8BIT) == (free_size - heap_caps_get_allocated_size(ptr)));
TEST_ASSERT(heap_caps_get_free_size(MALLOC_CAP_32BIT) == (free_size32 - heap_caps_get_allocated_size(ptr)));
free(ptr);
}
@ -133,7 +133,6 @@ TEST_CASE("heap_caps metadata test", "[heap]")
/* need to print something as first printf allocates some heap */
printf("heap_caps metadata test\n");
heap_caps_print_heap_info(MALLOC_CAP_8BIT);
heap_caps_print_heap_info(MALLOC_CAP_32BIT);
multi_heap_info_t original;
heap_caps_get_info(&original, MALLOC_CAP_8BIT);
@ -146,11 +145,15 @@ TEST_CASE("heap_caps metadata test", "[heap]")
multi_heap_info_t after;
heap_caps_get_info(&after, MALLOC_CAP_8BIT);
TEST_ASSERT(after.largest_free_block < original.largest_free_block);
TEST_ASSERT(after.total_free_bytes < original.total_free_bytes);
TEST_ASSERT(after.largest_free_block <= original.largest_free_block);
TEST_ASSERT(after.total_free_bytes <= original.total_free_bytes);
free(b);
heap_caps_get_info(&after, MALLOC_CAP_8BIT);
printf("\n\n After test, heap status:\n");
heap_caps_print_heap_info(MALLOC_CAP_8BIT);
/* Allow some leeway here, because LWIP sometimes allocates up to 144 bytes in the background
as part of timer management.
*/
@ -167,9 +170,9 @@ static IRAM_ATTR __attribute__((noinline)) bool iram_malloc_test(void)
spi_flash_guard_get()->start(); // Disables flash cache
bool result = true;
void *x = heap_caps_malloc(64, MALLOC_CAP_32BIT);
void *x = heap_caps_malloc(64, MALLOC_CAP_EXEC);
result = result && (x != NULL);
void *y = heap_caps_realloc(x, 32, MALLOC_CAP_32BIT);
void *y = heap_caps_realloc(x, 32, MALLOC_CAP_EXEC);
result = result && (y != NULL);
heap_caps_free(y);
@ -178,6 +181,7 @@ static IRAM_ATTR __attribute__((noinline)) bool iram_malloc_test(void)
return result;
}
TEST_CASE("heap_caps_xxx functions work with flash cache disabled", "[heap]")
{
TEST_ASSERT( iram_malloc_test() );
@ -240,4 +244,4 @@ TEST_CASE("allocation with invalid capability should also trigger the alloc fail
TEST_ASSERT(called_user_failed_hook != false);
(void)ptr;
}
}

View File

@ -34,7 +34,7 @@ TEST_CASE("realloc shrink buffer with EXEC CAPS", "[heap]")
TEST_ASSERT(y);
//y needs to fall in a compatible memory area of IRAM:
TEST_ASSERT(esp_ptr_executable(y));
TEST_ASSERT(esp_ptr_executable(y)|| esp_ptr_in_iram(y) || esp_ptr_in_diram_iram(y));
free(y);
}

View File

@ -7,6 +7,7 @@ endif
SOURCE_FILES = $(abspath \
../multi_heap.c \
../heap_tlsf.c \
../multi_heap_poisoning.c \
test_multi_heap.cpp \
main.cpp \

View File

@ -5,7 +5,7 @@
FAIL=0
for FLAGS in "CONFIG_HEAP_POISONING_NONE" "CONFIG_HEAP_POISONING_LIGHT" "CONFIG_HEAP_POISONING_COMPREHENSIVE"; do
for FLAGS in "CONFIG_HEAP_POISONING_NONE" "CONFIG_HEAP_POISONING_LIGHT" "CONFIG_HEAP_POISONING_COMPREHENSIVE" ; do
echo "==== Testing with config: ${FLAGS} ===="
CPPFLAGS="-D${FLAGS}" make clean test || FAIL=1
done

View File

@ -18,7 +18,7 @@
TEST_CASE("multi_heap simple allocations", "[multi_heap]")
{
uint8_t small_heap[128];
uint8_t small_heap[4 * 1024];
multi_heap_handle_t heap = multi_heap_register(small_heap, sizeof(small_heap));
@ -59,10 +59,10 @@ TEST_CASE("multi_heap simple allocations", "[multi_heap]")
TEST_CASE("multi_heap fragmentation", "[multi_heap]")
{
uint8_t small_heap[256];
uint8_t small_heap[4 * 1024];
multi_heap_handle_t heap = multi_heap_register(small_heap, sizeof(small_heap));
const size_t alloc_size = 24;
const size_t alloc_size = 128;
void *p[4];
for (int i = 0; i < 4; i++) {
@ -85,13 +85,13 @@ TEST_CASE("multi_heap fragmentation", "[multi_heap]")
multi_heap_free(heap, p[0]);
multi_heap_free(heap, p[1]);
multi_heap_free(heap, p[3]);
printf("1 allocations:\n");
multi_heap_dump(heap);
printf("****************\n");
void *big = multi_heap_malloc(heap, alloc_size * 3);
REQUIRE( p[3] == big ); /* big should go where p[3] was freed from */
//Blocks in TLSF are organized in different form, so this makes no sense
multi_heap_free(heap, big);
multi_heap_free(heap, p[2]);
@ -101,7 +101,7 @@ TEST_CASE("multi_heap fragmentation", "[multi_heap]")
printf("****************\n");
big = multi_heap_malloc(heap, alloc_size * 2);
REQUIRE( p[0] == big ); /* big should now go where p[0] was freed from */
//Blocks in TLSF are organized in different form, so this makes no sense
multi_heap_free(heap, big);
}
@ -109,7 +109,7 @@ TEST_CASE("multi_heap fragmentation", "[multi_heap]")
TEST_CASE("multi_heap defrag", "[multi_heap]")
{
void *p[4];
uint8_t small_heap[512];
uint8_t small_heap[4 * 1024];
multi_heap_info_t info, info2;
multi_heap_handle_t heap = multi_heap_register(small_heap, sizeof(small_heap));
@ -159,7 +159,7 @@ TEST_CASE("multi_heap defrag", "[multi_heap]")
TEST_CASE("multi_heap defrag realloc", "[multi_heap]")
{
void *p[4];
uint8_t small_heap[512];
uint8_t small_heap[4 * 1024];
multi_heap_info_t info, info2;
multi_heap_handle_t heap = multi_heap_register(small_heap, sizeof(small_heap));
@ -204,7 +204,7 @@ TEST_CASE("multi_heap defrag realloc", "[multi_heap]")
TEST_CASE("multi_heap many random allocations", "[multi_heap]")
{
uint8_t big_heap[1024];
uint8_t big_heap[8 * 1024];
const int NUM_POINTERS = 64;
printf("Running multi-allocation test...\n");
@ -215,7 +215,7 @@ TEST_CASE("multi_heap many random allocations", "[multi_heap]")
const size_t initial_free = multi_heap_free_size(heap);
const int ITERATIONS = 100000;
const int ITERATIONS = 10000;
for (int i = 0; i < ITERATIONS; i++) {
/* check all pointers allocated so far are valid inside big_heap */
@ -296,7 +296,7 @@ TEST_CASE("multi_heap many random allocations", "[multi_heap]")
TEST_CASE("multi_heap_get_info() function", "[multi_heap]")
{
uint8_t heapdata[256];
uint8_t heapdata[4 * 1024];
multi_heap_handle_t heap = multi_heap_register(heapdata, sizeof(heapdata));
multi_heap_info_t before, after, freed;
@ -349,25 +349,26 @@ TEST_CASE("multi_heap_get_info() function", "[multi_heap]")
TEST_CASE("multi_heap minimum-size allocations", "[multi_heap]")
{
uint8_t heapdata[16384];
void *p[sizeof(heapdata) / sizeof(void *)];
uint8_t heapdata[4096];
void *p[sizeof(heapdata) / sizeof(void *)] = {NULL};
const size_t NUM_P = sizeof(p) / sizeof(void *);
size_t allocated_size = 0;
multi_heap_handle_t heap = multi_heap_register(heapdata, sizeof(heapdata));
size_t before_free = multi_heap_free_size(heap);
size_t i;
for (i = 0; i < NUM_P; i++) {
//TLSF minimum block size is 4 bytes
p[i] = multi_heap_malloc(heap, 1);
if (p[i] == NULL) {
break;
}
}
}
REQUIRE( i < NUM_P); // Should have run out of heap before we ran out of pointers
printf("Allocated %zu minimum size chunks\n", i);
REQUIRE( 0 == multi_heap_free_size(heap) );
REQUIRE(multi_heap_free_size(heap) < before_free);
multi_heap_check(heap, true);
/* Free in random order */
@ -391,7 +392,7 @@ TEST_CASE("multi_heap minimum-size allocations", "[multi_heap]")
TEST_CASE("multi_heap_realloc()", "[multi_heap]")
{
const uint32_t PATTERN = 0xABABDADA;
uint8_t small_heap[300];
uint8_t small_heap[4 * 1024];
multi_heap_handle_t heap = multi_heap_register(small_heap, sizeof(small_heap));
uint32_t *a = (uint32_t *)multi_heap_malloc(heap, 64);
@ -427,9 +428,9 @@ TEST_CASE("multi_heap_realloc()", "[multi_heap]")
REQUIRE( f == b ); /* 'b' should be extended in-place, over space formerly occupied by 'd' */
#ifdef MULTI_HEAP_POISONING
#define TOO_MUCH 92 + 1
#define TOO_MUCH 7420 + 1
#else
#define TOO_MUCH 128 + 1
#define TOO_MUCH 7420 + 1
#endif
/* not enough contiguous space left in the heap */
uint32_t *g = (uint32_t *)multi_heap_realloc(heap, e, TOO_MUCH);
@ -443,61 +444,11 @@ TEST_CASE("multi_heap_realloc()", "[multi_heap]")
#endif
}
TEST_CASE("corrupt heap block", "[multi_heap]")
{
uint8_t small_heap[256];
multi_heap_handle_t heap = multi_heap_register(small_heap, sizeof(small_heap));
void *a = multi_heap_malloc(heap, 32);
REQUIRE( multi_heap_check(heap, true) );
memset(a, 0xEE, 64);
REQUIRE( !multi_heap_check(heap, true) );
}
TEST_CASE("unaligned heaps", "[multi_heap]")
{
const size_t CHUNK_LEN = 256;
const size_t CANARY_LEN = 16;
const uint8_t CANARY_BYTE = 0x3E;
uint8_t heap_chunk[CHUNK_LEN + CANARY_LEN * 2];
/* Put some canary bytes before and after the bytes we intend to use for
the heap, make sure they aren't ever overwritten */
memset(heap_chunk, CANARY_BYTE, CANARY_LEN);
memset(heap_chunk + CANARY_LEN + CHUNK_LEN, CANARY_BYTE, CANARY_LEN);
for (int i = 0; i < 8; i++) {
printf("Testing with offset %d\n", i);
multi_heap_handle_t heap = multi_heap_register(heap_chunk + CANARY_LEN + i, CHUNK_LEN - i);
multi_heap_info_t info;
REQUIRE( multi_heap_check(heap, true) );
multi_heap_get_info(heap, &info);
REQUIRE( info.total_free_bytes > CHUNK_LEN - 64 - i );
REQUIRE( info.largest_free_block > CHUNK_LEN - 64 - i );
void *a = multi_heap_malloc(heap, info.largest_free_block);
REQUIRE( a != NULL );
memset(a, 0xAA, info.largest_free_block);
REQUIRE( multi_heap_check(heap, true) );
multi_heap_free(heap, a);
REQUIRE( multi_heap_check(heap, true) );
for (unsigned j = 0; j < CANARY_LEN; j++) { // check canaries
REQUIRE( heap_chunk[j] == CANARY_BYTE );
REQUIRE( heap_chunk[CHUNK_LEN + CANARY_LEN + j] == CANARY_BYTE );
}
}
}
// TLSF only accepts heaps aligned to 4-byte boundary so
// only aligned allocation tests make sense.
TEST_CASE("multi_heap aligned allocations", "[multi_heap]")
{
uint8_t test_heap[1024 * 1024];
uint8_t test_heap[4 * 1024];
multi_heap_handle_t heap = multi_heap_register(test_heap, sizeof(test_heap));
uint32_t aligments = 0; // starts from alignment by 4-byte boundary
size_t old_size = multi_heap_free_size(heap);
@ -508,7 +459,7 @@ TEST_CASE("multi_heap aligned allocations", "[multi_heap]")
multi_heap_dump(heap);
printf("*********************\n");
for(;aligments < 500 * 1024; aligments++) {
for(;aligments <= 256; aligments++) {
//Use some stupid size value to test correct alignment even in strange
//memory layout objects:
@ -525,7 +476,6 @@ TEST_CASE("multi_heap aligned allocations", "[multi_heap]")
//printf("[ALIGNED_ALLOC] allocated size: %d \n", multi_heap_get_allocated_size(heap, buf));
printf("[ALIGNED_ALLOC] address of allocated memory: %p \n\n", (void *)buf);
//Address of obtained block must be aligned with selected value
if((aligments & 0x03) == 0) {
//Alignment is a multiple of four:
REQUIRE(((intptr_t)buf & 0x03) == 0);
@ -538,10 +488,10 @@ TEST_CASE("multi_heap aligned allocations", "[multi_heap]")
//canary verification will fail:
memset(buf, 0xA5, (aligments + 137));
multi_heap_aligned_free(heap, buf);
multi_heap_free(heap, buf);
}
}
printf("[ALIGNED_ALLOC] heap_size after: %d \n", multi_heap_free_size(heap));
REQUIRE((old_size - multi_heap_free_size(heap)) <= leakage);
}
}

View File

@ -154,3 +154,12 @@
#ifndef IDF_PERFORMANCE_MAX_SCHEDULING_TIME
#define IDF_PERFORMANCE_MAX_SCHEDULING_TIME 2000
#endif
#ifndef IDF_PERFORMANCE_MAX_MALLOC_DEFAULT_AVERAGE_TIME
#define IDF_PERFORMANCE_MAX_MALLOC_DEFAULT_AVERAGE_TIME 2600
#endif
#ifndef IDF_PERFORMANCE_MAX_FREE_DEFAULT_AVERAGE_TIME
#define IDF_PERFORMANCE_MAX_FREE_DEFAULT_AVERAGE_TIME 950
#endif

View File

@ -26,7 +26,6 @@
extern void *heap_caps_malloc_default( size_t size );
extern void *heap_caps_realloc_default( void *ptr, size_t size );
void* malloc(size_t size)
{
return heap_caps_malloc_default(size);
@ -77,6 +76,11 @@ void* _calloc_r(struct _reent *r, size_t nmemb, size_t size)
return result;
}
void* memalign(size_t alignment, size_t n)
{
return heap_caps_aligned_alloc(alignment, n, MALLOC_CAP_DEFAULT);
}
/* No-op function, used to force linking this file,
instead of the heap implementation from newlib.
*/
@ -89,13 +93,6 @@ void newlib_include_heap_impl(void)
Define them as non-functional stubs here, so that the application
can not cause the newlib heap implementation to be linked in
*/
void* memalign(size_t alignment, size_t n)
{
extern void memalign_function_was_linked_but_unsupported_in_esp_idf(void);
memalign_function_was_linked_but_unsupported_in_esp_idf();
return NULL;
}
int malloc_trim(size_t pad)
{

View File

@ -119,7 +119,6 @@ static void *thread_test_pthread_destructor(void *v_key)
static void test_pthread_destructor(void *value)
{
printf("Destructor called...\n");
actual_destructor_ptr = value;
}

View File

@ -46,7 +46,6 @@ typedef struct {
static inline void __attribute__((always_inline)) spinlock_initialize(spinlock_t *lock)
{
assert(lock);
#if !CONFIG_FREERTOS_UNICORE
lock->owner = SPINLOCK_FREE;
lock->count = 0;

View File

@ -139,7 +139,7 @@ TEST_CASE("multiple tasks can access wl handle simultaneously", "[wear_levelling
TEST_ESP_OK(wl_erase_range(handle, 0, sector_size * 8));
read_write_test_arg_t args1 = READ_WRITE_TEST_ARG_INIT(0, 1, handle, sector_size/sizeof(uint32_t));
read_write_test_arg_t args2 = READ_WRITE_TEST_ARG_INIT(sector_size, 2, handle, sector_size/sizeof(uint32_t));
const size_t stack_size = 4096;
const size_t stack_size = 8192;
printf("writing 1 and 2\n");
const int cpuid_0 = 0;

View File

@ -299,6 +299,8 @@ INPUT = \
$(IDF_PATH)/components/freertos/include/freertos/semphr.h \
$(IDF_PATH)/components/freertos/include/freertos/timers.h \
$(IDF_PATH)/components/freertos/include/freertos/event_groups.h \
$(IDF_PATH)/components/freertos/include/freertos/stream_buffer.h \
$(IDF_PATH)/components/freertos/include/freertos/message_buffer.h \
### Ringbuffer
$(IDF_PATH)/components/esp_ringbuf/include/freertos/ringbuf.h \
### Helper functions for error codes

View File

@ -19,7 +19,7 @@ These third party libraries can be included into the application (firmware) prod
* :component:`Xtensa header files<xtensa/include/xtensa>` are Copyright (C) 2013 Tensilica Inc and are licensed under the MIT License as reproduced in the individual header files.
* Original parts of FreeRTOS_ (components/freertos) are Copyright (C) 2015 Real Time Engineers Ltd and is licensed under the GNU General Public License V2 with the FreeRTOS Linking Exception, as described in :component_file:`license.txt<freertos/license.txt>`.
* Original parts of FreeRTOS_ (components/freertos) are Copyright (C) 2017 Amazon.com, Inc. or its affiliates are licensed under the MIT License, as described in :component_file:`license.txt<freertos/license.txt>`.
* Original parts of LWIP_ (components/lwip) are Copyright (C) 2001, 2002 Swedish Institute of Computer Science and are licensed under the BSD License as described in :component_file:`COPYING file<lwip/lwip/COPYING>`.
@ -65,6 +65,8 @@ These third party libraries can be included into the application (firmware) prod
* `cryptoauthlib`_ Microchip CryptoAuthentication Library - Copyright (c) 2015 - 2018 Microchip Technology Inc, is licensed under common Microchip software License as described in :example_file:`LICENSE file <peripherals/secure_element/atecc608_ecdsa/components/esp-cryptoauthlib/cryptoauthlib/LICENSE>`
* :component_file:` TLSF allocator <heap/heap_tlsf.c>` Two Level Segregated Fit memory allocator, Copyright (c) 2006-2016, Matthew Conte, and licensed under the BSD license.
Build Tools
-----------

View File

@ -21,59 +21,47 @@ found via https://www.freertos.org/a00106.html
For information regarding features that are exclusive to ESP-IDF FreeRTOS,
see :doc:`ESP-IDF FreeRTOS Additions<../api-reference/system/freertos_additions>`.
:ref:`backported-features`: Although ESP-IDF FreeRTOS is based on the Xtensa
port of FreeRTOS v8.2.0, a number of FreeRTOS v9.0.0 features have been backported
to ESP-IDF.
.. only:: esp32
.. only:: not CONFIG_FREERTOS_UNICORE
:ref:`tasks-and-task-creation`: Use :cpp:func:`xTaskCreatePinnedToCore` or
:cpp:func:`xTaskCreateStaticPinnedToCore` to create tasks in ESP-IDF FreeRTOS. The
last parameter of the two functions is ``xCoreID``. This parameter specifies
which core the task is pinned to. Acceptable values are ``0`` for **PRO_CPU**,
:ref:`tasks-and-task-creation`: Use :cpp:func:`xTaskCreatePinnedToCore` or
:cpp:func:`xTaskCreateStaticPinnedToCore` to create tasks in ESP-IDF FreeRTOS. The
last parameter of the two functions is ``xCoreID``. This parameter specifies
which core the task is pinned to. Acceptable values are ``0`` for **PRO_CPU**,
``1`` for **APP_CPU**, or ``tskNO_AFFINITY`` which allows the task to run on
both.
:ref:`round-robin-scheduling`: The ESP-IDF FreeRTOS scheduler will skip tasks when
implementing Round-Robin scheduling between multiple tasks in the Ready state
that are of the same priority. To avoid this behavior, ensure that those tasks either
:ref:`round-robin-scheduling`: The ESP-IDF FreeRTOS scheduler will skip tasks when
implementing Round-Robin scheduling between multiple tasks in the Ready state
that are of the same priority. To avoid this behavior, ensure that those tasks either
enter a blocked state, or are distributed across a wider range of priorities.
:ref:`scheduler-suspension`: Suspending the scheduler in ESP-IDF FreeRTOS will only
affect the scheduler on the the calling core. In other words, calling
:ref:`scheduler-suspension`: Suspending the scheduler in ESP-IDF FreeRTOS will only
affect the scheduler on the the calling core. In other words, calling
:cpp:func:`vTaskSuspendAll` on **PRO_CPU** will not prevent **APP_CPU** from scheduling, and
vice versa. Use critical sections or semaphores instead for simultaneous
access protection.
:ref:`tick-interrupt-synchronicity`: Tick interrupts of **PRO_CPU** and **APP_CPU**
are not synchronized. Do not expect to use :cpp:func:`vTaskDelay` or
:cpp:func:`vTaskDelayUntil` as an accurate method of synchronizing task execution
between the two cores. Use a counting semaphore instead as their context
:ref:`tick-interrupt-synchronicity`: Tick interrupts of **PRO_CPU** and **APP_CPU**
are not synchronized. Do not expect to use :cpp:func:`vTaskDelay` or
:cpp:func:`vTaskDelayUntil` as an accurate method of synchronizing task execution
between the two cores. Use a counting semaphore instead as their context
switches are not tied to tick interrupts due to preemption.
:ref:`critical-sections`: In ESP-IDF FreeRTOS, critical sections are implemented using
mutexes. Entering critical sections involve taking a mutex, then disabling the
scheduler and interrupts of the calling core. However the other core is left
mutexes. Entering critical sections involve taking a mutex, then disabling the
scheduler and interrupts of the calling core. However the other core is left
unaffected. If the other core attemps to take same mutex, it will spin until
the calling core has released the mutex by exiting the critical section.
:ref:`floating-points`: The {IDF_TARGET_NAME} supports hardware acceleration of single
:ref:`floating-points`: The ESP32 supports hardware acceleration of single
precision floating point arithmetic (``float``). However the use of hardware
acceleration leads to some behavioral restrictions in ESP-IDF FreeRTOS.
Therefore, tasks that utilize ``float`` will automatically be pinned to a core if
not done so already. Furthermore, ``float`` cannot be used in interrupt service
Therefore, tasks that utilize ``float`` will automatically be pinned to a core if
not done so already. Furthermore, ``float`` cannot be used in interrupt service
routines.
`Task Deletion`_: Task deletion behavior has been backported from FreeRTOS
v9.0.0 and modified to be SMP compatible. Task memory will be freed immediately
when :cpp:func:`vTaskDelete` is called to delete a task that is not currently running
and not pinned to the other core. Otherwise, freeing of task memory will still
be delegated to the Idle Task.
:ref:`deletion-callbacks`: ESP-IDF FreeRTOS has backported the Thread Local
Storage Pointers (TLSP) feature. However the extra feature of Deletion Callbacks has been
added. Deletion callbacks are called automatically during task deletion and are
used to free memory pointed to by TLSP. Call
:ref:`deletion-callbacks`: Deletion callbacks are called automatically during task deletion and are
used to free memory pointed to by TLSP. Call
:cpp:func:`vTaskSetThreadLocalStoragePointerAndDelCallback()` to set TLSP and Deletion
Callbacks.
@ -82,64 +70,6 @@ set in the project configuration (``idf.py menuconfig``) such as running ESP-IDF
Unicore (single core) Mode, or configuring the number of Thread Local Storage Pointers
each task will have.
.. _backported-features:
Backported Features
-------------------
The following features have been backported from FreeRTOS v9.0.0 to ESP-IDF.
Static Alocation
^^^^^^^^^^^^^^^^^
This feature has been backported from FreeRTOS v9.0.0 to ESP-IDF. The
:ref:`CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION` option must be enabled in `menuconfig`
in order for static allocation functions to be available. Once enabled, the
following functions can be called...
- :cpp:func:`xTaskCreateStatic` (see :ref:`backporting-notes` below)
- :c:macro:`xQueueCreateStatic`
- :c:macro:`xSemaphoreCreateBinaryStatic`
- :c:macro:`xSemaphoreCreateCountingStatic`
- :c:macro:`xSemaphoreCreateMutexStatic`
- :c:macro:`xSemaphoreCreateRecursiveMutexStatic`
- :cpp:func:`xTimerCreateStatic` (see :ref:`backporting-notes` below)
- :cpp:func:`xEventGroupCreateStatic`
Other Features
^^^^^^^^^^^^^^
- :cpp:func:`vTaskSetThreadLocalStoragePointer` (see :ref:`backporting-notes` below)
- :cpp:func:`pvTaskGetThreadLocalStoragePointer` (see :ref:`backporting-notes` below)
- :cpp:func:`vTimerSetTimerID`
- :cpp:func:`xTimerGetPeriod`
- :cpp:func:`xTimerGetExpiryTime`
- :cpp:func:`pcQueueGetName`
- :c:macro:`uxSemaphoreGetCount`
.. _backporting-notes:
Backporting Notes
^^^^^^^^^^^^^^^^^
**1)** :cpp:func:`xTaskCreateStatic` has been made SMP compatible in a similar
fashion to :cpp:func:`xTaskCreate` (see :ref:`tasks-and-task-creation`). Therefore
:cpp:func:`xTaskCreateStaticPinnedToCore` can also be called.
**2)** Although vanilla FreeRTOS allows the Timer feature's daemon task to
be statically allocated, the daemon task is always dynamically allocated in
ESP-IDF. Therefore ``vApplicationGetTimerTaskMemory`` **does not** need to be
defined when using statically allocated timers in ESP-IDF FreeRTOS.
**3)** The Thread Local Storage Pointer feature has been modified in ESP-IDF
FreeRTOS to include Deletion Callbacks (see :ref:`deletion-callbacks`). Therefore
the function :cpp:func:`vTaskSetThreadLocalStoragePointerAndDelCallback` can also be
called.
.. _tasks-and-task-creation:
Tasks and Task Creation
@ -149,9 +79,9 @@ Tasks in ESP-IDF FreeRTOS are designed to run on a particular core, therefore
two new task creation functions have been added to ESP-IDF FreeRTOS by
appending ``PinnedToCore`` to the names of the task creation functions in
vanilla FreeRTOS. The vanilla FreeRTOS functions of :cpp:func:`xTaskCreate`
and :cpp:func:`xTaskCreateStatic` have led to the addition of
:cpp:func:`xTaskCreatePinnedToCore` and :cpp:func:`xTaskCreateStaticPinnedToCore` in
ESP-IDF FreeRTOS (see :ref:`backported-features`).
and :cpp:func:`xTaskCreateStatic` have led to the addition of
:cpp:func:`xTaskCreatePinnedToCore` and :cpp:func:`xTaskCreateStaticPinnedToCore` in
ESP-IDF FreeRTOS
For more details see :component_file:`freertos/tasks.c`
@ -434,10 +364,9 @@ matter.
Task Deletion
-------------
FreeRTOS task deletion prior to v9.0.0 delegated the freeing of task memory
entirely to the Idle Task. Currently, the freeing of task memory will occur
immediately (within :cpp:func:`vTaskDelete`) if the task being deleted is not currently
running or is not pinned to the other core (with respect to the core
In FreeRTOS task deletion the freeing of task memory will occur
immediately (within :cpp:func:`vTaskDelete`) if the task being deleted is not currently
running or is not pinned to the other core (with respect to the core
:cpp:func:`vTaskDelete` is called on). TLSP deletion callbacks will also run immediately
if the same conditions are met.
@ -479,9 +408,6 @@ called for that TLSP during task deletion. If a deletion callback is `NULL`,
users should manually free the memory pointed to by the associated TLSP before
task deletion in order to avoid memory leak.
:ref:`CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS` in menuconfig can be used
to configure the number TLSP and Deletion Callbacks a TCB will have.
For more details see :doc:`FreeRTOS API reference<../api-reference/system/freertos>`.
@ -512,11 +438,7 @@ ESP-IDF FreeRTOS configurations, see :doc:`FreeRTOS <../api-reference/kconfig>`
will be modified. For more details regarding the effects of running ESP-IDF FreeRTOS
on a single core, search for occurences of ``CONFIG_FREERTOS_UNICORE`` in the ESP-IDF components.
:ref:`CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS` will define the
number of Thread Local Storage Pointers each task will have in ESP-IDF
FreeRTOS.
:ref:`CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION` will enable the backported
:ref:`CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION` will enable the
functionality of :cpp:func:`xTaskCreateStaticPinnedToCore` in ESP-IDF FreeRTOS
:ref:`CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION` will trigger a halt in

View File

@ -7,7 +7,7 @@ Overview
This section contains documentation of FreeRTOS types, functions, and macros. It is automatically generated from FreeRTOS header files.
.. note::
ESP-IDF FreeRTOS is based on the Xtensa port of FreeRTOS v8.2.0, however some functions of FreeRTOS v9.0.0 have been backported. See the :ref:`backported-features` for more information.
ESP-IDF FreeRTOS is based on the Xtensa port of FreeRTOS v10.2.0,
For more information about FreeRTOS features specific to ESP-IDF, see :doc:`ESP-IDF FreeRTOS SMP Changes<../../api-guides/freertos-smp>`
and :doc:`ESP-IDF FreeRTOS Additions<freertos_additions>`.
@ -39,4 +39,13 @@ Event Group API
.. include-build-file:: inc/event_groups.inc
Stream Buffer API
-----------------
.. include-build-file:: inc/stream_buffer.inc
Message Buffer API
------------------
.. include-build-file:: inc/message_buffer.inc

View File

@ -362,7 +362,7 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param)
do {
int tmr_id = 0;
s_tmr = xTimerCreate("connTmr", (10000 / portTICK_RATE_MS),
pdTRUE, (void *)tmr_id, a2d_app_heart_beat);
pdTRUE, (void *) &tmr_id, a2d_app_heart_beat);
xTimerStart(s_tmr, portMAX_DELAY);
} while (0);
break;

View File

@ -102,7 +102,7 @@ static void spp_task_task_handler(void *arg)
void spp_task_task_start_up(void)
{
spp_task_task_queue = xQueueCreate(10, sizeof(spp_task_msg_t));
xTaskCreate(spp_task_task_handler, "SPPAppT", 2048, NULL, 10, spp_task_task_handle);
xTaskCreate(spp_task_task_handler, "SPPAppT", 2048, NULL, 10, &spp_task_task_handle);
return;
}

View File

@ -424,7 +424,7 @@ static void handle_sync_timeout(void *arg)
static bool run_first = true;
if (run_first == true) {
xSemaphoreTake((SemaphoreHandle_t)arg, (portTickType)portMAX_DELAY);
esp_timer_start_periodic( (SemaphoreHandle_t)arg, 1000000);
esp_timer_start_periodic( (esp_timer_handle_t)arg, 1000000);
run_first = false;
}
switch (sync_obj.state) {

View File

@ -592,7 +592,7 @@ UT_034:
UT_035:
extends: .unit_test_s2_template
parallel: 41
parallel: 42
tags:
- ESP32S2_IDF
- UT_T1_1

View File

@ -20,4 +20,4 @@ skip:
- "components/nghttp/nghttp2"
- "components/protobuf-c/protobuf-c"
- "components/spiffs/spiffs"
- "components/unity/unity"
- "components/unity/unity"