mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
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:
commit
a1d3f2b291
2
.gitignore
vendored
2
.gitignore
vendored
@ -87,4 +87,4 @@ flake8_output.txt
|
||||
build
|
||||
|
||||
# lock files for examples and components
|
||||
dependencies.lock
|
||||
dependencies.lock
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
)
|
||||
|
2710
components/freertos/History.txt
Normal file
2710
components/freertos/History.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
418
components/freertos/include/freertos/atomic.h
Normal file
418
components/freertos/include/freertos/atomic.h
Normal 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 */
|
@ -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
|
||||
|
@ -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__
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
}
|
||||
|
702
components/freertos/include/freertos/message_buffer.h
Normal file
702
components/freertos/include/freertos/message_buffer.h
Normal 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 ) */
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
@ -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 */
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
745
components/freertos/include/freertos/stream_buffer.h
Normal file
745
components/freertos/include/freertos/stream_buffer.h
Normal 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
@ -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
|
||||
|
@ -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.
|
@ -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
1265
components/freertos/stream_buffer.c
Normal file
1265
components/freertos/stream_buffer.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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, ¬ify_value, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
|
103
components/freertos/test/test_stream_buffers.c
Normal file
103
components/freertos/test/test_stream_buffers.c
Normal 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);
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -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
|
@ -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. */
|
||||
|
@ -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 )
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
@ -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
867
components/heap/heap_tlsf.c
Normal 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
133
components/heap/heap_tlsf.h
Normal 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
|
||||
|
||||
|
172
components/heap/heap_tlsf_block_functions.h
Normal file
172
components/heap/heap_tlsf_block_functions.h
Normal 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);
|
||||
}
|
73
components/heap/heap_tlsf_config.h
Normal file
73
components/heap/heap_tlsf_config.h
Normal 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),
|
||||
};
|
@ -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.
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -1,5 +1,6 @@
|
||||
[mapping:heap]
|
||||
archive: libheap.a
|
||||
entries:
|
||||
heap_tlsf (noflash)
|
||||
multi_heap (noflash)
|
||||
multi_heap_poisoning (noflash)
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
108
components/heap/test/test_allocator_timings.c
Normal file
108
components/heap/test/test_allocator_timings.c
Normal 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
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ endif
|
||||
|
||||
SOURCE_FILES = $(abspath \
|
||||
../multi_heap.c \
|
||||
../heap_tlsf.c \
|
||||
../multi_heap_poisoning.c \
|
||||
test_multi_heap.cpp \
|
||||
main.cpp \
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
-----------
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -592,7 +592,7 @@ UT_034:
|
||||
|
||||
UT_035:
|
||||
extends: .unit_test_s2_template
|
||||
parallel: 41
|
||||
parallel: 42
|
||||
tags:
|
||||
- ESP32S2_IDF
|
||||
- UT_T1_1
|
||||
|
@ -20,4 +20,4 @@ skip:
|
||||
- "components/nghttp/nghttp2"
|
||||
- "components/protobuf-c/protobuf-c"
|
||||
- "components/spiffs/spiffs"
|
||||
- "components/unity/unity"
|
||||
- "components/unity/unity"
|
Loading…
Reference in New Issue
Block a user