doc: renamed project
This commit is contained in:
committed by
Sylvan Arnold
parent
244e516bd8
commit
32618389d1
20
pico-sensor/McuLib/FreeRTOS/Source/FreeRTOS_license.txt
Normal file
20
pico-sensor/McuLib/FreeRTOS/Source/FreeRTOS_license.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
MIT License
|
||||
|
||||
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.
|
||||
|
||||
383
pico-sensor/McuLib/FreeRTOS/Source/croutine.c
Normal file
383
pico-sensor/McuLib/FreeRTOS/Source/croutine.c
Normal file
@@ -0,0 +1,383 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "croutine.h"
|
||||
|
||||
/* Remove the whole file is co-routines are not being used. */
|
||||
#if ( configUSE_CO_ROUTINES != 0 )
|
||||
|
||||
/*
|
||||
* Some kernel aware debuggers require data to be viewed to be global, rather
|
||||
* than file scope.
|
||||
*/
|
||||
#ifdef portREMOVE_STATIC_QUALIFIER
|
||||
#define static
|
||||
#endif
|
||||
|
||||
|
||||
/* Lists for ready and blocked co-routines. --------------------*/
|
||||
static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /**< Prioritised ready co-routines. */
|
||||
static List_t xDelayedCoRoutineList1; /**< Delayed co-routines. */
|
||||
static List_t xDelayedCoRoutineList2; /**< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */
|
||||
static List_t * pxDelayedCoRoutineList = NULL; /**< Points to the delayed co-routine list currently being used. */
|
||||
static List_t * pxOverflowDelayedCoRoutineList = NULL; /**< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */
|
||||
static List_t xPendingReadyCoRoutineList; /**< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */
|
||||
|
||||
/* Other file private variables. --------------------------------*/
|
||||
CRCB_t * pxCurrentCoRoutine = NULL;
|
||||
static UBaseType_t uxTopCoRoutineReadyPriority = 0;
|
||||
static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0;
|
||||
|
||||
/* The initial state of the co-routine when it is created. */
|
||||
#define corINITIAL_STATE ( 0 )
|
||||
|
||||
/*
|
||||
* Place the co-routine represented by pxCRCB into the appropriate ready queue
|
||||
* for the priority. It is inserted at the end of the list.
|
||||
*
|
||||
* This macro accesses the co-routine ready lists and therefore must not be
|
||||
* used from within an ISR.
|
||||
*/
|
||||
#define prvAddCoRoutineToReadyQueue( pxCRCB ) \
|
||||
do { \
|
||||
if( ( pxCRCB )->uxPriority > uxTopCoRoutineReadyPriority ) \
|
||||
{ \
|
||||
uxTopCoRoutineReadyPriority = ( pxCRCB )->uxPriority; \
|
||||
} \
|
||||
vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ ( pxCRCB )->uxPriority ] ), &( ( pxCRCB )->xGenericListItem ) ); \
|
||||
} while( 0 )
|
||||
|
||||
/*
|
||||
* Utility to ready all the lists used by the scheduler. This is called
|
||||
* automatically upon the creation of the first co-routine.
|
||||
*/
|
||||
static void prvInitialiseCoRoutineLists( void );
|
||||
|
||||
/*
|
||||
* Co-routines that are readied by an interrupt cannot be placed directly into
|
||||
* the ready lists (there is no mutual exclusion). Instead they are placed in
|
||||
* in the pending ready list in order that they can later be moved to the ready
|
||||
* list by the co-routine scheduler.
|
||||
*/
|
||||
static void prvCheckPendingReadyList( void );
|
||||
|
||||
/*
|
||||
* Macro that looks at the list of co-routines that are currently delayed to
|
||||
* see if any require waking.
|
||||
*
|
||||
* Co-routines are stored in the queue in the order of their wake time -
|
||||
* meaning once one co-routine has been found whose timer has not expired
|
||||
* we need not look any further down the list.
|
||||
*/
|
||||
static void prvCheckDelayedList( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode,
|
||||
UBaseType_t uxPriority,
|
||||
UBaseType_t uxIndex )
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
CRCB_t * pxCoRoutine;
|
||||
|
||||
traceENTER_xCoRoutineCreate( pxCoRoutineCode, uxPriority, uxIndex );
|
||||
|
||||
/* Allocate the memory that will store the co-routine control block. */
|
||||
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
|
||||
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
|
||||
/* coverity[misra_c_2012_rule_11_5_violation] */
|
||||
pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) );
|
||||
|
||||
if( pxCoRoutine )
|
||||
{
|
||||
/* If pxCurrentCoRoutine is NULL then this is the first co-routine to
|
||||
* be created and the co-routine data structures need initialising. */
|
||||
if( pxCurrentCoRoutine == NULL )
|
||||
{
|
||||
pxCurrentCoRoutine = pxCoRoutine;
|
||||
prvInitialiseCoRoutineLists();
|
||||
}
|
||||
|
||||
/* Check the priority is within limits. */
|
||||
if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES )
|
||||
{
|
||||
uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1;
|
||||
}
|
||||
|
||||
/* Fill out the co-routine control block from the function parameters. */
|
||||
pxCoRoutine->uxState = corINITIAL_STATE;
|
||||
pxCoRoutine->uxPriority = uxPriority;
|
||||
pxCoRoutine->uxIndex = uxIndex;
|
||||
pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode;
|
||||
|
||||
/* Initialise all the other co-routine control block parameters. */
|
||||
vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) );
|
||||
vListInitialiseItem( &( pxCoRoutine->xEventListItem ) );
|
||||
|
||||
/* Set the co-routine control block as a link back from the ListItem_t.
|
||||
* This is so we can get back to the containing CRCB from a generic item
|
||||
* in a list. */
|
||||
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine );
|
||||
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine );
|
||||
|
||||
/* Event lists are always in priority order. */
|
||||
listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) );
|
||||
|
||||
/* Now the co-routine has been initialised it can be added to the ready
|
||||
* list at the correct priority. */
|
||||
prvAddCoRoutineToReadyQueue( pxCoRoutine );
|
||||
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
|
||||
}
|
||||
|
||||
traceRETURN_xCoRoutineCreate( xReturn );
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay,
|
||||
List_t * pxEventList )
|
||||
{
|
||||
TickType_t xTimeToWake;
|
||||
|
||||
traceENTER_vCoRoutineAddToDelayedList( xTicksToDelay, pxEventList );
|
||||
|
||||
/* Calculate the time to wake - this may overflow but this is
|
||||
* not a problem. */
|
||||
xTimeToWake = xCoRoutineTickCount + xTicksToDelay;
|
||||
|
||||
/* We must remove ourselves from the ready list before adding
|
||||
* ourselves to the blocked list as the same list item is used for
|
||||
* both lists. */
|
||||
( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
|
||||
|
||||
/* The list item will be inserted in wake time order. */
|
||||
listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake );
|
||||
|
||||
if( xTimeToWake < xCoRoutineTickCount )
|
||||
{
|
||||
/* Wake time has overflowed. Place this item in the
|
||||
* overflow list. */
|
||||
vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The wake time has not overflowed, so we can use the
|
||||
* current block list. */
|
||||
vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
|
||||
}
|
||||
|
||||
if( pxEventList )
|
||||
{
|
||||
/* Also add the co-routine to an event list. If this is done then the
|
||||
* function must be called with interrupts disabled. */
|
||||
vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) );
|
||||
}
|
||||
|
||||
traceRETURN_vCoRoutineAddToDelayedList();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvCheckPendingReadyList( void )
|
||||
{
|
||||
/* Are there any co-routines waiting to get moved to the ready list? These
|
||||
* are co-routines that have been readied by an ISR. The ISR cannot access
|
||||
* the ready lists itself. */
|
||||
while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE )
|
||||
{
|
||||
CRCB_t * pxUnblockedCRCB;
|
||||
|
||||
/* The pending ready list can be accessed by an ISR. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyCoRoutineList ) );
|
||||
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
|
||||
}
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) );
|
||||
prvAddCoRoutineToReadyQueue( pxUnblockedCRCB );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvCheckDelayedList( void )
|
||||
{
|
||||
CRCB_t * pxCRCB;
|
||||
|
||||
xPassedTicks = xTaskGetTickCount() - xLastTickCount;
|
||||
|
||||
while( xPassedTicks )
|
||||
{
|
||||
xCoRoutineTickCount++;
|
||||
xPassedTicks--;
|
||||
|
||||
/* If the tick count has overflowed we need to swap the ready lists. */
|
||||
if( xCoRoutineTickCount == 0 )
|
||||
{
|
||||
List_t * pxTemp;
|
||||
|
||||
/* Tick count has overflowed so we need to swap the delay lists. If there are
|
||||
* any items in pxDelayedCoRoutineList here then there is an error! */
|
||||
pxTemp = pxDelayedCoRoutineList;
|
||||
pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList;
|
||||
pxOverflowDelayedCoRoutineList = pxTemp;
|
||||
}
|
||||
|
||||
/* See if this tick has made a timeout expire. */
|
||||
while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE )
|
||||
{
|
||||
pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList );
|
||||
|
||||
if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) )
|
||||
{
|
||||
/* Timeout not yet expired. */
|
||||
break;
|
||||
}
|
||||
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
/* The event could have occurred just before this critical
|
||||
* section. If this is the case then the generic list item will
|
||||
* have been moved to the pending ready list and the following
|
||||
* line is still valid. Also the pvContainer parameter will have
|
||||
* been set to NULL so the following lines are also valid. */
|
||||
( void ) uxListRemove( &( pxCRCB->xGenericListItem ) );
|
||||
|
||||
/* Is the co-routine waiting on an event also? */
|
||||
if( pxCRCB->xEventListItem.pxContainer )
|
||||
{
|
||||
( void ) uxListRemove( &( pxCRCB->xEventListItem ) );
|
||||
}
|
||||
}
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
prvAddCoRoutineToReadyQueue( pxCRCB );
|
||||
}
|
||||
}
|
||||
|
||||
xLastTickCount = xCoRoutineTickCount;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vCoRoutineSchedule( void )
|
||||
{
|
||||
traceENTER_vCoRoutineSchedule();
|
||||
|
||||
/* Only run a co-routine after prvInitialiseCoRoutineLists() has been
|
||||
* called. prvInitialiseCoRoutineLists() is called automatically when a
|
||||
* co-routine is created. */
|
||||
if( pxDelayedCoRoutineList != NULL )
|
||||
{
|
||||
/* See if any co-routines readied by events need moving to the ready lists. */
|
||||
prvCheckPendingReadyList();
|
||||
|
||||
/* See if any delayed co-routines have timed out. */
|
||||
prvCheckDelayedList();
|
||||
|
||||
/* Find the highest priority queue that contains ready co-routines. */
|
||||
while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) )
|
||||
{
|
||||
if( uxTopCoRoutineReadyPriority == 0 )
|
||||
{
|
||||
/* No more co-routines to check. */
|
||||
return;
|
||||
}
|
||||
|
||||
--uxTopCoRoutineReadyPriority;
|
||||
}
|
||||
|
||||
/* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines
|
||||
* of the same priority get an equal share of the processor time. */
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) );
|
||||
|
||||
/* Call the co-routine. */
|
||||
( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex );
|
||||
}
|
||||
|
||||
traceRETURN_vCoRoutineSchedule();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInitialiseCoRoutineLists( void )
|
||||
{
|
||||
UBaseType_t uxPriority;
|
||||
|
||||
for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ )
|
||||
{
|
||||
vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) );
|
||||
}
|
||||
|
||||
vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 );
|
||||
vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 );
|
||||
vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList );
|
||||
|
||||
/* Start with pxDelayedCoRoutineList using list1 and the
|
||||
* pxOverflowDelayedCoRoutineList using list2. */
|
||||
pxDelayedCoRoutineList = &xDelayedCoRoutineList1;
|
||||
pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xCoRoutineRemoveFromEventList( const List_t * pxEventList )
|
||||
{
|
||||
CRCB_t * pxUnblockedCRCB;
|
||||
BaseType_t xReturn;
|
||||
|
||||
traceENTER_xCoRoutineRemoveFromEventList( pxEventList );
|
||||
|
||||
/* This function is called from within an interrupt. It can only access
|
||||
* event lists and the pending ready list. This function assumes that a
|
||||
* check has already been made to ensure pxEventList is not empty. */
|
||||
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
|
||||
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
|
||||
vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );
|
||||
|
||||
if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority )
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
|
||||
traceRETURN_xCoRoutineRemoveFromEventList( xReturn );
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif /* configUSE_CO_ROUTINES == 0 */
|
||||
|
||||
871
pico-sensor/McuLib/FreeRTOS/Source/event_groups.c
Normal file
871
pico-sensor/McuLib/FreeRTOS/Source/event_groups.c
Normal file
@@ -0,0 +1,871 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||
* all the API functions to use the MPU wrappers. That should only be done when
|
||||
* task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "timers.h"
|
||||
#include "event_groups.h"
|
||||
|
||||
/* 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
|
||||
|
||||
typedef struct EventGroupDef_t
|
||||
{
|
||||
EventBits_t uxEventBits;
|
||||
List_t xTasksWaitingForBits; /**< List of tasks waiting for a bit to be set. */
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
UBaseType_t uxEventGroupNumber;
|
||||
#endif
|
||||
|
||||
#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
|
||||
uint8_t ucStaticallyAllocated; /**< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
|
||||
#endif
|
||||
} EventGroup_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Test the bits set in uxCurrentEventBits to see if the wait condition is met.
|
||||
* The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is
|
||||
* pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
|
||||
* are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the
|
||||
* 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 ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
|
||||
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer )
|
||||
{
|
||||
EventGroup_t * pxEventBits;
|
||||
|
||||
traceENTER_xEventGroupCreateStatic( pxEventGroupBuffer );
|
||||
|
||||
/* A StaticEventGroup_t object must be provided. */
|
||||
configASSERT( pxEventGroupBuffer );
|
||||
|
||||
#if ( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
/* Sanity check that the size of the structure used to declare a
|
||||
* variable of type StaticEventGroup_t equals the size of the real
|
||||
* event group structure. */
|
||||
volatile size_t xSize = sizeof( StaticEventGroup_t );
|
||||
configASSERT( xSize == sizeof( EventGroup_t ) );
|
||||
}
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
/* The user has provided a statically allocated event group - use it. */
|
||||
/* MISRA Ref 11.3.1 [Misaligned access] */
|
||||
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
|
||||
/* coverity[misra_c_2012_rule_11_3_violation] */
|
||||
pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer;
|
||||
|
||||
if( pxEventBits != NULL )
|
||||
{
|
||||
pxEventBits->uxEventBits = 0;
|
||||
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
|
||||
|
||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||
{
|
||||
/* Both static and dynamic allocation can be used, so note that
|
||||
* this event group was created statically in case the event group
|
||||
* is later deleted. */
|
||||
pxEventBits->ucStaticallyAllocated = pdTRUE;
|
||||
}
|
||||
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||
|
||||
traceEVENT_GROUP_CREATE( pxEventBits );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* xEventGroupCreateStatic should only ever be called with
|
||||
* pxEventGroupBuffer pointing to a pre-allocated (compile time
|
||||
* allocated) StaticEventGroup_t variable. */
|
||||
traceEVENT_GROUP_CREATE_FAILED();
|
||||
}
|
||||
|
||||
traceRETURN_xEventGroupCreateStatic( pxEventBits );
|
||||
|
||||
return pxEventBits;
|
||||
}
|
||||
|
||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||
|
||||
EventGroupHandle_t xEventGroupCreate( void )
|
||||
{
|
||||
EventGroup_t * pxEventBits;
|
||||
|
||||
traceENTER_xEventGroupCreate();
|
||||
|
||||
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
|
||||
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
|
||||
/* coverity[misra_c_2012_rule_11_5_violation] */
|
||||
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );
|
||||
|
||||
if( pxEventBits != NULL )
|
||||
{
|
||||
pxEventBits->uxEventBits = 0;
|
||||
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
|
||||
|
||||
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
{
|
||||
/* Both static and dynamic allocation can be used, so note this
|
||||
* event group was allocated statically in case the event group is
|
||||
* later deleted. */
|
||||
pxEventBits->ucStaticallyAllocated = pdFALSE;
|
||||
}
|
||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||
|
||||
traceEVENT_GROUP_CREATE( pxEventBits );
|
||||
}
|
||||
else
|
||||
{
|
||||
traceEVENT_GROUP_CREATE_FAILED();
|
||||
}
|
||||
|
||||
traceRETURN_xEventGroupCreate( pxEventBits );
|
||||
|
||||
return pxEventBits;
|
||||
}
|
||||
|
||||
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToSet,
|
||||
const EventBits_t uxBitsToWaitFor,
|
||||
TickType_t xTicksToWait )
|
||||
{
|
||||
EventBits_t uxOriginalBitValue, uxReturn;
|
||||
EventGroup_t * pxEventBits = xEventGroup;
|
||||
BaseType_t xAlreadyYielded;
|
||||
BaseType_t xTimeoutOccurred = pdFALSE;
|
||||
|
||||
traceENTER_xEventGroupSync( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTicksToWait );
|
||||
|
||||
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||
configASSERT( uxBitsToWaitFor != 0 );
|
||||
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
|
||||
{
|
||||
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
uxOriginalBitValue = pxEventBits->uxEventBits;
|
||||
|
||||
( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
|
||||
|
||||
if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
|
||||
{
|
||||
/* All the rendezvous bits are now set - no need to block. */
|
||||
uxReturn = ( uxOriginalBitValue | uxBitsToSet );
|
||||
|
||||
/* Rendezvous always clear the bits. They will have been cleared
|
||||
* already unless this is the only task in the rendezvous. */
|
||||
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||
|
||||
xTicksToWait = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( xTicksToWait != ( TickType_t ) 0 )
|
||||
{
|
||||
traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
|
||||
|
||||
/* Store the bits that the calling task is waiting for in the
|
||||
* task's event list item so the kernel knows when a match is
|
||||
* found. Then enter the blocked state. */
|
||||
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
|
||||
|
||||
/* This assignment is obsolete as uxReturn will get set after
|
||||
* the task unblocks, but some compilers mistakenly generate a
|
||||
* warning about uxReturn being returned without being set if the
|
||||
* assignment is omitted. */
|
||||
uxReturn = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The rendezvous bits were not set, but no block time was
|
||||
* specified - just return the current event bit value. */
|
||||
uxReturn = pxEventBits->uxEventBits;
|
||||
xTimeoutOccurred = pdTRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
xAlreadyYielded = xTaskResumeAll();
|
||||
|
||||
if( xTicksToWait != ( TickType_t ) 0 )
|
||||
{
|
||||
if( xAlreadyYielded == pdFALSE )
|
||||
{
|
||||
taskYIELD_WITHIN_API();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* 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
|
||||
* the required bits were set they will have been stored in the task's
|
||||
* event list item, and they should now be retrieved then cleared. */
|
||||
uxReturn = uxTaskResetEventItemValue();
|
||||
|
||||
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
|
||||
{
|
||||
/* The task timed out, just return the current event bit value. */
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
uxReturn = pxEventBits->uxEventBits;
|
||||
|
||||
/* Although the task got here because it timed out before the
|
||||
* bits it was waiting for were set, it is possible that since it
|
||||
* unblocked another task has set the bits. If this is the case
|
||||
* then it needs to clear the bits before exiting. */
|
||||
if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
|
||||
{
|
||||
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
xTimeoutOccurred = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The task unblocked because the bits were set. */
|
||||
}
|
||||
|
||||
/* Control bits might be set as the task had blocked should not be
|
||||
* returned. */
|
||||
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
|
||||
}
|
||||
|
||||
traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
|
||||
|
||||
/* Prevent compiler warnings when trace macros are not used. */
|
||||
( void ) xTimeoutOccurred;
|
||||
|
||||
traceRETURN_xEventGroupSync( uxReturn );
|
||||
|
||||
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 = xEventGroup;
|
||||
EventBits_t uxReturn, uxControlBits = 0;
|
||||
BaseType_t xWaitConditionMet, xAlreadyYielded;
|
||||
BaseType_t xTimeoutOccurred = pdFALSE;
|
||||
|
||||
traceENTER_xEventGroupWaitBits( xEventGroup, uxBitsToWaitFor, xClearOnExit, xWaitForAllBits, xTicksToWait );
|
||||
|
||||
/* Check the user is not attempting to wait on the bits used by the kernel
|
||||
* itself, and that at least one bit is being requested. */
|
||||
configASSERT( xEventGroup );
|
||||
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||
configASSERT( uxBitsToWaitFor != 0 );
|
||||
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
|
||||
{
|
||||
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
|
||||
|
||||
/* Check to see if the wait condition is already met or not. */
|
||||
xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
|
||||
|
||||
if( xWaitConditionMet != pdFALSE )
|
||||
{
|
||||
/* The wait condition has already been met so there is no need to
|
||||
* block. */
|
||||
uxReturn = uxCurrentEventBits;
|
||||
xTicksToWait = ( TickType_t ) 0;
|
||||
|
||||
/* Clear the wait bits if requested to do so. */
|
||||
if( xClearOnExit != pdFALSE )
|
||||
{
|
||||
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else if( xTicksToWait == ( TickType_t ) 0 )
|
||||
{
|
||||
/* The wait condition has not been met, but no block time was
|
||||
* specified, so just return the current value. */
|
||||
uxReturn = uxCurrentEventBits;
|
||||
xTimeoutOccurred = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The task is going to block to wait for its required bits to be
|
||||
* set. uxControlBits are used to remember the specified behaviour of
|
||||
* this call to xEventGroupWaitBits() - for use when the event bits
|
||||
* unblock the task. */
|
||||
if( xClearOnExit != pdFALSE )
|
||||
{
|
||||
uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if( xWaitForAllBits != pdFALSE )
|
||||
{
|
||||
uxControlBits |= eventWAIT_FOR_ALL_BITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Store the bits that the calling task is waiting for in the
|
||||
* task's event list item so the kernel knows when a match is
|
||||
* found. Then enter the blocked state. */
|
||||
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
|
||||
|
||||
/* This is obsolete as it will get set after the task unblocks, but
|
||||
* some compilers mistakenly generate a warning about the variable
|
||||
* being returned without being set if it is not done. */
|
||||
uxReturn = 0;
|
||||
|
||||
traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
|
||||
}
|
||||
}
|
||||
xAlreadyYielded = xTaskResumeAll();
|
||||
|
||||
if( xTicksToWait != ( TickType_t ) 0 )
|
||||
{
|
||||
if( xAlreadyYielded == pdFALSE )
|
||||
{
|
||||
taskYIELD_WITHIN_API();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* 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
|
||||
* the required bits were set they will have been stored in the task's
|
||||
* event list item, and they should now be retrieved then cleared. */
|
||||
uxReturn = uxTaskResetEventItemValue();
|
||||
|
||||
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
|
||||
{
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
/* The task timed out, just return the current event bit value. */
|
||||
uxReturn = pxEventBits->uxEventBits;
|
||||
|
||||
/* It is possible that the event bits were updated between this
|
||||
* task leaving the Blocked state and running again. */
|
||||
if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
|
||||
{
|
||||
if( xClearOnExit != pdFALSE )
|
||||
{
|
||||
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
xTimeoutOccurred = pdTRUE;
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The task unblocked because the bits were set. */
|
||||
}
|
||||
|
||||
/* The task blocked so control bits may have been set. */
|
||||
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
|
||||
}
|
||||
|
||||
traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
|
||||
|
||||
/* Prevent compiler warnings when trace macros are not used. */
|
||||
( void ) xTimeoutOccurred;
|
||||
|
||||
traceRETURN_xEventGroupWaitBits( uxReturn );
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToClear )
|
||||
{
|
||||
EventGroup_t * pxEventBits = xEventGroup;
|
||||
EventBits_t uxReturn;
|
||||
|
||||
traceENTER_xEventGroupClearBits( xEventGroup, uxBitsToClear );
|
||||
|
||||
/* Check the user is not attempting to clear the bits used by the kernel
|
||||
* itself. */
|
||||
configASSERT( xEventGroup );
|
||||
configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
|
||||
|
||||
/* The value returned is the event group value prior to the bits being
|
||||
* cleared. */
|
||||
uxReturn = pxEventBits->uxEventBits;
|
||||
|
||||
/* Clear the bits. */
|
||||
pxEventBits->uxEventBits &= ~uxBitsToClear;
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
traceRETURN_xEventGroupClearBits( uxReturn );
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
|
||||
|
||||
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToClear )
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
|
||||
traceENTER_xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear );
|
||||
|
||||
traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
|
||||
xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL );
|
||||
|
||||
traceRETURN_xEventGroupClearBitsFromISR( xReturn );
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
|
||||
{
|
||||
UBaseType_t uxSavedInterruptStatus;
|
||||
EventGroup_t const * const pxEventBits = xEventGroup;
|
||||
EventBits_t uxReturn;
|
||||
|
||||
traceENTER_xEventGroupGetBitsFromISR( xEventGroup );
|
||||
|
||||
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
|
||||
{
|
||||
uxReturn = pxEventBits->uxEventBits;
|
||||
}
|
||||
taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
|
||||
|
||||
traceRETURN_xEventGroupGetBitsFromISR( uxReturn );
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToSet )
|
||||
{
|
||||
ListItem_t * pxListItem;
|
||||
ListItem_t * pxNext;
|
||||
ListItem_t const * pxListEnd;
|
||||
List_t const * pxList;
|
||||
EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
|
||||
EventGroup_t * pxEventBits = xEventGroup;
|
||||
BaseType_t xMatchFound = pdFALSE;
|
||||
|
||||
traceENTER_xEventGroupSetBits( xEventGroup, uxBitsToSet );
|
||||
|
||||
/* Check the user is not attempting to set the bits used by the kernel
|
||||
* itself. */
|
||||
configASSERT( xEventGroup );
|
||||
configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||
|
||||
pxList = &( pxEventBits->xTasksWaitingForBits );
|
||||
pxListEnd = listGET_END_MARKER( pxList );
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
|
||||
|
||||
pxListItem = listGET_HEAD_ENTRY( pxList );
|
||||
|
||||
/* Set the bits. */
|
||||
pxEventBits->uxEventBits |= uxBitsToSet;
|
||||
|
||||
/* See if the new bit value should unblock any tasks. */
|
||||
while( pxListItem != pxListEnd )
|
||||
{
|
||||
pxNext = listGET_NEXT( pxListItem );
|
||||
uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
|
||||
xMatchFound = pdFALSE;
|
||||
|
||||
/* Split the bits waited for from the control bits. */
|
||||
uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
|
||||
uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
|
||||
|
||||
if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
|
||||
{
|
||||
/* Just looking for single bit being set. */
|
||||
if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
|
||||
{
|
||||
xMatchFound = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
|
||||
{
|
||||
/* All bits are set. */
|
||||
xMatchFound = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Need all bits to be set, but not all the bits were set. */
|
||||
}
|
||||
|
||||
if( xMatchFound != pdFALSE )
|
||||
{
|
||||
/* The bits match. Should the bits be cleared on exit? */
|
||||
if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
|
||||
{
|
||||
uxBitsToClear |= uxBitsWaitedFor;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Store the actual event flag value in the task's event list
|
||||
* item before removing the task from the event list. The
|
||||
* 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. */
|
||||
vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
|
||||
}
|
||||
|
||||
/* Move onto the next list item. Note pxListItem->pxNext is not
|
||||
* used here as the list item may have been removed from the event list
|
||||
* and inserted into the ready/pending reading list. */
|
||||
pxListItem = pxNext;
|
||||
}
|
||||
|
||||
/* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
|
||||
* bit was set in the control word. */
|
||||
pxEventBits->uxEventBits &= ~uxBitsToClear;
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
traceRETURN_xEventGroupSetBits( pxEventBits->uxEventBits );
|
||||
|
||||
return pxEventBits->uxEventBits;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
|
||||
{
|
||||
EventGroup_t * pxEventBits = xEventGroup;
|
||||
const List_t * pxTasksWaitingForBits;
|
||||
|
||||
traceENTER_vEventGroupDelete( xEventGroup );
|
||||
|
||||
configASSERT( pxEventBits );
|
||||
|
||||
pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
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 != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
|
||||
vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
|
||||
}
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
|
||||
{
|
||||
/* The event group can only have been allocated dynamically - free
|
||||
* it again. */
|
||||
vPortFree( pxEventBits );
|
||||
}
|
||||
#elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
|
||||
{
|
||||
/* The event group could have been allocated statically or
|
||||
* dynamically, so check before attempting to free the memory. */
|
||||
if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
|
||||
{
|
||||
vPortFree( pxEventBits );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||
|
||||
traceRETURN_vEventGroupDelete();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup,
|
||||
StaticEventGroup_t ** ppxEventGroupBuffer )
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
EventGroup_t * pxEventBits = xEventGroup;
|
||||
|
||||
traceENTER_xEventGroupGetStaticBuffer( xEventGroup, ppxEventGroupBuffer );
|
||||
|
||||
configASSERT( pxEventBits );
|
||||
configASSERT( ppxEventGroupBuffer );
|
||||
|
||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||
{
|
||||
/* Check if the event group was statically allocated. */
|
||||
if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdTRUE )
|
||||
{
|
||||
/* MISRA Ref 11.3.1 [Misaligned access] */
|
||||
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
|
||||
/* coverity[misra_c_2012_rule_11_3_violation] */
|
||||
*ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits;
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
}
|
||||
#else /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||
{
|
||||
/* Event group must have been statically allocated. */
|
||||
/* MISRA Ref 11.3.1 [Misaligned access] */
|
||||
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
|
||||
/* coverity[misra_c_2012_rule_11_3_violation] */
|
||||
*ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits;
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||
|
||||
traceRETURN_xEventGroupGetStaticBuffer( xReturn );
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* For internal use only - execute a 'set bits' command that was pended from
|
||||
* an interrupt. */
|
||||
void vEventGroupSetBitsCallback( void * pvEventGroup,
|
||||
uint32_t ulBitsToSet )
|
||||
{
|
||||
traceENTER_vEventGroupSetBitsCallback( pvEventGroup, ulBitsToSet );
|
||||
|
||||
/* MISRA Ref 11.5.4 [Callback function parameter] */
|
||||
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
|
||||
/* coverity[misra_c_2012_rule_11_5_violation] */
|
||||
( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet );
|
||||
|
||||
traceRETURN_vEventGroupSetBitsCallback();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* For internal use only - execute a 'clear bits' command that was pended from
|
||||
* an interrupt. */
|
||||
void vEventGroupClearBitsCallback( void * pvEventGroup,
|
||||
uint32_t ulBitsToClear )
|
||||
{
|
||||
traceENTER_vEventGroupClearBitsCallback( pvEventGroup, ulBitsToClear );
|
||||
|
||||
/* MISRA Ref 11.5.4 [Callback function parameter] */
|
||||
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
|
||||
/* coverity[misra_c_2012_rule_11_5_violation] */
|
||||
( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear );
|
||||
|
||||
traceRETURN_vEventGroupClearBitsCallback();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
|
||||
const EventBits_t uxBitsToWaitFor,
|
||||
const BaseType_t xWaitForAllBits )
|
||||
{
|
||||
BaseType_t xWaitConditionMet = pdFALSE;
|
||||
|
||||
if( xWaitForAllBits == pdFALSE )
|
||||
{
|
||||
/* Task only has to wait for one bit within uxBitsToWaitFor to be
|
||||
* set. Is one already set? */
|
||||
if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
|
||||
{
|
||||
xWaitConditionMet = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Task has to wait for all the bits in uxBitsToWaitFor to be set.
|
||||
* Are they set already? */
|
||||
if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
|
||||
{
|
||||
xWaitConditionMet = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
|
||||
return xWaitConditionMet;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
|
||||
|
||||
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToSet,
|
||||
BaseType_t * pxHigherPriorityTaskWoken )
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
|
||||
traceENTER_xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken );
|
||||
|
||||
traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
|
||||
xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken );
|
||||
|
||||
traceRETURN_xEventGroupSetBitsFromISR( xReturn );
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
UBaseType_t uxEventGroupGetNumber( void * xEventGroup )
|
||||
{
|
||||
UBaseType_t xReturn;
|
||||
|
||||
/* MISRA Ref 11.5.2 [Opaque pointer] */
|
||||
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
|
||||
/* coverity[misra_c_2012_rule_11_5_violation] */
|
||||
EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup;
|
||||
|
||||
traceENTER_uxEventGroupGetNumber( xEventGroup );
|
||||
|
||||
if( xEventGroup == NULL )
|
||||
{
|
||||
xReturn = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pxEventBits->uxEventGroupNumber;
|
||||
}
|
||||
|
||||
traceRETURN_uxEventGroupGetNumber( xReturn );
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif /* configUSE_TRACE_FACILITY */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
void vEventGroupSetNumber( void * xEventGroup,
|
||||
UBaseType_t uxEventGroupNumber )
|
||||
{
|
||||
traceENTER_vEventGroupSetNumber( xEventGroup, uxEventGroupNumber );
|
||||
|
||||
/* MISRA Ref 11.5.2 [Opaque pointer] */
|
||||
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
|
||||
/* coverity[misra_c_2012_rule_11_5_violation] */
|
||||
( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber;
|
||||
|
||||
traceRETURN_vEventGroupSetNumber();
|
||||
}
|
||||
|
||||
#endif /* configUSE_TRACE_FACILITY */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
3278
pico-sensor/McuLib/FreeRTOS/Source/include/FreeRTOS.h
Normal file
3278
pico-sensor/McuLib/FreeRTOS/Source/include/FreeRTOS.h
Normal file
File diff suppressed because it is too large
Load Diff
396
pico-sensor/McuLib/FreeRTOS/Source/include/FreeRTOSConfig.h
Normal file
396
pico-sensor/McuLib/FreeRTOS/Source/include/FreeRTOSConfig.h
Normal file
@@ -0,0 +1,396 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_CONFIG_H
|
||||
#define FREERTOS_CONFIG_H
|
||||
|
||||
#include "McuLib.h" /* SDK and API used */
|
||||
#include "McuRTOSconfig.h" /* extra configuration settings not part of the original FreeRTOS ports */
|
||||
|
||||
#define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1 /* 1: include additional header file at the end of task.c to help with debugging in GDB in combination with configUSE_TRACE_FACILITY; 0: no extra file included. */
|
||||
#define configENABLE_BACKWARD_COMPATIBILITY 0 /* 1: enable backward compatibility mode, using old names in kernel. 0: use new kernel structure names (recommended) */
|
||||
/*-----------------------------------------------------------
|
||||
* Application specific definitions.
|
||||
*
|
||||
* These definitions should be adjusted for your particular hardware and
|
||||
* application requirements.
|
||||
*
|
||||
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
|
||||
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
|
||||
*
|
||||
* See http://www.freertos.org/a00110.html.
|
||||
*----------------------------------------------------------*/
|
||||
#ifndef configGENERATE_RUN_TIME_STATS_USE_TICKS
|
||||
#define configGENERATE_RUN_TIME_STATS_USE_TICKS 1 /* 1: Use the RTOS tick counter as runtime counter. 0: use extra timer */
|
||||
#endif
|
||||
#ifndef configGENERATE_RUN_TIME_STATS
|
||||
#define configGENERATE_RUN_TIME_STATS 1 /* 1: generate runtime statistics; 0: no runtime statistics */
|
||||
#endif
|
||||
#if configGENERATE_RUN_TIME_STATS
|
||||
#if configGENERATE_RUN_TIME_STATS_USE_TICKS
|
||||
#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS
|
||||
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() /* nothing */ /* default: use Tick counter as runtime counter */
|
||||
#endif
|
||||
#ifndef portGET_RUN_TIME_COUNTER_VALUE
|
||||
#define portGET_RUN_TIME_COUNTER_VALUE() xTaskGetTickCountFromISR() /* default: use Tick counter as runtime counter */
|
||||
#endif
|
||||
#else /* use dedicated timer */
|
||||
#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS
|
||||
extern void McuRTOS_AppConfigureTimerForRuntimeStats(void);
|
||||
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() McuRTOS_AppConfigureTimerForRuntimeStats()
|
||||
#endif
|
||||
#ifndef portGET_RUN_TIME_COUNTER_VALUE
|
||||
extern uint32_t McuRTOS_AppGetRuntimeCounterValueFromISR(void);
|
||||
#define portGET_RUN_TIME_COUNTER_VALUE() McuRTOS_AppGetRuntimeCounterValueFromISR()
|
||||
#endif
|
||||
#endif
|
||||
#else /* no runtime stats, use empty macros */
|
||||
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() /* nothing */
|
||||
#define portGET_RUN_TIME_COUNTER_VALUE() /* nothing */
|
||||
#endif
|
||||
#ifndef configUSE_PREEMPTION
|
||||
#define configUSE_PREEMPTION 1 /* 1: pre-emptive mode; 0: cooperative mode */
|
||||
#endif
|
||||
#ifndef configUSE_TIME_SLICING
|
||||
#define configUSE_TIME_SLICING 1 /* 1: use time slicing; 0: don't time slice at tick interrupt time */
|
||||
#endif
|
||||
#ifndef configUSE_IDLE_HOOK
|
||||
#define configUSE_IDLE_HOOK 1 /* 1: use Idle hook; 0: no Idle hook */
|
||||
#endif
|
||||
#ifndef configUSE_IDLE_HOOK_NAME
|
||||
#define configUSE_IDLE_HOOK_NAME McuRTOS_vApplicationIdleHook
|
||||
#endif
|
||||
#ifndef configUSE_TICK_HOOK
|
||||
#define configUSE_TICK_HOOK 1 /* 1: use Tick hook; 0: no Tick hook */
|
||||
#endif
|
||||
#ifndef configUSE_TICK_HOOK_NAME
|
||||
#define configUSE_TICK_HOOK_NAME McuRTOS_vApplicationTickHook
|
||||
#endif
|
||||
#ifndef configUSE_MALLOC_FAILED_HOOK
|
||||
#define configUSE_MALLOC_FAILED_HOOK 1 /* 1: use MallocFailed hook; 0: no MallocFailed hook */
|
||||
#endif
|
||||
#ifndef configUSE_MALLOC_FAILED_HOOK_NAME
|
||||
#define configUSE_MALLOC_FAILED_HOOK_NAME McuRTOS_vApplicationMallocFailedHook
|
||||
#endif
|
||||
#ifndef configTICK_RATE_HZ
|
||||
#define configTICK_RATE_HZ (1000) /* frequency of tick interrupt */
|
||||
#endif
|
||||
#define portTICK_RATE_MS (1000/configTICK_RATE_HZ) /* needed for legacy drivers and modules like lwIP */
|
||||
#ifndef configSYSTICK_USE_LOW_POWER_TIMER
|
||||
#define configSYSTICK_USE_LOW_POWER_TIMER 0 /* If using Kinetis Low Power Timer (LPTMR) instead of SysTick timer */
|
||||
#endif
|
||||
#ifndef configSYSTICK_LOW_POWER_TIMER_CLOCK_HZ
|
||||
#define configSYSTICK_LOW_POWER_TIMER_CLOCK_HZ 1000 /* Frequency of low power timer */
|
||||
#endif
|
||||
#if McuLib_CONFIG_NXP_SDK_USED \
|
||||
|| McuLib_CONFIG_SDK_VERSION_USED==McuLib_CONFIG_SDK_GENERIC \
|
||||
|| McuLib_CONFIG_SDK_VERSION_USED==McuLib_CONFIG_SDK_NORDIC_NRF5 \
|
||||
|| McuLib_CONFIG_SDK_VERSION_USED==McuLib_CONFIG_SDK_RPI_PICO
|
||||
/* The CMSIS variable SystemCoreClock contains the current clock speed */
|
||||
extern uint32_t SystemCoreClock;
|
||||
#define configCPU_CLOCK_HZ SystemCoreClock /* CPU clock frequency */
|
||||
#define configBUS_CLOCK_HZ SystemCoreClock /* Bus clock frequency */
|
||||
#else
|
||||
#define configCPU_CLOCK_HZ CPU_CORE_CLK_HZ /* CPU clock frequency */
|
||||
#define configBUS_CLOCK_HZ CPU_BUS_CLK_HZ /* Bus clock frequency */
|
||||
#endif /* #if McuLib_CONFIG_NXP_SDK_USED */
|
||||
#define configSYSTICK_USE_CORE_CLOCK 1 /* System Tick is using core clock */
|
||||
#define configSYSTICK_CLOCK_DIVIDER 1 /* no divider */
|
||||
#define configSYSTICK_CLOCK_HZ ((configCPU_CLOCK_HZ)/configSYSTICK_CLOCK_DIVIDER) /* frequency of system tick counter */
|
||||
#ifndef configMINIMAL_STACK_SIZE
|
||||
#define configMINIMAL_STACK_SIZE (200) /* stack size in addressable stack units */
|
||||
#endif
|
||||
|
||||
#ifndef configNUMBER_OF_CORES
|
||||
#define configNUMBER_OF_CORES (1) /* number of cores for the kernel */
|
||||
#endif
|
||||
|
||||
#ifndef configUSE_MINI_LIST_ITEM
|
||||
#define configUSE_MINI_LIST_ITEM (1)
|
||||
/*!< MiniListItem_t is used for start and end marker nodes in a FreeRTOS list and ListItem_t is used for all other nodes in a FreeRTOS list.
|
||||
* When configUSE_MINI_LIST_ITEM is set to 0, MiniListItem_t and ListItem_t are both the same. When configUSE_MINI_LIST_ITEM is set to 1,
|
||||
* MiniListItem_t contains 3 fewer fields than ListItem_t which saves some RAM at the cost of violating strict aliasing rules which some compilers
|
||||
* depend on for optimization. If left undefined, configUSE_MINI_LIST_ITEM defaults to 1 for backward compatibility.
|
||||
*/
|
||||
#endif
|
||||
/*----------------------------------------------------------*/
|
||||
/* Heap Memory */
|
||||
#ifndef configUSE_HEAP_SCHEME
|
||||
#define configUSE_HEAP_SCHEME 4 /* either 1 (only alloc), 2 (alloc/free), 3 (malloc), 4 (coalesc blocks), 5 (multiple blocks), 6 (newlib) */
|
||||
#endif /* configUSE_HEAP_SCHEME */
|
||||
#define configFRTOS_MEMORY_SCHEME configUSE_HEAP_SCHEME /* for backwards compatible only with legacy name */
|
||||
#ifndef configTOTAL_HEAP_SIZE
|
||||
#define configTOTAL_HEAP_SIZE (8192) /* size of heap in bytes */
|
||||
#endif /* configTOTAL_HEAP_SIZE */
|
||||
#ifndef configUSE_HEAP_SECTION_NAME
|
||||
#define configUSE_HEAP_SECTION_NAME 0 /* set to 1 if a custom section name (configHEAP_SECTION_NAME_STRING) shall be used, 0 otherwise */
|
||||
#endif
|
||||
#ifndef configHEAP_SECTION_NAME_STRING
|
||||
#define configHEAP_SECTION_NAME_STRING ".m_data_20000000" /* heap section name (use e.g. ".m_data_20000000" for KDS/gcc, ".bss.$SRAM_LOWER.FreeRTOS" for MCUXpresso or "m_data_20000000" for IAR). Check your linker file for the name used. */
|
||||
#endif
|
||||
#define configAPPLICATION_ALLOCATED_HEAP 0 /* set to one if application is defining heap ucHeap[] variable, 0 otherwise */
|
||||
#ifndef configSUPPORT_DYNAMIC_ALLOCATION
|
||||
#define configSUPPORT_DYNAMIC_ALLOCATION 1 /* 1: make dynamic allocation functions for RTOS available. 0: only static functions are allowed */
|
||||
#endif
|
||||
#ifndef configSUPPORT_STATIC_ALLOCATION
|
||||
#define configSUPPORT_STATIC_ALLOCATION 0 /* 1: make static allocation functions for RTOS available. 0: only dynamic functions are allowed */
|
||||
#endif
|
||||
#define configUSE_NEWLIB_REENTRANT (configUSE_HEAP_SCHEME==6) /* 1: a newlib reent structure will be allocated for each task; 0: no such reentr structure used */
|
||||
/*----------------------------------------------------------*/
|
||||
#ifndef configMAX_TASK_NAME_LEN
|
||||
#define configMAX_TASK_NAME_LEN 12 /* task name length in bytes */
|
||||
#endif
|
||||
#ifndef configUSE_TRACE_FACILITY
|
||||
#define configUSE_TRACE_FACILITY 1 /* 1: include additional structure members and functions to assist with execution visualization and tracing, 0: no runtime stats/trace */
|
||||
#endif
|
||||
#ifndef configUSE_STATS_FORMATTING_FUNCTIONS
|
||||
#define configUSE_STATS_FORMATTING_FUNCTIONS (configUSE_TRACE_FACILITY || configGENERATE_RUN_TIME_STATS)
|
||||
#endif
|
||||
#define configUSE_16_BIT_TICKS 0 /* 1: use 16bit tick counter type, 0: use 32bit tick counter type */
|
||||
#ifndef configIDLE_SHOULD_YIELD
|
||||
#define configIDLE_SHOULD_YIELD 1 /* 1: the IDEL task will yield as soon as possible. 0: The IDLE task waits until preemption. */
|
||||
#endif
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION (0 && configCPU_FAMILY_IS_ARM_M4_M7(configCPU_FAMILY)) /* 1: the scheduler uses an optimized task selection as defined by the port (if available). 0: normal task selection is used */
|
||||
#endif
|
||||
#ifndef configUSE_CO_ROUTINES
|
||||
#define configUSE_CO_ROUTINES 0
|
||||
#endif
|
||||
#ifndef configUSE_MUTEXES
|
||||
#define configUSE_MUTEXES 1
|
||||
#endif
|
||||
#ifndef configCHECK_FOR_STACK_OVERFLOW
|
||||
#define configCHECK_FOR_STACK_OVERFLOW 1 /* 0 is disabling stack overflow. Set it to 1 for Method1 or 2 for Method2 */
|
||||
#endif
|
||||
#ifndef configCHECK_FOR_STACK_OVERFLOW_NAME
|
||||
#define configCHECK_FOR_STACK_OVERFLOW_NAME McuRTOS_vApplicationStackOverflowHook
|
||||
#endif
|
||||
#ifndef configUSE_RECURSIVE_MUTEXES
|
||||
#define configUSE_RECURSIVE_MUTEXES 1
|
||||
#endif
|
||||
#ifndef configQUEUE_REGISTRY_SIZE
|
||||
#define configQUEUE_REGISTRY_SIZE 5
|
||||
#endif
|
||||
#ifndef configUSE_QUEUE_SETS
|
||||
#define configUSE_QUEUE_SETS 1
|
||||
#endif
|
||||
#ifndef configUSE_COUNTING_SEMAPHORES
|
||||
#define configUSE_COUNTING_SEMAPHORES 1
|
||||
#endif
|
||||
#ifndef configUSE_APPLICATION_TASK_TAG
|
||||
#define configUSE_APPLICATION_TASK_TAG 0
|
||||
#endif
|
||||
#ifndef configUSE_TASK_NOTIFICATIONS
|
||||
#define configUSE_TASK_NOTIFICATIONS 1
|
||||
#endif
|
||||
/* Tickless Idle Mode ----------------------------------------------------------*/
|
||||
#ifndef configUSE_TICKLESS_IDLE
|
||||
#define configUSE_TICKLESS_IDLE 0 /* set to 1 for tickless idle mode, 0 otherwise */
|
||||
#endif
|
||||
#ifndef configEXPECTED_IDLE_TIME_BEFORE_SLEEP
|
||||
#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2 /* number of ticks must be larger than this to enter tickless idle mode */
|
||||
#endif
|
||||
#ifndef configUSE_TICKLESS_IDLE_DECISION_HOOK
|
||||
#define configUSE_TICKLESS_IDLE_DECISION_HOOK 0 /* set to 1 to enable application hook, zero otherwise */
|
||||
#endif
|
||||
#ifndef configUSE_TICKLESS_IDLE_DECISION_HOOK_NAME
|
||||
#define configUSE_TICKLESS_IDLE_DECISION_HOOK_NAME xEnterTicklessIdle /* function name of decision hook */
|
||||
#endif
|
||||
#ifndef configNUM_THREAD_LOCAL_STORAGE_POINTERS
|
||||
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0 /* number of tread local storage pointers, 0 to disable functionality */
|
||||
#endif
|
||||
|
||||
#ifndef configMAX_PRIORITIES
|
||||
#define configMAX_PRIORITIES 6 /* task priorities can be from 0 up to this value-1 */
|
||||
#endif
|
||||
#define configMAX_CO_ROUTINE_PRIORITIES 2 /* co-routine priorities can be from 0 up to this value-1 */
|
||||
|
||||
/* the following needs to be defined (present) or not (not present)! */
|
||||
#define configTASK_RETURN_ADDRESS 0 /* return address of task is zero */
|
||||
|
||||
#ifndef configRECORD_STACK_HIGH_ADDRESS
|
||||
#define configRECORD_STACK_HIGH_ADDRESS 1 /* 1: record stack high address for the debugger, 0: do not record stack high address */
|
||||
#endif
|
||||
|
||||
/* Software timer definitions. */
|
||||
#ifndef configUSE_TIMERS
|
||||
#define configUSE_TIMERS 1 /* 1: enable software timers; 0: software timers disabled */
|
||||
#endif
|
||||
#ifndef configTIMER_TASK_PRIORITY
|
||||
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-1U) /* e.g. (configMAX_PRIORITIES-1U) */
|
||||
#endif
|
||||
#ifndef configTIMER_QUEUE_LENGTH
|
||||
#define configTIMER_QUEUE_LENGTH 10 /* size of queue for the timer task */
|
||||
#endif
|
||||
#ifndef configTIMER_TASK_STACK_DEPTH
|
||||
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE) /* e.g. (configMINIMAL_STACK_SIZE) */
|
||||
#endif
|
||||
#ifndef INCLUDE_xEventGroupSetBitFromISR
|
||||
#define INCLUDE_xEventGroupSetBitFromISR 1 /* 1: function is included; 0: do not include function */
|
||||
#endif
|
||||
#ifndef INCLUDE_xTimerPendFunctionCall
|
||||
#define INCLUDE_xTimerPendFunctionCall 1 /* 1: function is included; 0: do not include function */
|
||||
#endif
|
||||
#ifndef configUSE_DAEMON_TASK_STARTUP_HOOK
|
||||
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0 /* 1: use application specific vApplicationDaemonTaskStartupHook(), 0: do not use hook */
|
||||
#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 the following definitions to 1 to include the API function, or zero
|
||||
to exclude the API function. */
|
||||
#ifndef INCLUDE_vTaskEndScheduler
|
||||
#define INCLUDE_vTaskEndScheduler 0
|
||||
#endif
|
||||
#ifndef INCLUDE_vTaskPrioritySet
|
||||
#define INCLUDE_vTaskPrioritySet 1
|
||||
#endif
|
||||
#ifndef INCLUDE_uxTaskPriorityGet
|
||||
#define INCLUDE_uxTaskPriorityGet 1
|
||||
#endif
|
||||
#ifndef INCLUDE_vTaskDelete
|
||||
#define INCLUDE_vTaskDelete 1
|
||||
#endif
|
||||
#ifndef INCLUDE_vTaskCleanUpResources
|
||||
#define INCLUDE_vTaskCleanUpResources 1
|
||||
#endif
|
||||
#ifndef INCLUDE_vTaskSuspend
|
||||
#define INCLUDE_vTaskSuspend 1
|
||||
#endif
|
||||
#ifndef INCLUDE_vTaskDelayUntil
|
||||
#define INCLUDE_vTaskDelayUntil 1
|
||||
#endif
|
||||
#ifndef INCLUDE_vTaskDelay
|
||||
#define INCLUDE_vTaskDelay 1
|
||||
#endif
|
||||
#ifndef INCLUDE_uxTaskGetStackHighWaterMark
|
||||
#define INCLUDE_uxTaskGetStackHighWaterMark 1
|
||||
#endif
|
||||
#ifndef INCLUDE_xTaskGetSchedulerState
|
||||
#define INCLUDE_xTaskGetSchedulerState 1
|
||||
#endif
|
||||
#ifndef INCLUDE_xQueueGetMutexHolder
|
||||
#define INCLUDE_xQueueGetMutexHolder 1
|
||||
#endif
|
||||
#ifndef INCLUDE_xTaskGetHandle
|
||||
#define INCLUDE_xTaskGetHandle 1
|
||||
#endif
|
||||
#ifndef INCLUDE_xTaskAbortDelay
|
||||
#define INCLUDE_xTaskAbortDelay 1
|
||||
#endif
|
||||
#ifndef INCLUDE_xTaskGetCurrentTaskHandle
|
||||
#define INCLUDE_xTaskGetCurrentTaskHandle 1
|
||||
#endif
|
||||
#ifndef INCLUDE_xTaskGetIdleTaskHandle
|
||||
#define INCLUDE_xTaskGetIdleTaskHandle 1
|
||||
#endif
|
||||
#ifndef INCLUDE_xTaskResumeFromISR
|
||||
#define INCLUDE_xTaskResumeFromISR 1
|
||||
#endif
|
||||
#ifndef INCLUDE_eTaskGetState
|
||||
#define INCLUDE_eTaskGetState 1
|
||||
#endif
|
||||
#ifndef INCLUDE_pcTaskGetTaskName
|
||||
#define INCLUDE_pcTaskGetTaskName 1
|
||||
#endif
|
||||
/* -------------------------------------------------------------------- */
|
||||
#ifndef INCLUDE_pxTaskGetStackStart
|
||||
#define INCLUDE_pxTaskGetStackStart (1 && configUSE_SEGGER_SYSTEM_VIEWER_HOOKS)
|
||||
#endif
|
||||
/* -------------------------------------------------------------------- */
|
||||
#if configCPU_FAMILY_IS_ARM(configCPU_FAMILY)
|
||||
/* Cortex-M specific definitions. */
|
||||
#if configCPU_FAMILY_IS_ARM_M4(configCPU_FAMILY)
|
||||
#define configPRIO_BITS 4 /* 4 bits/16 priority levels on ARM Cortex M4 (Kinetis K Family) */
|
||||
#else
|
||||
#define configPRIO_BITS 2 /* 2 bits/4 priority levels on ARM Cortex M0+ (Kinetis L Family) */
|
||||
#endif
|
||||
|
||||
/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
|
||||
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
|
||||
|
||||
/* The highest interrupt priority that can be used by any interrupt service
|
||||
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
|
||||
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
|
||||
PRIORITY THAN THIS! (higher priorities are lower numeric values on an ARM Cortex-M). */
|
||||
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
|
||||
|
||||
/* Interrupt priorities used by the kernel port layer itself. These are generic
|
||||
to all Cortex-M ports, and do not rely on any particular library functions. */
|
||||
#define configKERNEL_INTERRUPT_PRIORITY (configLIBRARY_LOWEST_INTERRUPT_PRIORITY<<(8-configPRIO_BITS))
|
||||
|
||||
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
|
||||
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
|
||||
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY<<(8-configPRIO_BITS))
|
||||
#elif McuLib_CONFIG_CPU_IS_RISC_V
|
||||
#define configKERNEL_INTERRUPT_PRIORITY (7)
|
||||
#endif
|
||||
|
||||
/* Normal assert() semantics without relying on the provision of an assert.h header file. */
|
||||
#ifndef configASSERT
|
||||
#ifndef taskDISABLE_INTERRUPTS
|
||||
#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS()
|
||||
#endif
|
||||
#define configASSERT(x) if((x)==0) { taskDISABLE_INTERRUPTS(); for( ;; ); }
|
||||
#if 0 /* version for RISC-V with a debug break: */
|
||||
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); __asm volatile( "ebreak" ); for( ;; ); }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* RISC-V only: If the target chip includes a Core Local Interrupter (CLINT) then set configCLINT_BASE_ADDRESS to the CLINT base address.
|
||||
Otherwise set configCLINT_BASE_ADDRESS to 0.
|
||||
*/
|
||||
#define configCLINT_BASE_ADDRESS 0x0
|
||||
|
||||
/*---------------------------------------------------------------------------------------*/
|
||||
/* MPU and TrustZone settings */
|
||||
#ifndef configENABLE_FPU
|
||||
#define configENABLE_FPU (0)
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
#ifndef configENABLE_MPU
|
||||
#define configENABLE_MPU (0)
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#ifndef configENABLE_TRUSTZONE
|
||||
#define configENABLE_TRUSTZONE (0)
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/*---------------------------------------------------------------------------------------*/
|
||||
|
||||
/* custom include file: */
|
||||
// #include "CustomFreeRTOSSettings.h
|
||||
|
||||
|
||||
#endif /* FREERTOS_CONFIG_H */
|
||||
|
||||
|
||||
420
pico-sensor/McuLib/FreeRTOS/Source/include/atomic.h
Normal file
420
pico-sensor/McuLib/FreeRTOS/Source/include/atomic.h
Normal file
@@ -0,0 +1,420 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file atomic.h
|
||||
* @brief FreeRTOS atomic operation support.
|
||||
*
|
||||
* This file implements atomic functions by disabling interrupts globally.
|
||||
* Implementations with architecture specific atomic instructions can 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>
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
* 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 considered as performance optimization
|
||||
* for atomic. Thus, if portFORCE_INLINE is not provided by portmacro.h,
|
||||
* instead of resulting error, simply define it away.
|
||||
*/
|
||||
#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] pulDestination 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 *pulDestination with ulExchange, if previous
|
||||
* *pulDestination value equals ulComparand.
|
||||
*/
|
||||
static portFORCE_INLINE uint32_t Atomic_CompareAndSwap_u32( uint32_t volatile * pulDestination,
|
||||
uint32_t ulExchange,
|
||||
uint32_t ulComparand )
|
||||
{
|
||||
uint32_t ulReturnValue;
|
||||
|
||||
ATOMIC_ENTER_CRITICAL();
|
||||
{
|
||||
if( *pulDestination == ulComparand )
|
||||
{
|
||||
*pulDestination = ulExchange;
|
||||
ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
|
||||
}
|
||||
}
|
||||
ATOMIC_EXIT_CRITICAL();
|
||||
|
||||
return ulReturnValue;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Atomic swap (pointers)
|
||||
*
|
||||
* @brief Atomically sets the address pointed to by *ppvDestination to the value
|
||||
* of *pvExchange.
|
||||
*
|
||||
* @param[in, out] ppvDestination Pointer to memory location from where a pointer
|
||||
* value is to be loaded and written back to.
|
||||
* @param[in] pvExchange Pointer value to be written to *ppvDestination.
|
||||
*
|
||||
* @return The initial value of *ppvDestination.
|
||||
*/
|
||||
static portFORCE_INLINE void * Atomic_SwapPointers_p32( void * volatile * ppvDestination,
|
||||
void * pvExchange )
|
||||
{
|
||||
void * pReturnValue;
|
||||
|
||||
ATOMIC_ENTER_CRITICAL();
|
||||
{
|
||||
pReturnValue = *ppvDestination;
|
||||
*ppvDestination = pvExchange;
|
||||
}
|
||||
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] ppvDestination Pointer to memory location from where a pointer
|
||||
* value is to be loaded and checked.
|
||||
* @param[in] pvExchange If condition meets, write this value to memory.
|
||||
* @param[in] pvComparand Swap condition.
|
||||
*
|
||||
* @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.
|
||||
*
|
||||
* @note This function only swaps *ppvDestination with pvExchange, if previous
|
||||
* *ppvDestination value equals pvComparand.
|
||||
*/
|
||||
static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32( void * volatile * ppvDestination,
|
||||
void * pvExchange,
|
||||
void * pvComparand )
|
||||
{
|
||||
uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
|
||||
|
||||
ATOMIC_ENTER_CRITICAL();
|
||||
{
|
||||
if( *ppvDestination == pvComparand )
|
||||
{
|
||||
*ppvDestination = pvExchange;
|
||||
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] pulAddend Pointer to memory location from where value is to be
|
||||
* loaded and written back to.
|
||||
* @param[in] ulCount Value to be added to *pulAddend.
|
||||
*
|
||||
* @return previous *pulAddend value.
|
||||
*/
|
||||
static portFORCE_INLINE uint32_t Atomic_Add_u32( uint32_t volatile * pulAddend,
|
||||
uint32_t ulCount )
|
||||
{
|
||||
uint32_t ulCurrent;
|
||||
|
||||
ATOMIC_ENTER_CRITICAL();
|
||||
{
|
||||
ulCurrent = *pulAddend;
|
||||
*pulAddend += ulCount;
|
||||
}
|
||||
ATOMIC_EXIT_CRITICAL();
|
||||
|
||||
return ulCurrent;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Atomic subtract
|
||||
*
|
||||
* @brief Atomically subtracts count from the value of the specified pointer
|
||||
* pointers to.
|
||||
*
|
||||
* @param[in,out] pulAddend Pointer to memory location from where value is to be
|
||||
* loaded and written back to.
|
||||
* @param[in] ulCount Value to be subtract from *pulAddend.
|
||||
*
|
||||
* @return previous *pulAddend value.
|
||||
*/
|
||||
static portFORCE_INLINE uint32_t Atomic_Subtract_u32( uint32_t volatile * pulAddend,
|
||||
uint32_t ulCount )
|
||||
{
|
||||
uint32_t ulCurrent;
|
||||
|
||||
ATOMIC_ENTER_CRITICAL();
|
||||
{
|
||||
ulCurrent = *pulAddend;
|
||||
*pulAddend -= ulCount;
|
||||
}
|
||||
ATOMIC_EXIT_CRITICAL();
|
||||
|
||||
return ulCurrent;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Atomic increment
|
||||
*
|
||||
* @brief Atomically increments the value of the specified pointer points to.
|
||||
*
|
||||
* @param[in,out] pulAddend Pointer to memory location from where value is to be
|
||||
* loaded and written back to.
|
||||
*
|
||||
* @return *pulAddend value before increment.
|
||||
*/
|
||||
static portFORCE_INLINE uint32_t Atomic_Increment_u32( uint32_t volatile * pulAddend )
|
||||
{
|
||||
uint32_t ulCurrent;
|
||||
|
||||
ATOMIC_ENTER_CRITICAL();
|
||||
{
|
||||
ulCurrent = *pulAddend;
|
||||
*pulAddend += 1;
|
||||
}
|
||||
ATOMIC_EXIT_CRITICAL();
|
||||
|
||||
return ulCurrent;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Atomic decrement
|
||||
*
|
||||
* @brief Atomically decrements the value of the specified pointer points to
|
||||
*
|
||||
* @param[in,out] pulAddend Pointer to memory location from where value is to be
|
||||
* loaded and written back to.
|
||||
*
|
||||
* @return *pulAddend value before decrement.
|
||||
*/
|
||||
static portFORCE_INLINE uint32_t Atomic_Decrement_u32( uint32_t volatile * pulAddend )
|
||||
{
|
||||
uint32_t ulCurrent;
|
||||
|
||||
ATOMIC_ENTER_CRITICAL();
|
||||
{
|
||||
ulCurrent = *pulAddend;
|
||||
*pulAddend -= 1;
|
||||
}
|
||||
ATOMIC_EXIT_CRITICAL();
|
||||
|
||||
return ulCurrent;
|
||||
}
|
||||
|
||||
/*----------------------------- Bitwise Logical ------------------------------*/
|
||||
|
||||
/**
|
||||
* Atomic OR
|
||||
*
|
||||
* @brief Performs an atomic OR operation on the specified values.
|
||||
*
|
||||
* @param [in, out] pulDestination Pointer to memory location from where value is
|
||||
* to be loaded and written back to.
|
||||
* @param [in] ulValue Value to be ORed with *pulDestination.
|
||||
*
|
||||
* @return The original value of *pulDestination.
|
||||
*/
|
||||
static portFORCE_INLINE uint32_t Atomic_OR_u32( uint32_t volatile * pulDestination,
|
||||
uint32_t ulValue )
|
||||
{
|
||||
uint32_t ulCurrent;
|
||||
|
||||
ATOMIC_ENTER_CRITICAL();
|
||||
{
|
||||
ulCurrent = *pulDestination;
|
||||
*pulDestination |= ulValue;
|
||||
}
|
||||
ATOMIC_EXIT_CRITICAL();
|
||||
|
||||
return ulCurrent;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Atomic AND
|
||||
*
|
||||
* @brief Performs an atomic AND operation on the specified values.
|
||||
*
|
||||
* @param [in, out] pulDestination Pointer to memory location from where value is
|
||||
* to be loaded and written back to.
|
||||
* @param [in] ulValue Value to be ANDed with *pulDestination.
|
||||
*
|
||||
* @return The original value of *pulDestination.
|
||||
*/
|
||||
static portFORCE_INLINE uint32_t Atomic_AND_u32( uint32_t volatile * pulDestination,
|
||||
uint32_t ulValue )
|
||||
{
|
||||
uint32_t ulCurrent;
|
||||
|
||||
ATOMIC_ENTER_CRITICAL();
|
||||
{
|
||||
ulCurrent = *pulDestination;
|
||||
*pulDestination &= ulValue;
|
||||
}
|
||||
ATOMIC_EXIT_CRITICAL();
|
||||
|
||||
return ulCurrent;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Atomic NAND
|
||||
*
|
||||
* @brief Performs an atomic NAND operation on the specified values.
|
||||
*
|
||||
* @param [in, out] pulDestination Pointer to memory location from where value is
|
||||
* to be loaded and written back to.
|
||||
* @param [in] ulValue Value to be NANDed with *pulDestination.
|
||||
*
|
||||
* @return The original value of *pulDestination.
|
||||
*/
|
||||
static portFORCE_INLINE uint32_t Atomic_NAND_u32( uint32_t volatile * pulDestination,
|
||||
uint32_t ulValue )
|
||||
{
|
||||
uint32_t ulCurrent;
|
||||
|
||||
ATOMIC_ENTER_CRITICAL();
|
||||
{
|
||||
ulCurrent = *pulDestination;
|
||||
*pulDestination = ~( ulCurrent & ulValue );
|
||||
}
|
||||
ATOMIC_EXIT_CRITICAL();
|
||||
|
||||
return ulCurrent;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Atomic XOR
|
||||
*
|
||||
* @brief Performs an atomic XOR operation on the specified values.
|
||||
*
|
||||
* @param [in, out] pulDestination Pointer to memory location from where value is
|
||||
* to be loaded and written back to.
|
||||
* @param [in] ulValue Value to be XORed with *pulDestination.
|
||||
*
|
||||
* @return The original value of *pulDestination.
|
||||
*/
|
||||
static portFORCE_INLINE uint32_t Atomic_XOR_u32( uint32_t volatile * pulDestination,
|
||||
uint32_t ulValue )
|
||||
{
|
||||
uint32_t ulCurrent;
|
||||
|
||||
ATOMIC_ENTER_CRITICAL();
|
||||
{
|
||||
ulCurrent = *pulDestination;
|
||||
*pulDestination ^= ulValue;
|
||||
}
|
||||
ATOMIC_EXIT_CRITICAL();
|
||||
|
||||
return ulCurrent;
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* ATOMIC_H */
|
||||
|
||||
756
pico-sensor/McuLib/FreeRTOS/Source/include/croutine.h
Normal file
756
pico-sensor/McuLib/FreeRTOS/Source/include/croutine.h
Normal file
@@ -0,0 +1,756 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CO_ROUTINE_H
|
||||
#define CO_ROUTINE_H
|
||||
|
||||
#ifndef INC_FREERTOS_H
|
||||
#error "include FreeRTOS.h must appear in source files before include croutine.h"
|
||||
#endif
|
||||
|
||||
#include "list.h"
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/* Used to hide the implementation of the co-routine control block. The
|
||||
* control block structure however has to be included in the header due to
|
||||
* the macro implementation of the co-routine functionality. */
|
||||
typedef void * CoRoutineHandle_t;
|
||||
|
||||
/* Defines the prototype to which co-routine functions must conform. */
|
||||
typedef void (* crCOROUTINE_CODE)( CoRoutineHandle_t xHandle,
|
||||
UBaseType_t uxIndex );
|
||||
|
||||
typedef struct corCoRoutineControlBlock
|
||||
{
|
||||
crCOROUTINE_CODE pxCoRoutineFunction;
|
||||
ListItem_t xGenericListItem; /**< List item used to place the CRCB in ready and blocked queues. */
|
||||
ListItem_t xEventListItem; /**< List item used to place the CRCB in event lists. */
|
||||
UBaseType_t uxPriority; /**< The priority of the co-routine in relation to other co-routines. */
|
||||
UBaseType_t uxIndex; /**< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */
|
||||
uint16_t uxState; /**< Used internally by the co-routine implementation. */
|
||||
} CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* @code{c}
|
||||
* BaseType_t xCoRoutineCreate(
|
||||
* crCOROUTINE_CODE pxCoRoutineCode,
|
||||
* UBaseType_t uxPriority,
|
||||
* UBaseType_t uxIndex
|
||||
* );
|
||||
* @endcode
|
||||
*
|
||||
* Create a new co-routine and add it to the list of co-routines that are
|
||||
* ready to run.
|
||||
*
|
||||
* @param pxCoRoutineCode Pointer to the co-routine function. Co-routine
|
||||
* functions require special syntax - see the co-routine section of the WEB
|
||||
* documentation for more information.
|
||||
*
|
||||
* @param uxPriority The priority with respect to other co-routines at which
|
||||
* the co-routine will run.
|
||||
*
|
||||
* @param uxIndex Used to distinguish between different co-routines that
|
||||
* execute the same function. See the example below and the co-routine section
|
||||
* of the WEB documentation for further information.
|
||||
*
|
||||
* @return pdPASS if the co-routine was successfully created and added to a ready
|
||||
* list, otherwise an error code defined with ProjDefs.h.
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
* // Co-routine to be created.
|
||||
* void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
* {
|
||||
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||
* // This may not be necessary for const variables.
|
||||
* static const char cLedToFlash[ 2 ] = { 5, 6 };
|
||||
* static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };
|
||||
*
|
||||
* // Must start every co-routine with a call to crSTART();
|
||||
* crSTART( xHandle );
|
||||
*
|
||||
* for( ;; )
|
||||
* {
|
||||
* // This co-routine just delays for a fixed period, then toggles
|
||||
* // an LED. Two co-routines are created using this function, so
|
||||
* // the uxIndex parameter is used to tell the co-routine which
|
||||
* // LED to flash and how int32_t to delay. This assumes xQueue has
|
||||
* // already been created.
|
||||
* vParTestToggleLED( cLedToFlash[ uxIndex ] );
|
||||
* crDELAY( xHandle, uxFlashRates[ uxIndex ] );
|
||||
* }
|
||||
*
|
||||
* // Must end every co-routine with a call to crEND();
|
||||
* crEND();
|
||||
* }
|
||||
*
|
||||
* // Function that creates two co-routines.
|
||||
* void vOtherFunction( void )
|
||||
* {
|
||||
* uint8_t ucParameterToPass;
|
||||
* TaskHandle_t xHandle;
|
||||
*
|
||||
* // Create two co-routines at priority 0. The first is given index 0
|
||||
* // so (from the code above) toggles LED 5 every 200 ticks. The second
|
||||
* // is given index 1 so toggles LED 6 every 400 ticks.
|
||||
* for( uxIndex = 0; uxIndex < 2; uxIndex++ )
|
||||
* {
|
||||
* xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
* \defgroup xCoRoutineCreate xCoRoutineCreate
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode,
|
||||
UBaseType_t uxPriority,
|
||||
UBaseType_t uxIndex );
|
||||
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* @code{c}
|
||||
* void vCoRoutineSchedule( void );
|
||||
* @endcode
|
||||
*
|
||||
* Run a co-routine.
|
||||
*
|
||||
* vCoRoutineSchedule() executes the highest priority co-routine that is able
|
||||
* to run. The co-routine will execute until it either blocks, yields or is
|
||||
* preempted by a task. Co-routines execute cooperatively so one
|
||||
* co-routine cannot be preempted by another, but can be preempted by a task.
|
||||
*
|
||||
* If an application comprises of both tasks and co-routines then
|
||||
* vCoRoutineSchedule should be called from the idle task (in an idle task
|
||||
* hook).
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
* // This idle task hook will schedule a co-routine each time it is called.
|
||||
* // The rest of the idle task will execute between co-routine calls.
|
||||
* void vApplicationIdleHook( void )
|
||||
* {
|
||||
* vCoRoutineSchedule();
|
||||
* }
|
||||
*
|
||||
* // Alternatively, if you do not require any other part of the idle task to
|
||||
* // execute, the idle task hook can call vCoRoutineSchedule() within an
|
||||
* // infinite loop.
|
||||
* void vApplicationIdleHook( void )
|
||||
* {
|
||||
* for( ;; )
|
||||
* {
|
||||
* vCoRoutineSchedule();
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
* \defgroup vCoRoutineSchedule vCoRoutineSchedule
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
void vCoRoutineSchedule( void );
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* @code{c}
|
||||
* crSTART( CoRoutineHandle_t xHandle );
|
||||
* @endcode
|
||||
*
|
||||
* This macro MUST always be called at the start of a co-routine function.
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
* // Co-routine to be created.
|
||||
* void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
* {
|
||||
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||
* static int32_t ulAVariable;
|
||||
*
|
||||
* // Must start every co-routine with a call to crSTART();
|
||||
* crSTART( xHandle );
|
||||
*
|
||||
* for( ;; )
|
||||
* {
|
||||
* // Co-routine functionality goes here.
|
||||
* }
|
||||
*
|
||||
* // Must end every co-routine with a call to crEND();
|
||||
* crEND();
|
||||
* }
|
||||
* @endcode
|
||||
* \defgroup crSTART crSTART
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crSTART( pxCRCB ) \
|
||||
switch( ( ( CRCB_t * ) ( pxCRCB ) )->uxState ) { \
|
||||
case 0:
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* @code{c}
|
||||
* crEND();
|
||||
* @endcode
|
||||
*
|
||||
* This macro MUST always be called at the end of a co-routine function.
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
* // Co-routine to be created.
|
||||
* void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
* {
|
||||
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||
* static int32_t ulAVariable;
|
||||
*
|
||||
* // Must start every co-routine with a call to crSTART();
|
||||
* crSTART( xHandle );
|
||||
*
|
||||
* for( ;; )
|
||||
* {
|
||||
* // Co-routine functionality goes here.
|
||||
* }
|
||||
*
|
||||
* // Must end every co-routine with a call to crEND();
|
||||
* crEND();
|
||||
* }
|
||||
* @endcode
|
||||
* \defgroup crSTART crSTART
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crEND() }
|
||||
|
||||
/*
|
||||
* These macros are intended for internal use by the co-routine implementation
|
||||
* only. The macros should not be used directly by application writers.
|
||||
*/
|
||||
#define crSET_STATE0( xHandle ) \
|
||||
( ( CRCB_t * ) ( xHandle ) )->uxState = ( __LINE__ * 2 ); return; \
|
||||
case ( __LINE__ * 2 ):
|
||||
#define crSET_STATE1( xHandle ) \
|
||||
( ( CRCB_t * ) ( xHandle ) )->uxState = ( ( __LINE__ * 2 ) + 1 ); return; \
|
||||
case ( ( __LINE__ * 2 ) + 1 ):
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* @code{c}
|
||||
* crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );
|
||||
* @endcode
|
||||
*
|
||||
* Delay a co-routine for a fixed period of time.
|
||||
*
|
||||
* crDELAY can only be called from the co-routine function itself - not
|
||||
* from within a function called by the co-routine function. This is because
|
||||
* co-routines do not maintain their own stack.
|
||||
*
|
||||
* @param xHandle The handle of the co-routine to delay. This is the xHandle
|
||||
* parameter of the co-routine function.
|
||||
*
|
||||
* @param xTickToDelay The number of ticks that the co-routine should delay
|
||||
* for. The actual amount of time this equates to is defined by
|
||||
* configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_PERIOD_MS
|
||||
* can be used to convert ticks to milliseconds.
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
* // Co-routine to be created.
|
||||
* void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
* {
|
||||
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||
* // This may not be necessary for const variables.
|
||||
* // We are to delay for 200ms.
|
||||
* static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;
|
||||
*
|
||||
* // Must start every co-routine with a call to crSTART();
|
||||
* crSTART( xHandle );
|
||||
*
|
||||
* for( ;; )
|
||||
* {
|
||||
* // Delay for 200ms.
|
||||
* crDELAY( xHandle, xDelayTime );
|
||||
*
|
||||
* // Do something here.
|
||||
* }
|
||||
*
|
||||
* // Must end every co-routine with a call to crEND();
|
||||
* crEND();
|
||||
* }
|
||||
* @endcode
|
||||
* \defgroup crDELAY crDELAY
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crDELAY( xHandle, xTicksToDelay ) \
|
||||
do { \
|
||||
if( ( xTicksToDelay ) > 0 ) \
|
||||
{ \
|
||||
vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \
|
||||
} \
|
||||
crSET_STATE0( ( xHandle ) ); \
|
||||
} while( 0 )
|
||||
|
||||
/**
|
||||
* @code{c}
|
||||
* crQUEUE_SEND(
|
||||
* CoRoutineHandle_t xHandle,
|
||||
* QueueHandle_t pxQueue,
|
||||
* void *pvItemToQueue,
|
||||
* TickType_t xTicksToWait,
|
||||
* BaseType_t *pxResult
|
||||
* )
|
||||
* @endcode
|
||||
*
|
||||
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
|
||||
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
|
||||
*
|
||||
* crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
|
||||
* xQueueSend() and xQueueReceive() can only be used from tasks.
|
||||
*
|
||||
* crQUEUE_SEND can only be called from the co-routine function itself - not
|
||||
* from within a function called by the co-routine function. This is because
|
||||
* co-routines do not maintain their own stack.
|
||||
*
|
||||
* See the co-routine section of the WEB documentation for information on
|
||||
* passing data between tasks and co-routines and between ISR's and
|
||||
* co-routines.
|
||||
*
|
||||
* @param xHandle The handle of the calling co-routine. This is the xHandle
|
||||
* parameter of the co-routine function.
|
||||
*
|
||||
* @param pxQueue The handle of the queue on which the data will be posted.
|
||||
* The handle is obtained as the return value when the queue is created using
|
||||
* the xQueueCreate() API function.
|
||||
*
|
||||
* @param pvItemToQueue A pointer to the data being posted onto the queue.
|
||||
* The number of bytes of each queued item is specified when the queue is
|
||||
* created. This number of bytes is copied from pvItemToQueue into the queue
|
||||
* itself.
|
||||
*
|
||||
* @param xTickToDelay The number of ticks that the co-routine should block
|
||||
* to wait for space to become available on the queue, should space not be
|
||||
* available immediately. The actual amount of time this equates to is defined
|
||||
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
|
||||
* portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see example
|
||||
* below).
|
||||
*
|
||||
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if
|
||||
* data was successfully posted onto the queue, otherwise it will be set to an
|
||||
* error defined within ProjDefs.h.
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
* // Co-routine function that blocks for a fixed period then posts a number onto
|
||||
* // a queue.
|
||||
* static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
* {
|
||||
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||
* static BaseType_t xNumberToPost = 0;
|
||||
* static BaseType_t xResult;
|
||||
*
|
||||
* // Co-routines must begin with a call to crSTART().
|
||||
* crSTART( xHandle );
|
||||
*
|
||||
* for( ;; )
|
||||
* {
|
||||
* // This assumes the queue has already been created.
|
||||
* crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
|
||||
*
|
||||
* if( xResult != pdPASS )
|
||||
* {
|
||||
* // The message was not posted!
|
||||
* }
|
||||
*
|
||||
* // Increment the number to be posted onto the queue.
|
||||
* xNumberToPost++;
|
||||
*
|
||||
* // Delay for 100 ticks.
|
||||
* crDELAY( xHandle, 100 );
|
||||
* }
|
||||
*
|
||||
* // Co-routines must end with a call to crEND().
|
||||
* crEND();
|
||||
* }
|
||||
* @endcode
|
||||
* \defgroup crQUEUE_SEND crQUEUE_SEND
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \
|
||||
do { \
|
||||
*( pxResult ) = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), ( xTicksToWait ) ); \
|
||||
if( *( pxResult ) == errQUEUE_BLOCKED ) \
|
||||
{ \
|
||||
crSET_STATE0( ( xHandle ) ); \
|
||||
*pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \
|
||||
} \
|
||||
if( *pxResult == errQUEUE_YIELD ) \
|
||||
{ \
|
||||
crSET_STATE1( ( xHandle ) ); \
|
||||
*pxResult = pdPASS; \
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* @code{c}
|
||||
* crQUEUE_RECEIVE(
|
||||
* CoRoutineHandle_t xHandle,
|
||||
* QueueHandle_t pxQueue,
|
||||
* void *pvBuffer,
|
||||
* TickType_t xTicksToWait,
|
||||
* BaseType_t *pxResult
|
||||
* )
|
||||
* @endcode
|
||||
*
|
||||
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
|
||||
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
|
||||
*
|
||||
* crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
|
||||
* xQueueSend() and xQueueReceive() can only be used from tasks.
|
||||
*
|
||||
* crQUEUE_RECEIVE can only be called from the co-routine function itself - not
|
||||
* from within a function called by the co-routine function. This is because
|
||||
* co-routines do not maintain their own stack.
|
||||
*
|
||||
* See the co-routine section of the WEB documentation for information on
|
||||
* passing data between tasks and co-routines and between ISR's and
|
||||
* co-routines.
|
||||
*
|
||||
* @param xHandle The handle of the calling co-routine. This is the xHandle
|
||||
* parameter of the co-routine function.
|
||||
*
|
||||
* @param pxQueue The handle of the queue from which the data will be received.
|
||||
* The handle is obtained as the return value when the queue is created using
|
||||
* the xQueueCreate() API function.
|
||||
*
|
||||
* @param pvBuffer The buffer into which the received item is to be copied.
|
||||
* The number of bytes of each queued item is specified when the queue is
|
||||
* created. This number of bytes is copied into pvBuffer.
|
||||
*
|
||||
* @param xTickToDelay The number of ticks that the co-routine should block
|
||||
* to wait for data to become available from the queue, should data not be
|
||||
* available immediately. The actual amount of time this equates to is defined
|
||||
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
|
||||
* portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see the
|
||||
* crQUEUE_SEND example).
|
||||
*
|
||||
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if
|
||||
* data was successfully retrieved from the queue, otherwise it will be set to
|
||||
* an error code as defined within ProjDefs.h.
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
* // A co-routine receives the number of an LED to flash from a queue. It
|
||||
* // blocks on the queue until the number is received.
|
||||
* static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
* {
|
||||
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||
* static BaseType_t xResult;
|
||||
* static UBaseType_t uxLEDToFlash;
|
||||
*
|
||||
* // All co-routines must start with a call to crSTART().
|
||||
* crSTART( xHandle );
|
||||
*
|
||||
* for( ;; )
|
||||
* {
|
||||
* // Wait for data to become available on the queue.
|
||||
* crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
|
||||
*
|
||||
* if( xResult == pdPASS )
|
||||
* {
|
||||
* // We received the LED to flash - flash it!
|
||||
* vParTestToggleLED( uxLEDToFlash );
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* crEND();
|
||||
* }
|
||||
* @endcode
|
||||
* \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \
|
||||
do { \
|
||||
*( pxResult ) = xQueueCRReceive( ( pxQueue ), ( pvBuffer ), ( xTicksToWait ) ); \
|
||||
if( *( pxResult ) == errQUEUE_BLOCKED ) \
|
||||
{ \
|
||||
crSET_STATE0( ( xHandle ) ); \
|
||||
*( pxResult ) = xQueueCRReceive( ( pxQueue ), ( pvBuffer ), 0 ); \
|
||||
} \
|
||||
if( *( pxResult ) == errQUEUE_YIELD ) \
|
||||
{ \
|
||||
crSET_STATE1( ( xHandle ) ); \
|
||||
*( pxResult ) = pdPASS; \
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* @code{c}
|
||||
* crQUEUE_SEND_FROM_ISR(
|
||||
* QueueHandle_t pxQueue,
|
||||
* void *pvItemToQueue,
|
||||
* BaseType_t xCoRoutinePreviouslyWoken
|
||||
* )
|
||||
* @endcode
|
||||
*
|
||||
* The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
|
||||
* co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
|
||||
* functions used by tasks.
|
||||
*
|
||||
* crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
|
||||
* pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
|
||||
* xQueueReceiveFromISR() can only be used to pass data between a task and and
|
||||
* ISR.
|
||||
*
|
||||
* crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue
|
||||
* that is being used from within a co-routine.
|
||||
*
|
||||
* See the co-routine section of the WEB documentation for information on
|
||||
* passing data between tasks and co-routines and between ISR's and
|
||||
* co-routines.
|
||||
*
|
||||
* @param xQueue The handle to the queue on which the item is to be posted.
|
||||
*
|
||||
* @param pvItemToQueue A pointer to the item that is to be placed on the
|
||||
* queue. The size of the items the queue will hold was defined when the
|
||||
* queue was created, so this many bytes will be copied from pvItemToQueue
|
||||
* into the queue storage area.
|
||||
*
|
||||
* @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto
|
||||
* the same queue multiple times from a single interrupt. The first call
|
||||
* should always pass in pdFALSE. Subsequent calls should pass in
|
||||
* the value returned from the previous call.
|
||||
*
|
||||
* @return pdTRUE if a co-routine was woken by posting onto the queue. This is
|
||||
* used by the ISR to determine if a context switch may be required following
|
||||
* the ISR.
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
* // A co-routine that blocks on a queue waiting for characters to be received.
|
||||
* static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
* {
|
||||
* char cRxedChar;
|
||||
* BaseType_t xResult;
|
||||
*
|
||||
* // All co-routines must start with a call to crSTART().
|
||||
* crSTART( xHandle );
|
||||
*
|
||||
* for( ;; )
|
||||
* {
|
||||
* // Wait for data to become available on the queue. This assumes the
|
||||
* // queue xCommsRxQueue has already been created!
|
||||
* crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
|
||||
*
|
||||
* // Was a character received?
|
||||
* if( xResult == pdPASS )
|
||||
* {
|
||||
* // Process the character here.
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // All co-routines must end with a call to crEND().
|
||||
* crEND();
|
||||
* }
|
||||
*
|
||||
* // An ISR that uses a queue to send characters received on a serial port to
|
||||
* // a co-routine.
|
||||
* void vUART_ISR( void )
|
||||
* {
|
||||
* char cRxedChar;
|
||||
* BaseType_t xCRWokenByPost = pdFALSE;
|
||||
*
|
||||
* // We loop around reading characters until there are none left in the UART.
|
||||
* while( UART_RX_REG_NOT_EMPTY() )
|
||||
* {
|
||||
* // Obtain the character from the UART.
|
||||
* cRxedChar = UART_RX_REG;
|
||||
*
|
||||
* // Post the character onto a queue. xCRWokenByPost will be pdFALSE
|
||||
* // the first time around the loop. If the post causes a co-routine
|
||||
* // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
|
||||
* // In this manner we can ensure that if more than one co-routine is
|
||||
* // blocked on the queue only one is woken by this ISR no matter how
|
||||
* // many characters are posted to the queue.
|
||||
* xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
* \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) \
|
||||
xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) )
|
||||
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* @code{c}
|
||||
* crQUEUE_SEND_FROM_ISR(
|
||||
* QueueHandle_t pxQueue,
|
||||
* void *pvBuffer,
|
||||
* BaseType_t * pxCoRoutineWoken
|
||||
* )
|
||||
* @endcode
|
||||
*
|
||||
* The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
|
||||
* co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
|
||||
* functions used by tasks.
|
||||
*
|
||||
* crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
|
||||
* pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
|
||||
* xQueueReceiveFromISR() can only be used to pass data between a task and and
|
||||
* ISR.
|
||||
*
|
||||
* crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data
|
||||
* from a queue that is being used from within a co-routine (a co-routine
|
||||
* posted to the queue).
|
||||
*
|
||||
* See the co-routine section of the WEB documentation for information on
|
||||
* passing data between tasks and co-routines and between ISR's and
|
||||
* co-routines.
|
||||
*
|
||||
* @param xQueue The handle to the queue on which the item is to be posted.
|
||||
*
|
||||
* @param pvBuffer A pointer to a buffer into which the received item will be
|
||||
* placed. The size of the items the queue will hold was defined when the
|
||||
* queue was created, so this many bytes will be copied from the queue into
|
||||
* pvBuffer.
|
||||
*
|
||||
* @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become
|
||||
* available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a
|
||||
* co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise
|
||||
* *pxCoRoutineWoken will remain unchanged.
|
||||
*
|
||||
* @return pdTRUE an item was successfully received from the queue, otherwise
|
||||
* pdFALSE.
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
* // A co-routine that posts a character to a queue then blocks for a fixed
|
||||
* // period. The character is incremented each time.
|
||||
* static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
* {
|
||||
* // cChar holds its value while this co-routine is blocked and must therefore
|
||||
* // be declared static.
|
||||
* static char cCharToTx = 'a';
|
||||
* BaseType_t xResult;
|
||||
*
|
||||
* // All co-routines must start with a call to crSTART().
|
||||
* crSTART( xHandle );
|
||||
*
|
||||
* for( ;; )
|
||||
* {
|
||||
* // Send the next character to the queue.
|
||||
* crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
|
||||
*
|
||||
* if( xResult == pdPASS )
|
||||
* {
|
||||
* // The character was successfully posted to the queue.
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* // Could not post the character to the queue.
|
||||
* }
|
||||
*
|
||||
* // Enable the UART Tx interrupt to cause an interrupt in this
|
||||
* // hypothetical UART. The interrupt will obtain the character
|
||||
* // from the queue and send it.
|
||||
* ENABLE_RX_INTERRUPT();
|
||||
*
|
||||
* // Increment to the next character then block for a fixed period.
|
||||
* // cCharToTx will maintain its value across the delay as it is
|
||||
* // declared static.
|
||||
* cCharToTx++;
|
||||
* if( cCharToTx > 'x' )
|
||||
* {
|
||||
* cCharToTx = 'a';
|
||||
* }
|
||||
* crDELAY( 100 );
|
||||
* }
|
||||
*
|
||||
* // All co-routines must end with a call to crEND().
|
||||
* crEND();
|
||||
* }
|
||||
*
|
||||
* // An ISR that uses a queue to receive characters to send on a UART.
|
||||
* void vUART_ISR( void )
|
||||
* {
|
||||
* char cCharToTx;
|
||||
* BaseType_t xCRWokenByPost = pdFALSE;
|
||||
*
|
||||
* while( UART_TX_REG_EMPTY() )
|
||||
* {
|
||||
* // Are there any characters in the queue waiting to be sent?
|
||||
* // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
|
||||
* // is woken by the post - ensuring that only a single co-routine is
|
||||
* // woken no matter how many times we go around this loop.
|
||||
* if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
|
||||
* {
|
||||
* SEND_CHARACTER( cCharToTx );
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
* \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) \
|
||||
xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) )
|
||||
|
||||
/*
|
||||
* This function is intended for internal use by the co-routine macros only.
|
||||
* The macro nature of the co-routine implementation requires that the
|
||||
* prototype appears here. The function should not be used by application
|
||||
* writers.
|
||||
*
|
||||
* Removes the current co-routine from its ready list and places it in the
|
||||
* appropriate delayed list.
|
||||
*/
|
||||
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay,
|
||||
List_t * pxEventList );
|
||||
|
||||
/*
|
||||
* This function is intended for internal use by the queue implementation only.
|
||||
* The function should not be used by application writers.
|
||||
*
|
||||
* Removes the highest priority co-routine from the event list and places it in
|
||||
* the pending ready list.
|
||||
*/
|
||||
BaseType_t xCoRoutineRemoveFromEventList( const List_t * pxEventList );
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* CO_ROUTINE_H */
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DEPRECATED_DEFINITIONS_H
|
||||
#define DEPRECATED_DEFINITIONS_H
|
||||
|
||||
|
||||
/* Each FreeRTOS port has a unique portmacro.h header file. Originally a
|
||||
* pre-processor definition was used to ensure the pre-processor found the correct
|
||||
* portmacro.h file for the port being used. That scheme was deprecated in favour
|
||||
* of setting the compiler's include path such that it found the correct
|
||||
* portmacro.h file - removing the need for the constant and allowing the
|
||||
* portmacro.h file to be located anywhere in relation to the port being used. The
|
||||
* definitions below remain in the code for backward compatibility only. New
|
||||
* projects should not use them. */
|
||||
|
||||
#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT
|
||||
#include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h"
|
||||
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 )();
|
||||
#endif
|
||||
|
||||
#ifdef GCC_MEGA_AVR
|
||||
#include "../portable/GCC/ATMega323/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef IAR_MEGA_AVR
|
||||
#include "../portable/IAR/ATMega323/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef MPLAB_PIC24_PORT
|
||||
#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef MPLAB_DSPIC_PORT
|
||||
#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef MPLAB_PIC18F_PORT
|
||||
#include "../../Source/portable/MPLAB/PIC18F/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef MPLAB_PIC32MX_PORT
|
||||
#include "../../Source/portable/MPLAB/PIC32MX/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef _FEDPICC
|
||||
#include "libFreeRTOS/Include/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef SDCC_CYGNAL
|
||||
#include "../../Source/portable/SDCC/Cygnal/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_ARM7
|
||||
#include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_ARM7_ECLIPSE
|
||||
#include "portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef ROWLEY_LPC23xx
|
||||
#include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef IAR_MSP430
|
||||
#include "..\..\Source\portable\IAR\MSP430\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_MSP430
|
||||
#include "../../Source/portable/GCC/MSP430F449/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef ROWLEY_MSP430
|
||||
#include "../../Source/portable/Rowley/MSP430F449/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef ARM7_LPC21xx_KEIL_RVDS
|
||||
#include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef SAM7_GCC
|
||||
#include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef SAM7_IAR
|
||||
#include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef SAM9XE_IAR
|
||||
#include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef LPC2000_IAR
|
||||
#include "..\..\Source\portable\IAR\LPC2000\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef STR71X_IAR
|
||||
#include "..\..\Source\portable\IAR\STR71x\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef STR75X_IAR
|
||||
#include "..\..\Source\portable\IAR\STR75x\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef STR75X_GCC
|
||||
#include "..\..\Source\portable\GCC\STR75x\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef STR91X_IAR
|
||||
#include "..\..\Source\portable\IAR\STR91x\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_H8S
|
||||
#include "../../Source/portable/GCC/H8S2329/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_AT91FR40008
|
||||
#include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef RVDS_ARMCM3_LM3S102
|
||||
#include "../../Source/portable/RVDS/ARM_CM3/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_ARMCM3_LM3S102
|
||||
#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_ARMCM3
|
||||
#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef IAR_ARM_CM3
|
||||
#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef IAR_ARMCM3_LM
|
||||
#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef HCS12_CODE_WARRIOR
|
||||
#include "../../Source/portable/CodeWarrior/HCS12/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef MICROBLAZE_GCC
|
||||
#include "../../Source/portable/GCC/MicroBlaze/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef TERN_EE
|
||||
#include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_HCS12
|
||||
#include "../../Source/portable/GCC/HCS12/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_MCF5235
|
||||
#include "../../Source/portable/GCC/MCF5235/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef COLDFIRE_V2_GCC
|
||||
#include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef COLDFIRE_V2_CODEWARRIOR
|
||||
#include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_PPC405
|
||||
#include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_PPC440
|
||||
#include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef _16FX_SOFTUNE
|
||||
#include "..\..\Source\portable\Softune\MB96340\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef BCC_INDUSTRIAL_PC_PORT
|
||||
|
||||
/* A short file name has to be used in place of the normal
|
||||
* FreeRTOSConfig.h when using the Borland compiler. */
|
||||
#include "frconfig.h"
|
||||
#include "..\portable\BCC\16BitDOS\PC\prtmacro.h"
|
||||
typedef void ( __interrupt __far * pxISR )();
|
||||
#endif
|
||||
|
||||
#ifdef BCC_FLASH_LITE_186_PORT
|
||||
|
||||
/* A short file name has to be used in place of the normal
|
||||
* FreeRTOSConfig.h when using the Borland compiler. */
|
||||
#include "frconfig.h"
|
||||
#include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h"
|
||||
typedef void ( __interrupt __far * pxISR )();
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifdef __AVR32_AVR32A__
|
||||
#include "portmacro.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __ICCAVR32__
|
||||
#ifdef __CORE__
|
||||
#if __CORE__ == __AVR32A__
|
||||
#include "portmacro.h"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __91467D
|
||||
#include "portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef __96340
|
||||
#include "portmacro.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __IAR_V850ES_Fx3__
|
||||
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef __IAR_V850ES_Jx3__
|
||||
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef __IAR_V850ES_Jx3_L__
|
||||
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef __IAR_V850ES_Jx2__
|
||||
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef __IAR_V850ES_Hx2__
|
||||
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef __IAR_78K0R_Kx3__
|
||||
#include "../../Source/portable/IAR/78K0R/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef __IAR_78K0R_Kx3L__
|
||||
#include "../../Source/portable/IAR/78K0R/portmacro.h"
|
||||
#endif
|
||||
|
||||
#endif /* DEPRECATED_DEFINITIONS_H */
|
||||
|
||||
828
pico-sensor/McuLib/FreeRTOS/Source/include/event_groups.h
Normal file
828
pico-sensor/McuLib/FreeRTOS/Source/include/event_groups.h
Normal file
@@ -0,0 +1,828 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EVENT_GROUPS_H
|
||||
#define EVENT_GROUPS_H
|
||||
|
||||
#ifndef INC_FREERTOS_H
|
||||
#error "include FreeRTOS.h" must appear in source files before "include event_groups.h"
|
||||
#endif
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "timers.h"
|
||||
|
||||
/* The following bit fields convey control information in a task's event list
|
||||
* item value. It is important they don't clash with the
|
||||
* taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
|
||||
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
|
||||
#define eventCLEAR_EVENTS_ON_EXIT_BIT ( ( uint16_t ) 0x0100U )
|
||||
#define eventUNBLOCKED_DUE_TO_BIT_SET ( ( uint16_t ) 0x0200U )
|
||||
#define eventWAIT_FOR_ALL_BITS ( ( uint16_t ) 0x0400U )
|
||||
#define eventEVENT_BITS_CONTROL_BYTES ( ( uint16_t ) 0xff00U )
|
||||
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
|
||||
#define eventCLEAR_EVENTS_ON_EXIT_BIT ( ( uint32_t ) 0x01000000UL )
|
||||
#define eventUNBLOCKED_DUE_TO_BIT_SET ( ( uint32_t ) 0x02000000UL )
|
||||
#define eventWAIT_FOR_ALL_BITS ( ( uint32_t ) 0x04000000UL )
|
||||
#define eventEVENT_BITS_CONTROL_BYTES ( ( uint32_t ) 0xff000000UL )
|
||||
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_64_BITS )
|
||||
#define eventCLEAR_EVENTS_ON_EXIT_BIT ( ( uint64_t ) 0x0100000000000000ULL )
|
||||
#define eventUNBLOCKED_DUE_TO_BIT_SET ( ( uint64_t ) 0x0200000000000000ULL )
|
||||
#define eventWAIT_FOR_ALL_BITS ( ( uint64_t ) 0x0400000000000000ULL )
|
||||
#define eventEVENT_BITS_CONTROL_BYTES ( ( uint64_t ) 0xff00000000000000ULL )
|
||||
#endif /* if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/**
|
||||
* An event group is a collection of bits to which an application can assign a
|
||||
* meaning. For example, an application may create an event group to convey
|
||||
* the status of various CAN bus related events in which bit 0 might mean "A CAN
|
||||
* message has been received and is ready for processing", bit 1 might mean "The
|
||||
* application has queued a message that is ready for sending onto the CAN
|
||||
* network", and bit 2 might mean "It is time to send a SYNC message onto the
|
||||
* CAN network" etc. A task can then test the bit values to see which events
|
||||
* are active, and optionally enter the Blocked state to wait for a specified
|
||||
* bit or a group of specified bits to be active. To continue the CAN bus
|
||||
* example, a CAN controlling task can enter the Blocked state (and therefore
|
||||
* not consume any processing time) until either bit 0, bit 1 or bit 2 are
|
||||
* active, at which time the bit that was actually active would inform the task
|
||||
* which action it had to take (process a received message, send a message, or
|
||||
* send a SYNC).
|
||||
*
|
||||
* The event groups implementation contains intelligence to avoid race
|
||||
* conditions that would otherwise occur were an application to use a simple
|
||||
* variable for the same purpose. This is particularly important with respect
|
||||
* to when a bit within an event group is to be cleared, and when bits have to
|
||||
* be set and then tested atomically - as is the case where event groups are
|
||||
* used to create a synchronisation point between multiple tasks (a
|
||||
* 'rendezvous').
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*
|
||||
* Type by which event groups are referenced. For example, a call to
|
||||
* 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;
|
||||
|
||||
/*
|
||||
* The type that holds event bits always matches TickType_t - therefore the
|
||||
* number of bits it holds is set by configTICK_TYPE_WIDTH_IN_BITS (16 bits if set to 0,
|
||||
* 32 bits if set to 1, 64 bits if set to 2.
|
||||
*
|
||||
* \defgroup EventBits_t EventBits_t
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
typedef TickType_t EventBits_t;
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
* @code{c}
|
||||
* EventGroupHandle_t xEventGroupCreate( void );
|
||||
* @endcode
|
||||
*
|
||||
* Create a new event group.
|
||||
*
|
||||
* Internally, within the FreeRTOS implementation, event groups use a [small]
|
||||
* block of memory, in which the event group's structure is stored. If an event
|
||||
* groups is created using xEventGroupCreate() then the required memory is
|
||||
* automatically dynamically allocated inside the xEventGroupCreate() function.
|
||||
* (see https://www.FreeRTOS.org/a00111.html). If an event group is created
|
||||
* using xEventGroupCreateStatic() then the application writer must instead
|
||||
* provide the memory that will get used by the event group.
|
||||
* xEventGroupCreateStatic() therefore allows an event group to be created
|
||||
* without using any dynamic memory allocation.
|
||||
*
|
||||
* Although event groups are not related to ticks, for internal implementation
|
||||
* reasons the number of bits available for use in an event group is dependent
|
||||
* on the configTICK_TYPE_WIDTH_IN_BITS setting in FreeRTOSConfig.h. If
|
||||
* configTICK_TYPE_WIDTH_IN_BITS is 0 then each event group contains 8 usable bits (bit
|
||||
* 0 to bit 7). If configTICK_TYPE_WIDTH_IN_BITS is set to 1 then each event group has
|
||||
* 24 usable bits (bit 0 to bit 23). If configTICK_TYPE_WIDTH_IN_BITS is set to 2 then
|
||||
* each event group has 56 usable bits (bit 0 to bit 53). The EventBits_t type
|
||||
* is used to store event bits within an event group.
|
||||
*
|
||||
* @return If the event group was created then a handle to the event group is
|
||||
* returned. If there was insufficient FreeRTOS heap available to create the
|
||||
* event group then NULL is returned. See https://www.FreeRTOS.org/a00111.html
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
* // Declare a variable to hold the created event group.
|
||||
* EventGroupHandle_t xCreatedEventGroup;
|
||||
*
|
||||
* // Attempt to create the event group.
|
||||
* xCreatedEventGroup = xEventGroupCreate();
|
||||
*
|
||||
* // Was the event group created successfully?
|
||||
* if( xCreatedEventGroup == NULL )
|
||||
* {
|
||||
* // The event group was not created because there was insufficient
|
||||
* // FreeRTOS heap available.
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* // The event group was created.
|
||||
* }
|
||||
* @endcode
|
||||
* \defgroup xEventGroupCreate xEventGroupCreate
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||
EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
* @code{c}
|
||||
* EventGroupHandle_t xEventGroupCreateStatic( EventGroupHandle_t * pxEventGroupBuffer );
|
||||
* @endcode
|
||||
*
|
||||
* Create a new event group.
|
||||
*
|
||||
* Internally, within the FreeRTOS implementation, event groups use a [small]
|
||||
* block of memory, in which the event group's structure is stored. If an event
|
||||
* groups is created using xEventGroupCreate() then the required memory is
|
||||
* automatically dynamically allocated inside the xEventGroupCreate() function.
|
||||
* (see https://www.FreeRTOS.org/a00111.html). If an event group is created
|
||||
* using xEventGroupCreateStatic() then the application writer must instead
|
||||
* provide the memory that will get used by the event group.
|
||||
* xEventGroupCreateStatic() therefore allows an event group to be created
|
||||
* without using any dynamic memory allocation.
|
||||
*
|
||||
* Although event groups are not related to ticks, for internal implementation
|
||||
* reasons the number of bits available for use in an event group is dependent
|
||||
* on the configTICK_TYPE_WIDTH_IN_BITS setting in FreeRTOSConfig.h. If
|
||||
* configTICK_TYPE_WIDTH_IN_BITS is 0 then each event group contains 8 usable bits (bit
|
||||
* 0 to bit 7). If configTICK_TYPE_WIDTH_IN_BITS is set to 1 then each event group has
|
||||
* 24 usable bits (bit 0 to bit 23). If configTICK_TYPE_WIDTH_IN_BITS is set to 2 then
|
||||
* each event group has 56 usable bits (bit 0 to bit 53). The EventBits_t type
|
||||
* is used to store event bits within an event group.
|
||||
*
|
||||
* @param pxEventGroupBuffer pxEventGroupBuffer must point to a variable of type
|
||||
* StaticEventGroup_t, which will be then be used to hold the event group's data
|
||||
* structures, removing the need for the memory to be allocated dynamically.
|
||||
*
|
||||
* @return If the event group was created then a handle to the event group is
|
||||
* returned. If pxEventGroupBuffer was NULL then NULL is returned.
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
* // StaticEventGroup_t is a publicly accessible structure that has the same
|
||||
* // size and alignment requirements as the real event group structure. It is
|
||||
* // provided as a mechanism for applications to know the size of the event
|
||||
* // group (which is dependent on the architecture and configuration file
|
||||
* // settings) without breaking the strict data hiding policy by exposing the
|
||||
* // real event group internals. This StaticEventGroup_t variable is passed
|
||||
* // into the xSemaphoreCreateEventGroupStatic() function and is used to store
|
||||
* // the event group's data structures
|
||||
* StaticEventGroup_t xEventGroupBuffer;
|
||||
*
|
||||
* // Create the event group without dynamically allocating any memory.
|
||||
* xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
|
||||
* @endcode
|
||||
*/
|
||||
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
* @code{c}
|
||||
* EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
|
||||
* const EventBits_t uxBitsToWaitFor,
|
||||
* const BaseType_t xClearOnExit,
|
||||
* const BaseType_t xWaitForAllBits,
|
||||
* const TickType_t xTicksToWait );
|
||||
* @endcode
|
||||
*
|
||||
* [Potentially] block to wait for one or more bits to be set within a
|
||||
* previously created event group.
|
||||
*
|
||||
* This function cannot be called from an interrupt.
|
||||
*
|
||||
* @param xEventGroup The event group in which the bits are being tested. The
|
||||
* event group must have previously been created using a call to
|
||||
* xEventGroupCreate().
|
||||
*
|
||||
* @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
|
||||
* inside the event group. For example, to wait for bit 0 and/or bit 2 set
|
||||
* uxBitsToWaitFor to 0x05. To wait for bits 0 and/or bit 1 and/or bit 2 set
|
||||
* uxBitsToWaitFor to 0x07. Etc.
|
||||
*
|
||||
* @param xClearOnExit If xClearOnExit is set to pdTRUE then any bits within
|
||||
* uxBitsToWaitFor that are set within the event group will be cleared before
|
||||
* xEventGroupWaitBits() returns if the wait condition was met (if the function
|
||||
* returns for a reason other than a timeout). If xClearOnExit is set to
|
||||
* pdFALSE then the bits set in the event group are not altered when the call to
|
||||
* xEventGroupWaitBits() returns.
|
||||
*
|
||||
* @param xWaitForAllBits If xWaitForAllBits is set to pdTRUE then
|
||||
* xEventGroupWaitBits() will return when either all the bits in uxBitsToWaitFor
|
||||
* are set or the specified block time expires. If xWaitForAllBits is set to
|
||||
* pdFALSE then xEventGroupWaitBits() will return when any one of the bits set
|
||||
* in uxBitsToWaitFor is set or the specified block time expires. The block
|
||||
* time is specified by the xTicksToWait parameter.
|
||||
*
|
||||
* @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
|
||||
* for one/all (depending on the xWaitForAllBits value) of the bits specified by
|
||||
* uxBitsToWaitFor to become set. A value of portMAX_DELAY can be used to block
|
||||
* indefinitely (provided INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h).
|
||||
*
|
||||
* @return The value of the event group at the time either the bits being waited
|
||||
* for became set, or the block time expired. Test the return value to know
|
||||
* which bits were set. If xEventGroupWaitBits() returned because its timeout
|
||||
* expired then not all the bits being waited for will be set. If
|
||||
* xEventGroupWaitBits() returned because the bits it was waiting for were set
|
||||
* then the returned value is the event group value before any bits were
|
||||
* automatically cleared in the case that xClearOnExit parameter was set to
|
||||
* pdTRUE.
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
* #define BIT_0 ( 1 << 0 )
|
||||
* #define BIT_4 ( 1 << 4 )
|
||||
*
|
||||
* void aFunction( EventGroupHandle_t xEventGroup )
|
||||
* {
|
||||
* EventBits_t uxBits;
|
||||
* const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
|
||||
*
|
||||
* // Wait a maximum of 100ms for either bit 0 or bit 4 to be set within
|
||||
* // the event group. Clear the bits before exiting.
|
||||
* uxBits = xEventGroupWaitBits(
|
||||
* xEventGroup, // The event group being tested.
|
||||
* BIT_0 | BIT_4, // The bits within the event group to wait for.
|
||||
* pdTRUE, // BIT_0 and BIT_4 should be cleared before returning.
|
||||
* pdFALSE, // Don't wait for both bits, either bit will do.
|
||||
* xTicksToWait ); // Wait a maximum of 100ms for either bit to be set.
|
||||
*
|
||||
* if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
|
||||
* {
|
||||
* // xEventGroupWaitBits() returned because both bits were set.
|
||||
* }
|
||||
* else if( ( uxBits & BIT_0 ) != 0 )
|
||||
* {
|
||||
* // xEventGroupWaitBits() returned because just BIT_0 was set.
|
||||
* }
|
||||
* else if( ( uxBits & BIT_4 ) != 0 )
|
||||
* {
|
||||
* // xEventGroupWaitBits() returned because just BIT_4 was set.
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* // xEventGroupWaitBits() returned because xTicksToWait ticks passed
|
||||
* // without either BIT_0 or BIT_4 becoming set.
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
* \defgroup xEventGroupWaitBits xEventGroupWaitBits
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToWaitFor,
|
||||
const BaseType_t xClearOnExit,
|
||||
const BaseType_t xWaitForAllBits,
|
||||
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
* @code{c}
|
||||
* EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
|
||||
* @endcode
|
||||
*
|
||||
* Clear bits within an event group. This function cannot be called from an
|
||||
* interrupt.
|
||||
*
|
||||
* @param xEventGroup The event group in which the bits are to be cleared.
|
||||
*
|
||||
* @param uxBitsToClear A bitwise value that indicates the bit or bits to clear
|
||||
* in the event group. For example, to clear bit 3 only, set uxBitsToClear to
|
||||
* 0x08. To clear bit 3 and bit 0 set uxBitsToClear to 0x09.
|
||||
*
|
||||
* @return The value of the event group before the specified bits were cleared.
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
* #define BIT_0 ( 1 << 0 )
|
||||
* #define BIT_4 ( 1 << 4 )
|
||||
*
|
||||
* void aFunction( EventGroupHandle_t xEventGroup )
|
||||
* {
|
||||
* EventBits_t uxBits;
|
||||
*
|
||||
* // Clear bit 0 and bit 4 in xEventGroup.
|
||||
* uxBits = xEventGroupClearBits(
|
||||
* xEventGroup, // The event group being updated.
|
||||
* BIT_0 | BIT_4 );// The bits being cleared.
|
||||
*
|
||||
* if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
|
||||
* {
|
||||
* // Both bit 0 and bit 4 were set before xEventGroupClearBits() was
|
||||
* // called. Both will now be clear (not set).
|
||||
* }
|
||||
* else if( ( uxBits & BIT_0 ) != 0 )
|
||||
* {
|
||||
* // Bit 0 was set before xEventGroupClearBits() was called. It will
|
||||
* // now be clear.
|
||||
* }
|
||||
* else if( ( uxBits & BIT_4 ) != 0 )
|
||||
* {
|
||||
* // Bit 4 was set before xEventGroupClearBits() was called. It will
|
||||
* // now be clear.
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* // Neither bit 0 nor bit 4 were set in the first place.
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
* \defgroup xEventGroupClearBits xEventGroupClearBits
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
* @code{c}
|
||||
* BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
|
||||
* @endcode
|
||||
*
|
||||
* A version of xEventGroupClearBits() that can be called from an interrupt.
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* task.
|
||||
*
|
||||
* @note If this function returns pdPASS then the timer task is ready to run
|
||||
* and a portYIELD_FROM_ISR(pdTRUE) should be executed to perform the needed
|
||||
* clear on the event group. This behavior is different from
|
||||
* xEventGroupSetBitsFromISR because the parameter xHigherPriorityTaskWoken is
|
||||
* not present.
|
||||
*
|
||||
* @param xEventGroup The event group in which the bits are to be cleared.
|
||||
*
|
||||
* @param uxBitsToClear A bitwise value that indicates the bit or bits to clear.
|
||||
* 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
|
||||
* if the timer service queue was full.
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
* #define BIT_0 ( 1 << 0 )
|
||||
* #define BIT_4 ( 1 << 4 )
|
||||
*
|
||||
* // An event group which it is assumed has already been created by a call to
|
||||
* // xEventGroupCreate().
|
||||
* EventGroupHandle_t xEventGroup;
|
||||
*
|
||||
* void anInterruptHandler( void )
|
||||
* {
|
||||
* // Clear bit 0 and bit 4 in xEventGroup.
|
||||
* xResult = xEventGroupClearBitsFromISR(
|
||||
* xEventGroup, // The event group being updated.
|
||||
* BIT_0 | BIT_4 ); // The bits being set.
|
||||
*
|
||||
* if( xResult == pdPASS )
|
||||
* {
|
||||
* // The message was posted successfully.
|
||||
* portYIELD_FROM_ISR(pdTRUE);
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
* \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
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
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
* @code{c}
|
||||
* EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
|
||||
* @endcode
|
||||
*
|
||||
* Set bits within an event group.
|
||||
* This function cannot be called from an interrupt. xEventGroupSetBitsFromISR()
|
||||
* is a version that can be called from an interrupt.
|
||||
*
|
||||
* Setting bits in an event group will automatically unblock tasks that are
|
||||
* blocked waiting for the bits.
|
||||
*
|
||||
* @param xEventGroup The event group in which the bits are to be set.
|
||||
*
|
||||
* @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
|
||||
* For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3
|
||||
* and bit 0 set uxBitsToSet to 0x09.
|
||||
*
|
||||
* @return The value of the event group at the time the call to
|
||||
* xEventGroupSetBits() returns. There are two reasons why the returned value
|
||||
* might have the bits specified by the uxBitsToSet parameter cleared. First,
|
||||
* if setting a bit results in a task that was waiting for the bit leaving the
|
||||
* blocked state then it is possible the bit will be cleared automatically
|
||||
* (see the xClearBitOnExit parameter of xEventGroupWaitBits()). Second, any
|
||||
* unblocked (or otherwise Ready state) task that has a priority above that of
|
||||
* the task that called xEventGroupSetBits() will execute and may change the
|
||||
* event group value before the call to xEventGroupSetBits() returns.
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
* #define BIT_0 ( 1 << 0 )
|
||||
* #define BIT_4 ( 1 << 4 )
|
||||
*
|
||||
* void aFunction( EventGroupHandle_t xEventGroup )
|
||||
* {
|
||||
* EventBits_t uxBits;
|
||||
*
|
||||
* // Set bit 0 and bit 4 in xEventGroup.
|
||||
* uxBits = xEventGroupSetBits(
|
||||
* xEventGroup, // The event group being updated.
|
||||
* BIT_0 | BIT_4 );// The bits being set.
|
||||
*
|
||||
* if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
|
||||
* {
|
||||
* // Both bit 0 and bit 4 remained set when the function returned.
|
||||
* }
|
||||
* else if( ( uxBits & BIT_0 ) != 0 )
|
||||
* {
|
||||
* // Bit 0 remained set when the function returned, but bit 4 was
|
||||
* // cleared. It might be that bit 4 was cleared automatically as a
|
||||
* // task that was waiting for bit 4 was removed from the Blocked
|
||||
* // state.
|
||||
* }
|
||||
* else if( ( uxBits & BIT_4 ) != 0 )
|
||||
* {
|
||||
* // Bit 4 remained set when the function returned, but bit 0 was
|
||||
* // cleared. It might be that bit 0 was cleared automatically as a
|
||||
* // task that was waiting for bit 0 was removed from the Blocked
|
||||
* // state.
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* // Neither bit 0 nor bit 4 remained set. It might be that a task
|
||||
* // was waiting for both of the bits to be set, and the bits were
|
||||
* // cleared as the task left the Blocked state.
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
* \defgroup xEventGroupSetBits xEventGroupSetBits
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
* @code{c}
|
||||
* BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
|
||||
* @endcode
|
||||
*
|
||||
* A version of xEventGroupSetBits() that can be called from an interrupt.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @param xEventGroup The event group in which the bits are to be set.
|
||||
*
|
||||
* @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
|
||||
* For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3
|
||||
* and bit 0 set uxBitsToSet to 0x09.
|
||||
*
|
||||
* @param pxHigherPriorityTaskWoken As mentioned above, calling this function
|
||||
* will result in a message being sent to the timer daemon task. If the
|
||||
* priority of the timer daemon task is higher than the priority of the
|
||||
* currently running task (the task the interrupt interrupted) then
|
||||
* *pxHigherPriorityTaskWoken will be set to pdTRUE by
|
||||
* xEventGroupSetBitsFromISR(), indicating that a context switch should be
|
||||
* requested before the interrupt exits. For that reason
|
||||
* *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
|
||||
* if the timer service queue was full.
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
* #define BIT_0 ( 1 << 0 )
|
||||
* #define BIT_4 ( 1 << 4 )
|
||||
*
|
||||
* // An event group which it is assumed has already been created by a call to
|
||||
* // xEventGroupCreate().
|
||||
* EventGroupHandle_t xEventGroup;
|
||||
*
|
||||
* void anInterruptHandler( void )
|
||||
* {
|
||||
* BaseType_t xHigherPriorityTaskWoken, xResult;
|
||||
*
|
||||
* // xHigherPriorityTaskWoken must be initialised to pdFALSE.
|
||||
* xHigherPriorityTaskWoken = pdFALSE;
|
||||
*
|
||||
* // Set bit 0 and bit 4 in xEventGroup.
|
||||
* xResult = xEventGroupSetBitsFromISR(
|
||||
* xEventGroup, // The event group being updated.
|
||||
* BIT_0 | BIT_4 // The bits being set.
|
||||
* &xHigherPriorityTaskWoken );
|
||||
*
|
||||
* // Was the message posted successfully?
|
||||
* if( xResult == pdPASS )
|
||||
* {
|
||||
* // If xHigherPriorityTaskWoken is now set to pdTRUE then a context
|
||||
* // switch should be requested. The macro used is port specific and
|
||||
* // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
|
||||
* // refer to the documentation page for the port being used.
|
||||
* portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
* \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
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
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
* @code{c}
|
||||
* EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
|
||||
* const EventBits_t uxBitsToSet,
|
||||
* const EventBits_t uxBitsToWaitFor,
|
||||
* TickType_t xTicksToWait );
|
||||
* @endcode
|
||||
*
|
||||
* Atomically set bits within an event group, then wait for a combination of
|
||||
* bits to be set within the same event group. This functionality is typically
|
||||
* used to synchronise multiple tasks, where each task has to wait for the other
|
||||
* tasks to reach a synchronisation point before proceeding.
|
||||
*
|
||||
* This function cannot be used from an interrupt.
|
||||
*
|
||||
* The function will return before its block time expires if the bits specified
|
||||
* by the uxBitsToWait parameter are set, or become set within that time. In
|
||||
* this case all the bits specified by uxBitsToWait will be automatically
|
||||
* cleared before the function returns.
|
||||
*
|
||||
* @param xEventGroup The event group in which the bits are being tested. The
|
||||
* event group must have previously been created using a call to
|
||||
* xEventGroupCreate().
|
||||
*
|
||||
* @param uxBitsToSet The bits to set in the event group before determining
|
||||
* if, and possibly waiting for, all the bits specified by the uxBitsToWait
|
||||
* parameter are set.
|
||||
*
|
||||
* @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
|
||||
* inside the event group. For example, to wait for bit 0 and bit 2 set
|
||||
* uxBitsToWaitFor to 0x05. To wait for bits 0 and bit 1 and bit 2 set
|
||||
* uxBitsToWaitFor to 0x07. Etc.
|
||||
*
|
||||
* @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
|
||||
* for all of the bits specified by uxBitsToWaitFor to become set.
|
||||
*
|
||||
* @return The value of the event group at the time either the bits being waited
|
||||
* for became set, or the block time expired. Test the return value to know
|
||||
* which bits were set. If xEventGroupSync() returned because its timeout
|
||||
* expired then not all the bits being waited for will be set. If
|
||||
* xEventGroupSync() returned because all the bits it was waiting for were
|
||||
* set then the returned value is the event group value before any bits were
|
||||
* automatically cleared.
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
* // Bits used by the three tasks.
|
||||
* #define TASK_0_BIT ( 1 << 0 )
|
||||
* #define TASK_1_BIT ( 1 << 1 )
|
||||
* #define TASK_2_BIT ( 1 << 2 )
|
||||
*
|
||||
* #define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )
|
||||
*
|
||||
* // Use an event group to synchronise three tasks. It is assumed this event
|
||||
* // group has already been created elsewhere.
|
||||
* EventGroupHandle_t xEventBits;
|
||||
*
|
||||
* void vTask0( void *pvParameters )
|
||||
* {
|
||||
* EventBits_t uxReturn;
|
||||
* TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
|
||||
*
|
||||
* for( ;; )
|
||||
* {
|
||||
* // Perform task functionality here.
|
||||
*
|
||||
* // Set bit 0 in the event flag to note this task has reached the
|
||||
* // sync point. The other two tasks will set the other two bits defined
|
||||
* // by ALL_SYNC_BITS. All three tasks have reached the synchronisation
|
||||
* // point when all the ALL_SYNC_BITS are set. Wait a maximum of 100ms
|
||||
* // for this to happen.
|
||||
* uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait );
|
||||
*
|
||||
* if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
|
||||
* {
|
||||
* // All three tasks reached the synchronisation point before the call
|
||||
* // to xEventGroupSync() timed out.
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* void vTask1( void *pvParameters )
|
||||
* {
|
||||
* for( ;; )
|
||||
* {
|
||||
* // Perform task functionality here.
|
||||
*
|
||||
* // Set bit 1 in the event flag to note this task has reached the
|
||||
* // synchronisation point. The other two tasks will set the other two
|
||||
* // bits defined by ALL_SYNC_BITS. All three tasks have reached the
|
||||
* // synchronisation point when all the ALL_SYNC_BITS are set. Wait
|
||||
* // indefinitely for this to happen.
|
||||
* xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );
|
||||
*
|
||||
* // xEventGroupSync() was called with an indefinite block time, so
|
||||
* // this task will only reach here if the synchronisation was made by all
|
||||
* // three tasks, so there is no need to test the return value.
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* void vTask2( void *pvParameters )
|
||||
* {
|
||||
* for( ;; )
|
||||
* {
|
||||
* // Perform task functionality here.
|
||||
*
|
||||
* // Set bit 2 in the event flag to note this task has reached the
|
||||
* // synchronisation point. The other two tasks will set the other two
|
||||
* // bits defined by ALL_SYNC_BITS. All three tasks have reached the
|
||||
* // synchronisation point when all the ALL_SYNC_BITS are set. Wait
|
||||
* // indefinitely for this to happen.
|
||||
* xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );
|
||||
*
|
||||
* // xEventGroupSync() was called with an indefinite block time, so
|
||||
* // this task will only reach here if the synchronisation was made by all
|
||||
* // three tasks, so there is no need to test the return value.
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @endcode
|
||||
* \defgroup xEventGroupSync xEventGroupSync
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToSet,
|
||||
const EventBits_t uxBitsToWaitFor,
|
||||
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
* @code{c}
|
||||
* EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
|
||||
* @endcode
|
||||
*
|
||||
* Returns the current value of the bits in an event group. This function
|
||||
* cannot be used from an interrupt.
|
||||
*
|
||||
* @param xEventGroup The event group being queried.
|
||||
*
|
||||
* @return The event group bits at the time xEventGroupGetBits() was called.
|
||||
*
|
||||
* \defgroup xEventGroupGetBits xEventGroupGetBits
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( ( xEventGroup ), 0 )
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
* @code{c}
|
||||
* EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
|
||||
* @endcode
|
||||
*
|
||||
* A version of xEventGroupGetBits() that can be called from an ISR.
|
||||
*
|
||||
* @param xEventGroup The event group being queried.
|
||||
*
|
||||
* @return The event group bits at the time xEventGroupGetBitsFromISR() was called.
|
||||
*
|
||||
* \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
* @code{c}
|
||||
* void xEventGroupDelete( EventGroupHandle_t xEventGroup );
|
||||
* @endcode
|
||||
*
|
||||
* Delete an event group that was previously created by a call to
|
||||
* xEventGroupCreate(). Tasks that are blocked on the event group will be
|
||||
* unblocked and obtain 0 as the event group's value.
|
||||
*
|
||||
* @param xEventGroup The event group being deleted.
|
||||
*/
|
||||
void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
* @code{c}
|
||||
* BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup,
|
||||
* StaticEventGroup_t ** ppxEventGroupBuffer );
|
||||
* @endcode
|
||||
*
|
||||
* Retrieve a pointer to a statically created event groups's data structure
|
||||
* buffer. It is the same buffer that is supplied at the time of creation.
|
||||
*
|
||||
* @param xEventGroup The event group for which to retrieve the buffer.
|
||||
*
|
||||
* @param ppxEventGroupBuffer Used to return a pointer to the event groups's
|
||||
* data structure buffer.
|
||||
*
|
||||
* @return pdTRUE if the buffer was retrieved, pdFALSE otherwise.
|
||||
*/
|
||||
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup,
|
||||
StaticEventGroup_t ** ppxEventGroupBuffer ) PRIVILEGED_FUNCTION;
|
||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||
|
||||
/* For internal use only. */
|
||||
void vEventGroupSetBitsCallback( void * pvEventGroup,
|
||||
uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION;
|
||||
void vEventGroupClearBitsCallback( void * pvEventGroup,
|
||||
uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION;
|
||||
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
UBaseType_t uxEventGroupGetNumber( void * xEventGroup ) PRIVILEGED_FUNCTION;
|
||||
void vEventGroupSetNumber( void * xEventGroup,
|
||||
UBaseType_t uxEventGroupNumber ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* EVENT_GROUPS_H */
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright 2017-2020 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/* freertos_tasks_c_additions.h Rev. 1.4 */
|
||||
#ifndef FREERTOS_TASKS_C_ADDITIONS_H
|
||||
#define FREERTOS_TASKS_C_ADDITIONS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#if !defined(__HIWARE__) /* << EST */
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#if (configUSE_TRACE_FACILITY == 0)
|
||||
#error "configUSE_TRACE_FACILITY must be enabled"
|
||||
#endif
|
||||
|
||||
#define FREERTOS_DEBUG_CONFIG_MAJOR_VERSION 1
|
||||
#define FREERTOS_DEBUG_CONFIG_MINOR_VERSION 2
|
||||
|
||||
/* NOTE!!
|
||||
* Default to a FreeRTOS version which didn't include these macros. FreeRTOS
|
||||
* v7.5.3 is used here.
|
||||
*/
|
||||
#ifndef tskKERNEL_VERSION_BUILD
|
||||
#define tskKERNEL_VERSION_BUILD 3
|
||||
#endif
|
||||
#ifndef tskKERNEL_VERSION_MINOR
|
||||
#define tskKERNEL_VERSION_MINOR 5
|
||||
#endif
|
||||
#ifndef tskKERNEL_VERSION_MAJOR
|
||||
#define tskKERNEL_VERSION_MAJOR 7
|
||||
#endif
|
||||
|
||||
/* NOTE!!
|
||||
* The configFRTOS_MEMORY_SCHEME macro describes the heap scheme using a value
|
||||
* 1 - 5 which corresponds to the following schemes:
|
||||
*
|
||||
* heap_1 - the very simplest, does not permit memory to be freed
|
||||
* heap_2 - permits memory to be freed, but not does coalescence adjacent free
|
||||
* blocks.
|
||||
* heap_3 - simply wraps the standard malloc() and free() for thread safety
|
||||
* heap_4 - coalesces adjacent free blocks to avoid fragmentation. Includes
|
||||
* absolute address placement option
|
||||
* heap_5 - as per heap_4, with the ability to span the heap across
|
||||
* multiple nonOadjacent memory areas
|
||||
* heap_6 - reentrant newlib implementation
|
||||
*/
|
||||
#ifndef configUSE_HEAP_SCHEME
|
||||
#define configUSE_HEAP_SCHEME 3 /* thread safe malloc */
|
||||
#endif
|
||||
|
||||
#if ((configUSE_HEAP_SCHEME > 6) || (configUSE_HEAP_SCHEME < 1)) /* <<EST Using up to 6 schemes */
|
||||
#error "Invalid configFRTOS_MEMORY_SCHEME setting!"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const uint8_t FreeRTOSDebugConfig[];
|
||||
|
||||
/* NOTES!!
|
||||
* IAR documentation is confusing. It suggests the data must be statically
|
||||
* linked, and the #pragma placed immediately before the symbol definition.
|
||||
* The IAR supplied examples violate both "rules", so this is a best guess.
|
||||
*/
|
||||
|
||||
|
||||
#if (tskKERNEL_VERSION_MAJOR >= 10) && (tskKERNEL_VERSION_MINOR >= 2)
|
||||
// Need the portARCH_NAME define
|
||||
#ifndef portARCH_NAME
|
||||
#define portARCH_NAME NULL
|
||||
#endif
|
||||
#if defined(__GNUC__)
|
||||
char *const portArch_Name __attribute__((section(".rodata"))) = portARCH_NAME;
|
||||
#elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
|
||||
char *const portArch_Name __attribute__((used)) = portARCH_NAME;
|
||||
#elif defined(__IAR_SYSTEMS_ICC__)
|
||||
#pragma required=portArch_Name
|
||||
char *const portArch_Name = portARCH_NAME;
|
||||
#endif
|
||||
#else
|
||||
char *const portArch_Name = NULL;
|
||||
#endif // tskKERNEL_VERSION_MAJOR
|
||||
|
||||
#if defined(__GNUC__)
|
||||
const uint8_t FreeRTOSDebugConfig[] __attribute__((used)) __attribute__((section(".rodata"))) __attribute__((aligned(4))) = /* needs to be 32bit aligned for LinkServer FreeRTOS thread awareness, otherwise problem with GDB. */
|
||||
#elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
|
||||
const uint8_t FreeRTOSDebugConfig[] __attribute__((used)) =
|
||||
#elif defined(__IAR_SYSTEMS_ICC__)
|
||||
#pragma required=FreeRTOSDebugConfig
|
||||
const uint8_t FreeRTOSDebugConfig[] =
|
||||
#else /* << EST generic compiler */
|
||||
const uint8_t FreeRTOSDebugConfig[] =
|
||||
#endif
|
||||
{
|
||||
FREERTOS_DEBUG_CONFIG_MAJOR_VERSION,
|
||||
FREERTOS_DEBUG_CONFIG_MINOR_VERSION,
|
||||
tskKERNEL_VERSION_MAJOR,
|
||||
tskKERNEL_VERSION_MINOR,
|
||||
tskKERNEL_VERSION_BUILD,
|
||||
configUSE_HEAP_SCHEME,
|
||||
offsetof(struct tskTaskControlBlock, pxTopOfStack),
|
||||
#if (tskKERNEL_VERSION_MAJOR > 8)
|
||||
offsetof(struct tskTaskControlBlock, xStateListItem),
|
||||
#else
|
||||
offsetof(struct tskTaskControlBlock, xGenericListItem),
|
||||
#endif
|
||||
offsetof(struct tskTaskControlBlock, xEventListItem),
|
||||
offsetof(struct tskTaskControlBlock, pxStack),
|
||||
offsetof(struct tskTaskControlBlock, pcTaskName),
|
||||
offsetof(struct tskTaskControlBlock, uxTCBNumber),
|
||||
offsetof(struct tskTaskControlBlock, uxTaskNumber),
|
||||
configMAX_TASK_NAME_LEN,
|
||||
configMAX_PRIORITIES,
|
||||
#if (tskKERNEL_VERSION_MAJOR >= 10) && (tskKERNEL_VERSION_MINOR >= 2)
|
||||
configENABLE_MPU,
|
||||
configENABLE_FPU,
|
||||
configENABLE_TRUSTZONE,
|
||||
configRUN_FREERTOS_SECURE_ONLY,
|
||||
0, // 32-bit align
|
||||
0, 0, 0, 0 // padding
|
||||
#else
|
||||
0 // pad to 32-bit boundary
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // FREERTOS_TASKS_C_ADDITIONS_H
|
||||
|
||||
504
pico-sensor/McuLib/FreeRTOS/Source/include/list.h
Normal file
504
pico-sensor/McuLib/FreeRTOS/Source/include/list.h
Normal file
@@ -0,0 +1,504 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is the list implementation used by the scheduler. While it is tailored
|
||||
* heavily for the schedulers needs, it is also available for use by
|
||||
* application code.
|
||||
*
|
||||
* list_ts can only store pointers to list_item_ts. Each ListItem_t contains a
|
||||
* numeric value (xItemValue). Most of the time the lists are sorted in
|
||||
* ascending item value order.
|
||||
*
|
||||
* Lists are created already containing one list item. The value of this
|
||||
* item is the maximum possible that can be stored, it is therefore always at
|
||||
* the end of the list and acts as a marker. The list member pxHead always
|
||||
* points to this marker - even though it is at the tail of the list. This
|
||||
* is because the tail contains a wrap back pointer to the true head of
|
||||
* the list.
|
||||
*
|
||||
* In addition to it's value, each list item contains a pointer to the next
|
||||
* item in the list (pxNext), a pointer to the list it is in (pxContainer)
|
||||
* and a pointer to back to the object that contains it. These later two
|
||||
* pointers are included for efficiency of list manipulation. There is
|
||||
* effectively a two way link between the object containing the list item and
|
||||
* the list item itself.
|
||||
*
|
||||
*
|
||||
* \page ListIntroduction List Implementation
|
||||
* \ingroup FreeRTOSIntro
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LIST_H
|
||||
#define LIST_H
|
||||
|
||||
#ifndef INC_FREERTOS_H
|
||||
#error "FreeRTOS.h must be included before list.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The list structure members are modified from within interrupts, and therefore
|
||||
* by rights should be declared volatile. However, they are only modified in a
|
||||
* functionally atomic way (within critical sections of with the scheduler
|
||||
* suspended) and are either passed by reference into a function or indexed via
|
||||
* a volatile variable. Therefore, in all use cases tested so far, the volatile
|
||||
* qualifier can be omitted in order to provide a moderate performance
|
||||
* improvement without adversely affecting functional behaviour. The assembly
|
||||
* instructions generated by the IAR, ARM and GCC compilers when the respective
|
||||
* compiler's options were set for maximum optimisation has been inspected and
|
||||
* deemed to be as intended. That said, as compiler technology advances, and
|
||||
* especially if aggressive cross module optimisation is used (a use case that
|
||||
* has not been exercised to any great extend) then it is feasible that the
|
||||
* volatile qualifier will be needed for correct optimisation. It is expected
|
||||
* that a compiler removing essential code because, without the volatile
|
||||
* qualifier on the list structure members and with aggressive cross module
|
||||
* optimisation, the compiler deemed the code unnecessary will result in
|
||||
* complete and obvious failure of the scheduler. If this is ever experienced
|
||||
* then the volatile qualifier can be inserted in the relevant places within the
|
||||
* list structures by simply defining configLIST_VOLATILE to volatile in
|
||||
* FreeRTOSConfig.h (as per the example at the bottom of this comment block).
|
||||
* If configLIST_VOLATILE is not defined then the preprocessor directives below
|
||||
* will simply #define configLIST_VOLATILE away completely.
|
||||
*
|
||||
* To use volatile list structure members then add the following line to
|
||||
* FreeRTOSConfig.h (without the quotes):
|
||||
* "#define configLIST_VOLATILE volatile"
|
||||
*/
|
||||
#ifndef configLIST_VOLATILE
|
||||
#define configLIST_VOLATILE
|
||||
#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/* Macros that can be used to place known values within the list structures,
|
||||
* then check that the known values do not get corrupted during the execution of
|
||||
* the application. These may catch the list data structures being overwritten in
|
||||
* memory. They will not catch data errors caused by incorrect configuration or
|
||||
* use of FreeRTOS.*/
|
||||
#if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 )
|
||||
/* Define the macros to do nothing. */
|
||||
#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
|
||||
#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
|
||||
#define listFIRST_LIST_INTEGRITY_CHECK_VALUE
|
||||
#define listSECOND_LIST_INTEGRITY_CHECK_VALUE
|
||||
#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
|
||||
#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
|
||||
#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )
|
||||
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )
|
||||
#define listTEST_LIST_ITEM_INTEGRITY( pxItem )
|
||||
#define listTEST_LIST_INTEGRITY( pxList )
|
||||
#else /* if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) */
|
||||
/* Define macros that add new members into the list structures. */
|
||||
#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1;
|
||||
#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2;
|
||||
#define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1;
|
||||
#define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2;
|
||||
|
||||
/* Define macros that set the new structure members to known values. */
|
||||
#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
|
||||
#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
|
||||
#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
|
||||
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
|
||||
|
||||
/* Define macros that will assert if one of the structure members does not
|
||||
* contain its expected value. */
|
||||
#define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
|
||||
#define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
|
||||
#endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */
|
||||
|
||||
|
||||
/*
|
||||
* 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. */
|
||||
configLIST_VOLATILE TickType_t xItemValue; /**< The value being listed. In most cases this is used to sort the list in ascending order. */
|
||||
struct xLIST_ITEM * configLIST_VOLATILE pxNext; /**< Pointer to the next ListItem_t in the list. */
|
||||
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /**< Pointer to the previous ListItem_t in the list. */
|
||||
void * pvOwner; /**< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */
|
||||
struct xLIST * configLIST_VOLATILE pxContainer; /**< Pointer to the list in which this list item is placed (if any). */
|
||||
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
};
|
||||
typedef struct xLIST_ITEM ListItem_t;
|
||||
|
||||
#if ( configUSE_MINI_LIST_ITEM == 1 )
|
||||
struct xMINI_LIST_ITEM
|
||||
{
|
||||
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
configLIST_VOLATILE TickType_t xItemValue;
|
||||
struct xLIST_ITEM * configLIST_VOLATILE pxNext;
|
||||
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
|
||||
};
|
||||
typedef struct xMINI_LIST_ITEM MiniListItem_t;
|
||||
#else
|
||||
typedef struct xLIST_ITEM MiniListItem_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Definition of the type of queue used by the scheduler.
|
||||
*/
|
||||
typedef struct xLIST
|
||||
{
|
||||
listFIRST_LIST_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
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;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )
|
||||
|
||||
/*
|
||||
* 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 listGET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner )
|
||||
|
||||
/*
|
||||
* Access macro to set the value of the list item. In most cases the value is
|
||||
* used to sort the list in ascending order.
|
||||
*
|
||||
* \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) )
|
||||
|
||||
/*
|
||||
* Access macro to retrieve the value of the list item. The value can
|
||||
* represent anything - for example the priority of a task, or the time at
|
||||
* which a task should be unblocked.
|
||||
*
|
||||
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue )
|
||||
|
||||
/*
|
||||
* Access macro to retrieve the value of the list item at the head of a given
|
||||
* list.
|
||||
*
|
||||
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue )
|
||||
|
||||
/*
|
||||
* Return the list item at the head of the list.
|
||||
*
|
||||
* \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext )
|
||||
|
||||
/*
|
||||
* Return the next list item.
|
||||
*
|
||||
* \page listGET_NEXT listGET_NEXT
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext )
|
||||
|
||||
/*
|
||||
* Return the list item that marks the end of the list
|
||||
*
|
||||
* \page listGET_END_MARKER listGET_END_MARKER
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )
|
||||
|
||||
/*
|
||||
* Access macro to determine if a list contains any items. The macro will
|
||||
* only have the value true if the list is empty.
|
||||
*
|
||||
* \page listLIST_IS_EMPTY listLIST_IS_EMPTY
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listLIST_IS_EMPTY( pxList ) ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE )
|
||||
|
||||
/*
|
||||
* Access macro to return the number of items in the list.
|
||||
*/
|
||||
#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems )
|
||||
|
||||
/*
|
||||
* Access function to obtain the owner of the next entry in a 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
|
||||
* and returns that entry's pxOwner parameter. Using multiple calls to this
|
||||
* function it is therefore possible to move through every item contained in
|
||||
* a list.
|
||||
*
|
||||
* The pxOwner parameter of a list item is a pointer to the object that owns
|
||||
* the list item. In the scheduler this is normally a task control block.
|
||||
* The pxOwner parameter effectively creates a two way link between the list
|
||||
* item and its owner.
|
||||
*
|
||||
* @param pxTCB pxTCB is set to the address of the owner of the next list item.
|
||||
* @param pxList The list from which the next item owner is to be returned.
|
||||
*
|
||||
* \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \
|
||||
do { \
|
||||
List_t * const pxConstList = ( pxList ); \
|
||||
/* Increment the index to the next item and return the item, ensuring */ \
|
||||
/* we don't return the marker used at the end of the list. */ \
|
||||
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
|
||||
if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \
|
||||
{ \
|
||||
( pxConstList )->pxIndex = ( pxConstList )->xListEnd.pxNext; \
|
||||
} \
|
||||
( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \
|
||||
} while( 0 )
|
||||
|
||||
/*
|
||||
* Version of uxListRemove() that does not return a value. Provided as a slight
|
||||
* optimisation for xTaskIncrementTick() by being inline.
|
||||
*
|
||||
* Remove an item from a list. The list item has a pointer to the list that
|
||||
* it is in, so only the list item need be passed into the function.
|
||||
*
|
||||
* @param uxListRemove The item to be removed. The item will remove itself from
|
||||
* the list pointed to by it's pxContainer parameter.
|
||||
*
|
||||
* @return The number of items that remain in the list after the list item has
|
||||
* been removed.
|
||||
*
|
||||
* \page listREMOVE_ITEM listREMOVE_ITEM
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listREMOVE_ITEM( pxItemToRemove ) \
|
||||
do { \
|
||||
/* The list item knows which list it is in. Obtain the list from the list \
|
||||
* item. */ \
|
||||
List_t * const pxList = ( pxItemToRemove )->pxContainer; \
|
||||
\
|
||||
( pxItemToRemove )->pxNext->pxPrevious = ( pxItemToRemove )->pxPrevious; \
|
||||
( pxItemToRemove )->pxPrevious->pxNext = ( pxItemToRemove )->pxNext; \
|
||||
/* Make sure the index is left pointing to a valid item. */ \
|
||||
if( pxList->pxIndex == ( pxItemToRemove ) ) \
|
||||
{ \
|
||||
pxList->pxIndex = ( pxItemToRemove )->pxPrevious; \
|
||||
} \
|
||||
\
|
||||
( pxItemToRemove )->pxContainer = NULL; \
|
||||
( pxList->uxNumberOfItems )--; \
|
||||
} while( 0 )
|
||||
|
||||
/*
|
||||
* Inline version of vListInsertEnd() to provide slight optimisation for
|
||||
* xTaskIncrementTick().
|
||||
*
|
||||
* Insert a list item into a list. The item will be inserted in a position
|
||||
* such that it will be the last item within the list returned by multiple
|
||||
* calls to listGET_OWNER_OF_NEXT_ENTRY.
|
||||
*
|
||||
* The list member pxIndex is used to walk through a list. Calling
|
||||
* listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list.
|
||||
* Placing an item in a list using vListInsertEnd effectively places the item
|
||||
* in the list position pointed to by pxIndex. This means that every other
|
||||
* item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before
|
||||
* the pxIndex parameter again points to the item being inserted.
|
||||
*
|
||||
* @param pxList The list into which the item is to be inserted.
|
||||
*
|
||||
* @param pxNewListItem The list item to be inserted into the list.
|
||||
*
|
||||
* \page listINSERT_END listINSERT_END
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listINSERT_END( pxList, pxNewListItem ) \
|
||||
do { \
|
||||
ListItem_t * const pxIndex = ( pxList )->pxIndex; \
|
||||
\
|
||||
/* Only effective when configASSERT() is also defined, these tests may catch \
|
||||
* the list data structures being overwritten in memory. They will not catch \
|
||||
* data errors caused by incorrect configuration or use of FreeRTOS. */ \
|
||||
listTEST_LIST_INTEGRITY( ( pxList ) ); \
|
||||
listTEST_LIST_ITEM_INTEGRITY( ( pxNewListItem ) ); \
|
||||
\
|
||||
/* Insert a new list item into ( pxList ), but rather than sort the list, \
|
||||
* makes the new list item the last item to be removed by a call to \
|
||||
* listGET_OWNER_OF_NEXT_ENTRY(). */ \
|
||||
( pxNewListItem )->pxNext = pxIndex; \
|
||||
( pxNewListItem )->pxPrevious = pxIndex->pxPrevious; \
|
||||
\
|
||||
pxIndex->pxPrevious->pxNext = ( pxNewListItem ); \
|
||||
pxIndex->pxPrevious = ( pxNewListItem ); \
|
||||
\
|
||||
/* Remember which list the item is in. */ \
|
||||
( pxNewListItem )->pxContainer = ( pxList ); \
|
||||
\
|
||||
( ( pxList )->uxNumberOfItems )++; \
|
||||
} while( 0 )
|
||||
|
||||
/*
|
||||
* Access function to obtain the owner of the first entry in a list. Lists
|
||||
* are normally sorted in ascending item value order.
|
||||
*
|
||||
* This function returns the pxOwner member of the first item in the list.
|
||||
* The pxOwner parameter of a list item is a pointer to the object that owns
|
||||
* the list item. In the scheduler this is normally a task control block.
|
||||
* The pxOwner parameter effectively creates a two way link between the list
|
||||
* item and its owner.
|
||||
*
|
||||
* @param pxList The list from which the owner of the head item is to be
|
||||
* returned.
|
||||
*
|
||||
* \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( ( &( ( pxList )->xListEnd ) )->pxNext->pvOwner )
|
||||
|
||||
/*
|
||||
* Check to see if a list item is within a list. The list item maintains a
|
||||
* "container" pointer that points to the list it is in. All this macro does
|
||||
* is check to see if the container and the list match.
|
||||
*
|
||||
* @param pxList The list we want to know if the list item is within.
|
||||
* @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 ) ( ( ( pxListItem )->pxContainer == ( pxList ) ) ? ( pdTRUE ) : ( pdFALSE ) )
|
||||
|
||||
/*
|
||||
* Return the list a list item is contained within (referenced from).
|
||||
*
|
||||
* @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 )->pxContainer )
|
||||
|
||||
/*
|
||||
* This provides a crude means of knowing if a list has been initialised, as
|
||||
* pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise()
|
||||
* function.
|
||||
*/
|
||||
#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY )
|
||||
|
||||
/*
|
||||
* Must be called before a list is used! This initialises all the members
|
||||
* of the list structure and inserts the xListEnd item into the list as a
|
||||
* marker to the back of the list.
|
||||
*
|
||||
* @param pxList Pointer to the list being initialised.
|
||||
*
|
||||
* \page vListInitialise vListInitialise
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Must be called before a list item is used. This sets the list container to
|
||||
* null so the item does not think that it is already contained in a list.
|
||||
*
|
||||
* @param pxItem Pointer to the list item being initialised.
|
||||
*
|
||||
* \page vListInitialiseItem vListInitialiseItem
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Insert a list item into a list. The item will be inserted into the list in
|
||||
* a position determined by its item value (ascending item value order).
|
||||
*
|
||||
* @param pxList The list into which the item is to be inserted.
|
||||
*
|
||||
* @param pxNewListItem The item that is to be placed in the list.
|
||||
*
|
||||
* \page vListInsert vListInsert
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
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 pxIndex is used to walk through a list. Calling
|
||||
* listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list.
|
||||
* Placing an item in a list using vListInsertEnd effectively places the item
|
||||
* in the list position pointed to by pxIndex. This means that every other
|
||||
* item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before
|
||||
* the pxIndex parameter again points to the item being inserted.
|
||||
*
|
||||
* @param pxList The list into which the item is to be inserted.
|
||||
*
|
||||
* @param pxNewListItem The list item to be inserted into the list.
|
||||
*
|
||||
* \page vListInsertEnd vListInsertEnd
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
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
|
||||
* it is in, so only the list item need be passed into the function.
|
||||
*
|
||||
* @param uxListRemove The item to be removed. The item will remove itself from
|
||||
* the list pointed to by it's pxContainer parameter.
|
||||
*
|
||||
* @return The number of items that remain in the list after the list item has
|
||||
* been removed.
|
||||
*
|
||||
* \page uxListRemove uxListRemove
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* ifndef LIST_H */
|
||||
|
||||
888
pico-sensor/McuLib/FreeRTOS/Source/include/message_buffer.h
Normal file
888
pico-sensor/McuLib/FreeRTOS/Source/include/message_buffer.h
Normal file
@@ -0,0 +1,888 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* 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"
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#if defined( __cplusplus )
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/**
|
||||
* 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. Message buffer is essentially built as a stream buffer hence its handle
|
||||
* is also set to same type as a stream buffer handle.
|
||||
*/
|
||||
typedef StreamBufferHandle_t MessageBufferHandle_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes );
|
||||
* @endcode
|
||||
*
|
||||
* Creates a new message buffer using dynamically allocated memory. See
|
||||
* xMessageBufferCreateStatic() for a version that uses statically allocated
|
||||
* 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.
|
||||
*
|
||||
* @param pxSendCompletedCallback Callback invoked when a send operation to the
|
||||
* message buffer is complete. If the parameter is NULL or xMessageBufferCreate()
|
||||
* is called without the parameter, then it will use the default implementation
|
||||
* provided by sbSEND_COMPLETED macro. To enable the callback,
|
||||
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
|
||||
*
|
||||
* @param pxReceiveCompletedCallback Callback invoked when a receive operation from
|
||||
* the message buffer is complete. If the parameter is NULL or xMessageBufferCreate()
|
||||
* is called without the parameter, it will use the default implementation provided
|
||||
* by sbRECEIVE_COMPLETED macro. To enable the callback,
|
||||
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
|
||||
*
|
||||
* @return If NULL is returned, then the message buffer cannot be created
|
||||
* because there is insufficient heap memory available for FreeRTOS to allocate
|
||||
* the message buffer data structures and storage area. A non-NULL value being
|
||||
* 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 length 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
|
||||
* \defgroup xMessageBufferCreate xMessageBufferCreate
|
||||
* \ingroup MessageBufferManagement
|
||||
*/
|
||||
#define xMessageBufferCreate( xBufferSizeBytes ) \
|
||||
xStreamBufferGenericCreate( ( xBufferSizeBytes ), ( size_t ) 0, pdTRUE, NULL, NULL )
|
||||
|
||||
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
|
||||
#define xMessageBufferCreateWithCallback( xBufferSizeBytes, pxSendCompletedCallback, pxReceiveCompletedCallback ) \
|
||||
xStreamBufferGenericCreate( ( xBufferSizeBytes ), ( size_t ) 0, pdTRUE, ( pxSendCompletedCallback ), ( pxReceiveCompletedCallback ) )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* MessageBufferHandle_t xMessageBufferCreateStatic( size_t xBufferSizeBytes,
|
||||
* uint8_t *pucMessageBufferStorageArea,
|
||||
* StaticMessageBuffer_t *pxStaticMessageBuffer );
|
||||
* @endcode
|
||||
* Creates a new message buffer using statically allocated memory. See
|
||||
* xMessageBufferCreate() for a version that uses dynamically allocated memory.
|
||||
*
|
||||
* @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 big. This is the array to which messages are
|
||||
* copied when they are written to the message buffer.
|
||||
*
|
||||
* @param pxStaticMessageBuffer Must point to a variable of type
|
||||
* StaticMessageBuffer_t, which will be used to hold the message buffer's data
|
||||
* structure.
|
||||
*
|
||||
* @param pxSendCompletedCallback Callback invoked when a new message is sent to the message buffer.
|
||||
* If the parameter is NULL or xMessageBufferCreate() is called without the parameter, then it will use the default
|
||||
* implementation provided by sbSEND_COMPLETED macro. To enable the callback,
|
||||
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
|
||||
*
|
||||
* @param pxReceiveCompletedCallback Callback invoked when a message is read from a
|
||||
* message buffer. If the parameter is NULL or xMessageBufferCreate() is called without the parameter, it will
|
||||
* use the default implementation provided by sbRECEIVE_COMPLETED macro. To enable the callback,
|
||||
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
|
||||
*
|
||||
* @return If the message buffer is created successfully then a handle to the
|
||||
* created message buffer is returned. If either pucMessageBufferStorageArea or
|
||||
* pxStaticmessageBuffer are NULL then NULL is returned.
|
||||
*
|
||||
* Example use:
|
||||
* @code{c}
|
||||
*
|
||||
* // Used to dimension the array used to hold the messages. The available space
|
||||
* // will actually be one less than this, so 999.
|
||||
#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( ucStorageBuffer ),
|
||||
* ucStorageBuffer,
|
||||
* &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
|
||||
* \defgroup xMessageBufferCreateStatic xMessageBufferCreateStatic
|
||||
* \ingroup MessageBufferManagement
|
||||
*/
|
||||
#define xMessageBufferCreateStatic( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer ) \
|
||||
xStreamBufferGenericCreateStatic( ( xBufferSizeBytes ), 0, pdTRUE, ( pucMessageBufferStorageArea ), ( pxStaticMessageBuffer ), NULL, NULL )
|
||||
|
||||
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
|
||||
#define xMessageBufferCreateStaticWithCallback( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback ) \
|
||||
xStreamBufferGenericCreateStatic( ( xBufferSizeBytes ), 0, pdTRUE, ( pucMessageBufferStorageArea ), ( pxStaticMessageBuffer ), ( pxSendCompletedCallback ), ( pxReceiveCompletedCallback ) )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* BaseType_t xMessageBufferGetStaticBuffers( MessageBufferHandle_t xMessageBuffer,
|
||||
* uint8_t ** ppucMessageBufferStorageArea,
|
||||
* StaticMessageBuffer_t ** ppxStaticMessageBuffer );
|
||||
* @endcode
|
||||
*
|
||||
* Retrieve pointers to a statically created message buffer's data structure
|
||||
* buffer and storage area buffer. These are the same buffers that are supplied
|
||||
* at the time of creation.
|
||||
*
|
||||
* @param xMessageBuffer The message buffer for which to retrieve the buffers.
|
||||
*
|
||||
* @param ppucMessageBufferStorageArea Used to return a pointer to the
|
||||
* message buffer's storage area buffer.
|
||||
*
|
||||
* @param ppxStaticMessageBuffer Used to return a pointer to the message
|
||||
* buffer's data structure buffer.
|
||||
*
|
||||
* @return pdTRUE if buffers were retrieved, pdFALSE otherwise..
|
||||
*
|
||||
* \defgroup xMessageBufferGetStaticBuffers xMessageBufferGetStaticBuffers
|
||||
* \ingroup MessageBufferManagement
|
||||
*/
|
||||
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
#define xMessageBufferGetStaticBuffers( xMessageBuffer, ppucMessageBufferStorageArea, ppxStaticMessageBuffer ) \
|
||||
xStreamBufferGetStaticBuffers( ( xMessageBuffer ), ( ppucMessageBufferStorageArea ), ( ppxStaticMessageBuffer ) )
|
||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* size_t xMessageBufferSend( MessageBufferHandle_t xMessageBuffer,
|
||||
* const void *pvTxData,
|
||||
* size_t xDataLengthBytes,
|
||||
* TickType_t xTicksToWait );
|
||||
* @endcode
|
||||
*
|
||||
* Sends a discrete message to the message buffer. The message can be any
|
||||
* length that fits within the buffer's free space, and is copied into the
|
||||
* 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
|
||||
* \defgroup xMessageBufferSend xMessageBufferSend
|
||||
* \ingroup MessageBufferManagement
|
||||
*/
|
||||
#define xMessageBufferSend( xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) \
|
||||
xStreamBufferSend( ( xMessageBuffer ), ( pvTxData ), ( xDataLengthBytes ), ( xTicksToWait ) )
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* size_t xMessageBufferSendFromISR( MessageBufferHandle_t xMessageBuffer,
|
||||
* const void *pvTxData,
|
||||
* size_t xDataLengthBytes,
|
||||
* BaseType_t *pxHigherPriorityTaskWoken );
|
||||
* @endcode
|
||||
*
|
||||
* Interrupt safe version of the API function that sends a discrete message to
|
||||
* the message buffer. The message can be any length that fits within the
|
||||
* 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
|
||||
* \defgroup xMessageBufferSendFromISR xMessageBufferSendFromISR
|
||||
* \ingroup MessageBufferManagement
|
||||
*/
|
||||
#define xMessageBufferSendFromISR( xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) \
|
||||
xStreamBufferSendFromISR( ( xMessageBuffer ), ( pvTxData ), ( xDataLengthBytes ), ( pxHigherPriorityTaskWoken ) )
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer,
|
||||
* void *pvRxData,
|
||||
* size_t xBufferLengthBytes,
|
||||
* TickType_t xTicksToWait );
|
||||
* @endcode
|
||||
*
|
||||
* Receives a discrete message from a message buffer. Messages can be of
|
||||
* variable length and are copied out of the buffer.
|
||||
*
|
||||
* ***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
|
||||
* \defgroup xMessageBufferReceive xMessageBufferReceive
|
||||
* \ingroup MessageBufferManagement
|
||||
*/
|
||||
#define xMessageBufferReceive( xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) \
|
||||
xStreamBufferReceive( ( xMessageBuffer ), ( pvRxData ), ( xBufferLengthBytes ), ( xTicksToWait ) )
|
||||
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* size_t xMessageBufferReceiveFromISR( MessageBufferHandle_t xMessageBuffer,
|
||||
* void *pvRxData,
|
||||
* size_t xBufferLengthBytes,
|
||||
* BaseType_t *pxHigherPriorityTaskWoken );
|
||||
* @endcode
|
||||
*
|
||||
* An interrupt safe version of the API function that receives a discrete
|
||||
* message from a message buffer. Messages can be of variable length and are
|
||||
* 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
|
||||
* \defgroup xMessageBufferReceiveFromISR xMessageBufferReceiveFromISR
|
||||
* \ingroup MessageBufferManagement
|
||||
*/
|
||||
#define xMessageBufferReceiveFromISR( xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) \
|
||||
xStreamBufferReceiveFromISR( ( xMessageBuffer ), ( pvRxData ), ( xBufferLengthBytes ), ( pxHigherPriorityTaskWoken ) )
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* void vMessageBufferDelete( MessageBufferHandle_t xMessageBuffer );
|
||||
* @endcode
|
||||
*
|
||||
* Deletes a message buffer that was previously created using a call to
|
||||
* xMessageBufferCreate() or xMessageBufferCreateStatic(). If the message
|
||||
* 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( xMessageBuffer )
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
* @code{c}
|
||||
* BaseType_t xMessageBufferIsFull( MessageBufferHandle_t xMessageBuffer );
|
||||
* @endcode
|
||||
*
|
||||
* Tests to see if a message buffer is full. A message buffer is full if it
|
||||
* cannot accept any more messages, of any size, until space is made available
|
||||
* 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( xMessageBuffer )
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
* @code{c}
|
||||
* BaseType_t xMessageBufferIsEmpty( MessageBufferHandle_t xMessageBuffer );
|
||||
* @endcode
|
||||
*
|
||||
* Tests to see if a message buffer is empty (does not contain any messages).
|
||||
*
|
||||
* @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( xMessageBuffer )
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
* @code{c}
|
||||
* BaseType_t xMessageBufferReset( MessageBufferHandle_t xMessageBuffer );
|
||||
* @endcode
|
||||
*
|
||||
* Resets a message buffer to its initial empty state, discarding any message it
|
||||
* contained.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* \defgroup xMessageBufferReset xMessageBufferReset
|
||||
* \ingroup MessageBufferManagement
|
||||
*/
|
||||
#define xMessageBufferReset( xMessageBuffer ) \
|
||||
xStreamBufferReset( xMessageBuffer )
|
||||
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
* @code{c}
|
||||
* size_t xMessageBufferSpaceAvailable( MessageBufferHandle_t xMessageBuffer );
|
||||
* @endcode
|
||||
* Returns the number of bytes of free space in the message buffer.
|
||||
*
|
||||
* @param xMessageBuffer The handle of the message buffer being queried.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* \defgroup xMessageBufferSpaceAvailable xMessageBufferSpaceAvailable
|
||||
* \ingroup MessageBufferManagement
|
||||
*/
|
||||
#define xMessageBufferSpaceAvailable( xMessageBuffer ) \
|
||||
xStreamBufferSpacesAvailable( xMessageBuffer )
|
||||
#define xMessageBufferSpacesAvailable( xMessageBuffer ) \
|
||||
xStreamBufferSpacesAvailable( xMessageBuffer ) /* Corrects typo in original macro name. */
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
* @code{c}
|
||||
* size_t xMessageBufferNextLengthBytes( MessageBufferHandle_t xMessageBuffer );
|
||||
* @endcode
|
||||
* Returns the length (in bytes) of the next message in a message buffer.
|
||||
* Useful if xMessageBufferReceive() returned 0 because the size of the buffer
|
||||
* passed into xMessageBufferReceive() was too small to hold the next message.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* \defgroup xMessageBufferNextLengthBytes xMessageBufferNextLengthBytes
|
||||
* \ingroup MessageBufferManagement
|
||||
*/
|
||||
#define xMessageBufferNextLengthBytes( xMessageBuffer ) \
|
||||
xStreamBufferNextMessageLengthBytes( xMessageBuffer ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* BaseType_t xMessageBufferSendCompletedFromISR( MessageBufferHandle_t xMessageBuffer, BaseType_t *pxHigherPriorityTaskWoken );
|
||||
* @endcode
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* \defgroup xMessageBufferSendCompletedFromISR xMessageBufferSendCompletedFromISR
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
#define xMessageBufferSendCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) \
|
||||
xStreamBufferSendCompletedFromISR( ( xMessageBuffer ), ( pxHigherPriorityTaskWoken ) )
|
||||
|
||||
/**
|
||||
* message_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* BaseType_t xMessageBufferReceiveCompletedFromISR( MessageBufferHandle_t xMessageBuffer, BaseType_t *pxHigherPriorityTaskWoken );
|
||||
* @endcode
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* \defgroup xMessageBufferReceiveCompletedFromISR xMessageBufferReceiveCompletedFromISR
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
#define xMessageBufferReceiveCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) \
|
||||
xStreamBufferReceiveCompletedFromISR( ( xMessageBuffer ), ( pxHigherPriorityTaskWoken ) )
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#if defined( __cplusplus )
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* !defined( FREERTOS_MESSAGE_BUFFER_H ) */
|
||||
|
||||
389
pico-sensor/McuLib/FreeRTOS/Source/include/mpu_prototypes.h
Normal file
389
pico-sensor/McuLib/FreeRTOS/Source/include/mpu_prototypes.h
Normal file
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* When the MPU is used the standard (non MPU) API functions are mapped to
|
||||
* equivalents that start "MPU_", the prototypes for which are defined in this
|
||||
* header files. 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MPU_PROTOTYPES_H
|
||||
#define MPU_PROTOTYPES_H
|
||||
|
||||
typedef struct xTaskGenericNotifyParams
|
||||
{
|
||||
TaskHandle_t xTaskToNotify;
|
||||
UBaseType_t uxIndexToNotify;
|
||||
uint32_t ulValue;
|
||||
eNotifyAction eAction;
|
||||
uint32_t * pulPreviousNotificationValue;
|
||||
} xTaskGenericNotifyParams_t;
|
||||
|
||||
typedef struct xTaskGenericNotifyWaitParams
|
||||
{
|
||||
UBaseType_t uxIndexToWaitOn;
|
||||
uint32_t ulBitsToClearOnEntry;
|
||||
uint32_t ulBitsToClearOnExit;
|
||||
uint32_t * pulNotificationValue;
|
||||
TickType_t xTicksToWait;
|
||||
} xTaskGenericNotifyWaitParams_t;
|
||||
|
||||
typedef struct xTimerGenericCommandFromTaskParams
|
||||
{
|
||||
TimerHandle_t xTimer;
|
||||
BaseType_t xCommandID;
|
||||
TickType_t xOptionalValue;
|
||||
BaseType_t * pxHigherPriorityTaskWoken;
|
||||
TickType_t xTicksToWait;
|
||||
} xTimerGenericCommandFromTaskParams_t;
|
||||
|
||||
typedef struct xEventGroupWaitBitsParams
|
||||
{
|
||||
EventGroupHandle_t xEventGroup;
|
||||
EventBits_t uxBitsToWaitFor;
|
||||
BaseType_t xClearOnExit;
|
||||
BaseType_t xWaitForAllBits;
|
||||
TickType_t xTicksToWait;
|
||||
} xEventGroupWaitBitsParams_t;
|
||||
|
||||
/* MPU versions of task.h API functions. */
|
||||
void MPU_vTaskDelay( const TickType_t xTicksToDelay ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
|
||||
const TickType_t xTimeIncrement ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||
UBaseType_t MPU_uxTaskPriorityGet( const TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||
eTaskState MPU_eTaskGetState( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||
void MPU_vTaskGetInfo( TaskHandle_t xTask,
|
||||
TaskStatus_t * pxTaskStatus,
|
||||
BaseType_t xGetFreeStackSpace,
|
||||
eTaskState eState ) FREERTOS_SYSTEM_CALL;
|
||||
void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend ) FREERTOS_SYSTEM_CALL;
|
||||
void MPU_vTaskResume( TaskHandle_t xTaskToResume ) FREERTOS_SYSTEM_CALL;
|
||||
TickType_t MPU_xTaskGetTickCount( void ) FREERTOS_SYSTEM_CALL;
|
||||
UBaseType_t MPU_uxTaskGetNumberOfTasks( void ) FREERTOS_SYSTEM_CALL;
|
||||
UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||
configSTACK_DEPTH_TYPE MPU_uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||
void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask,
|
||||
TaskHookFunction_t pxHookFunction ) FREERTOS_SYSTEM_CALL;
|
||||
TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||
void MPU_vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet,
|
||||
BaseType_t xIndex,
|
||||
void * pvValue ) FREERTOS_SYSTEM_CALL;
|
||||
void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery,
|
||||
BaseType_t xIndex ) FREERTOS_SYSTEM_CALL;
|
||||
TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ) FREERTOS_SYSTEM_CALL;
|
||||
UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
|
||||
const UBaseType_t uxArraySize,
|
||||
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) FREERTOS_SYSTEM_CALL;
|
||||
configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetRunTimeCounter( const TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||
configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetRunTimePercent( const TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||
configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimeCounter( void ) FREERTOS_SYSTEM_CALL;
|
||||
configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimePercent( void ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify,
|
||||
UBaseType_t uxIndexToNotify,
|
||||
uint32_t ulValue,
|
||||
eNotifyAction eAction,
|
||||
uint32_t * pulPreviousNotificationValue ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xTaskGenericNotifyEntry( const xTaskGenericNotifyParams_t * pxParams ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn,
|
||||
uint32_t ulBitsToClearOnEntry,
|
||||
uint32_t ulBitsToClearOnExit,
|
||||
uint32_t * pulNotificationValue,
|
||||
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xTaskGenericNotifyWaitEntry( const xTaskGenericNotifyWaitParams_t * pxParams ) FREERTOS_SYSTEM_CALL;
|
||||
uint32_t MPU_ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn,
|
||||
BaseType_t xClearCountOnExit,
|
||||
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xTaskGenericNotifyStateClear( TaskHandle_t xTask,
|
||||
UBaseType_t uxIndexToClear ) FREERTOS_SYSTEM_CALL;
|
||||
uint32_t MPU_ulTaskGenericNotifyValueClear( TaskHandle_t xTask,
|
||||
UBaseType_t uxIndexToClear,
|
||||
uint32_t ulBitsToClear ) FREERTOS_SYSTEM_CALL;
|
||||
void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
|
||||
TickType_t * const pxTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||
TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xTaskGetSchedulerState( void ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/* Privileged only wrappers for Task APIs. These are needed so that
|
||||
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||
* with all the APIs. */
|
||||
BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode,
|
||||
const char * const pcName,
|
||||
const uint16_t usStackDepth,
|
||||
void * const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION;
|
||||
TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode,
|
||||
const char * const pcName,
|
||||
const uint32_t ulStackDepth,
|
||||
void * const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
StackType_t * const puxStackBuffer,
|
||||
StaticTask_t * const pxTaskBuffer ) PRIVILEGED_FUNCTION;
|
||||
void MPU_vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION;
|
||||
void MPU_vTaskPrioritySet( TaskHandle_t xTask,
|
||||
UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION;
|
||||
TaskHandle_t MPU_xTaskGetHandle( const char * pcNameToQuery ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask,
|
||||
void * pvParameter ) PRIVILEGED_FUNCTION;
|
||||
char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition,
|
||||
TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition,
|
||||
TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION;
|
||||
void MPU_vTaskAllocateMPURegions( TaskHandle_t xTaskToModify,
|
||||
const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xTaskGetStaticBuffers( TaskHandle_t xTask,
|
||||
StackType_t ** ppuxStackBuffer,
|
||||
StaticTask_t ** ppxTaskBuffer ) PRIVILEGED_FUNCTION;
|
||||
UBaseType_t MPU_uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
|
||||
UBaseType_t MPU_uxTaskBasePriorityGet( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
|
||||
UBaseType_t MPU_uxTaskBasePriorityGetFromISR( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION;
|
||||
TaskHookFunction_t MPU_xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify,
|
||||
UBaseType_t uxIndexToNotify,
|
||||
uint32_t ulValue,
|
||||
eNotifyAction eAction,
|
||||
uint32_t * pulPreviousNotificationValue,
|
||||
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
void MPU_vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
|
||||
UBaseType_t uxIndexToNotify,
|
||||
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/* MPU versions of queue.h API functions. */
|
||||
BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue,
|
||||
const void * const pvItemToQueue,
|
||||
TickType_t xTicksToWait,
|
||||
const BaseType_t xCopyPosition ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xQueueReceive( QueueHandle_t xQueue,
|
||||
void * const pvBuffer,
|
||||
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xQueuePeek( QueueHandle_t xQueue,
|
||||
void * const pvBuffer,
|
||||
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xQueueSemaphoreTake( QueueHandle_t xQueue,
|
||||
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||
UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||
UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||
TaskHandle_t MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex,
|
||||
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) FREERTOS_SYSTEM_CALL;
|
||||
void MPU_vQueueAddToRegistry( QueueHandle_t xQueue,
|
||||
const char * pcName ) FREERTOS_SYSTEM_CALL;
|
||||
void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||
const char * MPU_pcQueueGetName( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
|
||||
QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL;
|
||||
QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet,
|
||||
const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||
void MPU_vQueueSetQueueNumber( QueueHandle_t xQueue,
|
||||
UBaseType_t uxQueueNumber ) FREERTOS_SYSTEM_CALL;
|
||||
UBaseType_t MPU_uxQueueGetQueueNumber( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||
uint8_t MPU_ucQueueGetQueueType( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/* Privileged only wrappers for Queue APIs. These are needed so that
|
||||
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||
* with all the APIs. */
|
||||
void MPU_vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
|
||||
QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
|
||||
QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType,
|
||||
StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION;
|
||||
QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,
|
||||
const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION;
|
||||
QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount,
|
||||
const UBaseType_t uxInitialCount,
|
||||
StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION;
|
||||
QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength,
|
||||
const UBaseType_t uxItemSize,
|
||||
const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
|
||||
QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength,
|
||||
const UBaseType_t uxItemSize,
|
||||
uint8_t * pucQueueStorage,
|
||||
StaticQueue_t * pxStaticQueue,
|
||||
const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
|
||||
QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore,
|
||||
QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue,
|
||||
BaseType_t xNewQueue ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xQueueGenericGetStaticBuffers( QueueHandle_t xQueue,
|
||||
uint8_t ** ppucQueueStorage,
|
||||
StaticQueue_t ** ppxStaticQueue ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xQueueGenericSendFromISR( QueueHandle_t xQueue,
|
||||
const void * const pvItemToQueue,
|
||||
BaseType_t * const pxHigherPriorityTaskWoken,
|
||||
const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xQueueGiveFromISR( QueueHandle_t xQueue,
|
||||
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xQueuePeekFromISR( QueueHandle_t xQueue,
|
||||
void * const pvBuffer ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xQueueReceiveFromISR( QueueHandle_t xQueue,
|
||||
void * const pvBuffer,
|
||||
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
|
||||
UBaseType_t MPU_uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
|
||||
TaskHandle_t MPU_xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION;
|
||||
QueueSetMemberHandle_t MPU_xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/* MPU versions of timers.h API functions. */
|
||||
void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||
void MPU_vTimerSetTimerID( TimerHandle_t xTimer,
|
||||
void * pvNewID ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||
TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xTimerGenericCommandFromTask( TimerHandle_t xTimer,
|
||||
const BaseType_t xCommandID,
|
||||
const TickType_t xOptionalValue,
|
||||
BaseType_t * const pxHigherPriorityTaskWoken,
|
||||
const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xTimerGenericCommandFromTaskEntry( const xTimerGenericCommandFromTaskParams_t * pxParams ) FREERTOS_SYSTEM_CALL;
|
||||
const char * MPU_pcTimerGetName( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||
void MPU_vTimerSetReloadMode( TimerHandle_t xTimer,
|
||||
const BaseType_t uxAutoReload ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xTimerGetReloadMode( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||
UBaseType_t MPU_uxTimerGetReloadMode( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||
TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||
TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/* Privileged only wrappers for Timer APIs. These are needed so that
|
||||
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||
* with all the APIs. */
|
||||
TimerHandle_t MPU_xTimerCreate( const char * const pcTimerName,
|
||||
const TickType_t xTimerPeriodInTicks,
|
||||
const UBaseType_t uxAutoReload,
|
||||
void * const pvTimerID,
|
||||
TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION;
|
||||
TimerHandle_t MPU_xTimerCreateStatic( const char * const pcTimerName,
|
||||
const TickType_t xTimerPeriodInTicks,
|
||||
const UBaseType_t uxAutoReload,
|
||||
void * const pvTimerID,
|
||||
TimerCallbackFunction_t pxCallbackFunction,
|
||||
StaticTimer_t * pxTimerBuffer ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xTimerGetStaticBuffer( TimerHandle_t xTimer,
|
||||
StaticTimer_t ** ppxTimerBuffer ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xTimerGenericCommandFromISR( TimerHandle_t xTimer,
|
||||
const BaseType_t xCommandID,
|
||||
const TickType_t xOptionalValue,
|
||||
BaseType_t * const pxHigherPriorityTaskWoken,
|
||||
const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/* MPU versions of event_group.h API functions. */
|
||||
EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToWaitFor,
|
||||
const BaseType_t xClearOnExit,
|
||||
const BaseType_t xWaitForAllBits,
|
||||
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||
EventBits_t MPU_xEventGroupWaitBitsEntry( const xEventGroupWaitBitsParams_t * pxParams ) FREERTOS_SYSTEM_CALL;
|
||||
EventBits_t MPU_xEventGroupClearBits( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToClear ) FREERTOS_SYSTEM_CALL;
|
||||
EventBits_t MPU_xEventGroupSetBits( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToSet ) FREERTOS_SYSTEM_CALL;
|
||||
EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToSet,
|
||||
const EventBits_t uxBitsToWaitFor,
|
||||
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
UBaseType_t MPU_uxEventGroupGetNumber( void * xEventGroup ) FREERTOS_SYSTEM_CALL;
|
||||
void MPU_vEventGroupSetNumber( void * xEventGroup,
|
||||
UBaseType_t uxEventGroupNumber ) FREERTOS_SYSTEM_CALL;
|
||||
#endif /* ( configUSE_TRACE_FACILITY == 1 )*/
|
||||
|
||||
/* Privileged only wrappers for Event Group APIs. These are needed so that
|
||||
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||
* with all the APIs. */
|
||||
EventGroupHandle_t MPU_xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
|
||||
EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) PRIVILEGED_FUNCTION;
|
||||
void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup,
|
||||
StaticEventGroup_t ** ppxEventGroupBuffer ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToSet,
|
||||
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
EventBits_t MPU_xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/* MPU versions of message/stream_buffer.h API functions. */
|
||||
size_t MPU_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
|
||||
const void * pvTxData,
|
||||
size_t xDataLengthBytes,
|
||||
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||
size_t MPU_xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
|
||||
void * pvRxData,
|
||||
size_t xBufferLengthBytes,
|
||||
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||
size_t MPU_xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||
size_t MPU_xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||
BaseType_t MPU_xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer,
|
||||
size_t xTriggerLevel ) FREERTOS_SYSTEM_CALL;
|
||||
size_t MPU_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/* Privileged only wrappers for Stream Buffer APIs. These are needed so that
|
||||
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||
* with all the APIs. */
|
||||
StreamBufferHandle_t MPU_xStreamBufferGenericCreate( size_t xBufferSizeBytes,
|
||||
size_t xTriggerLevelBytes,
|
||||
BaseType_t xIsMessageBuffer,
|
||||
StreamBufferCallbackFunction_t pxSendCompletedCallback,
|
||||
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION;
|
||||
StreamBufferHandle_t MPU_xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
|
||||
size_t xTriggerLevelBytes,
|
||||
BaseType_t xIsMessageBuffer,
|
||||
uint8_t * const pucStreamBufferStorageArea,
|
||||
StaticStreamBuffer_t * const pxStaticStreamBuffer,
|
||||
StreamBufferCallbackFunction_t pxSendCompletedCallback,
|
||||
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION;
|
||||
void MPU_vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xStreamBufferGetStaticBuffers( StreamBufferHandle_t xStreamBuffers,
|
||||
uint8_t * ppucStreamBufferStorageArea,
|
||||
StaticStreamBuffer_t * ppxStaticStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
size_t MPU_xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||
const void * pvTxData,
|
||||
size_t xDataLengthBytes,
|
||||
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
size_t MPU_xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||
void * pvRxData,
|
||||
size_t xBufferLengthBytes,
|
||||
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t MPU_xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* MPU_PROTOTYPES_H */
|
||||
|
||||
105
pico-sensor/McuLib/FreeRTOS/Source/include/mpu_syscall_numbers.h
Normal file
105
pico-sensor/McuLib/FreeRTOS/Source/include/mpu_syscall_numbers.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MPU_SYSCALL_NUMBERS_H
|
||||
#define MPU_SYSCALL_NUMBERS_H
|
||||
|
||||
/* Numbers assigned to various system calls. */
|
||||
#define SYSTEM_CALL_xTaskGenericNotify 0
|
||||
#define SYSTEM_CALL_xTaskGenericNotifyWait 1
|
||||
#define SYSTEM_CALL_xTimerGenericCommandFromTask 2
|
||||
#define SYSTEM_CALL_xEventGroupWaitBits 3
|
||||
#define SYSTEM_CALL_xTaskDelayUntil 4
|
||||
#define SYSTEM_CALL_xTaskAbortDelay 5
|
||||
#define SYSTEM_CALL_vTaskDelay 6
|
||||
#define SYSTEM_CALL_uxTaskPriorityGet 7
|
||||
#define SYSTEM_CALL_eTaskGetState 8
|
||||
#define SYSTEM_CALL_vTaskGetInfo 9
|
||||
#define SYSTEM_CALL_xTaskGetIdleTaskHandle 10
|
||||
#define SYSTEM_CALL_vTaskSuspend 11
|
||||
#define SYSTEM_CALL_vTaskResume 12
|
||||
#define SYSTEM_CALL_xTaskGetTickCount 13
|
||||
#define SYSTEM_CALL_uxTaskGetNumberOfTasks 14
|
||||
#define SYSTEM_CALL_ulTaskGetRunTimeCounter 15
|
||||
#define SYSTEM_CALL_ulTaskGetRunTimePercent 16
|
||||
#define SYSTEM_CALL_ulTaskGetIdleRunTimePercent 17
|
||||
#define SYSTEM_CALL_ulTaskGetIdleRunTimeCounter 18
|
||||
#define SYSTEM_CALL_vTaskSetApplicationTaskTag 19
|
||||
#define SYSTEM_CALL_xTaskGetApplicationTaskTag 20
|
||||
#define SYSTEM_CALL_vTaskSetThreadLocalStoragePointer 21
|
||||
#define SYSTEM_CALL_pvTaskGetThreadLocalStoragePointer 22
|
||||
#define SYSTEM_CALL_uxTaskGetSystemState 23
|
||||
#define SYSTEM_CALL_uxTaskGetStackHighWaterMark 24
|
||||
#define SYSTEM_CALL_uxTaskGetStackHighWaterMark2 25
|
||||
#define SYSTEM_CALL_xTaskGetCurrentTaskHandle 26
|
||||
#define SYSTEM_CALL_xTaskGetSchedulerState 27
|
||||
#define SYSTEM_CALL_vTaskSetTimeOutState 28
|
||||
#define SYSTEM_CALL_xTaskCheckForTimeOut 29
|
||||
#define SYSTEM_CALL_ulTaskGenericNotifyTake 30
|
||||
#define SYSTEM_CALL_xTaskGenericNotifyStateClear 31
|
||||
#define SYSTEM_CALL_ulTaskGenericNotifyValueClear 32
|
||||
#define SYSTEM_CALL_xQueueGenericSend 33
|
||||
#define SYSTEM_CALL_uxQueueMessagesWaiting 34
|
||||
#define SYSTEM_CALL_uxQueueSpacesAvailable 35
|
||||
#define SYSTEM_CALL_xQueueReceive 36
|
||||
#define SYSTEM_CALL_xQueuePeek 37
|
||||
#define SYSTEM_CALL_xQueueSemaphoreTake 38
|
||||
#define SYSTEM_CALL_xQueueGetMutexHolder 39
|
||||
#define SYSTEM_CALL_xQueueTakeMutexRecursive 40
|
||||
#define SYSTEM_CALL_xQueueGiveMutexRecursive 41
|
||||
#define SYSTEM_CALL_xQueueSelectFromSet 42
|
||||
#define SYSTEM_CALL_xQueueAddToSet 43
|
||||
#define SYSTEM_CALL_vQueueAddToRegistry 44
|
||||
#define SYSTEM_CALL_vQueueUnregisterQueue 45
|
||||
#define SYSTEM_CALL_pcQueueGetName 46
|
||||
#define SYSTEM_CALL_pvTimerGetTimerID 47
|
||||
#define SYSTEM_CALL_vTimerSetTimerID 48
|
||||
#define SYSTEM_CALL_xTimerIsTimerActive 49
|
||||
#define SYSTEM_CALL_xTimerGetTimerDaemonTaskHandle 50
|
||||
#define SYSTEM_CALL_pcTimerGetName 51
|
||||
#define SYSTEM_CALL_vTimerSetReloadMode 52
|
||||
#define SYSTEM_CALL_xTimerGetReloadMode 53
|
||||
#define SYSTEM_CALL_uxTimerGetReloadMode 54
|
||||
#define SYSTEM_CALL_xTimerGetPeriod 55
|
||||
#define SYSTEM_CALL_xTimerGetExpiryTime 56
|
||||
#define SYSTEM_CALL_xEventGroupClearBits 57
|
||||
#define SYSTEM_CALL_xEventGroupSetBits 58
|
||||
#define SYSTEM_CALL_xEventGroupSync 59
|
||||
#define SYSTEM_CALL_uxEventGroupGetNumber 60
|
||||
#define SYSTEM_CALL_vEventGroupSetNumber 61
|
||||
#define SYSTEM_CALL_xStreamBufferSend 62
|
||||
#define SYSTEM_CALL_xStreamBufferReceive 63
|
||||
#define SYSTEM_CALL_xStreamBufferIsFull 64
|
||||
#define SYSTEM_CALL_xStreamBufferIsEmpty 65
|
||||
#define SYSTEM_CALL_xStreamBufferSpacesAvailable 66
|
||||
#define SYSTEM_CALL_xStreamBufferBytesAvailable 67
|
||||
#define SYSTEM_CALL_xStreamBufferSetTriggerLevel 68
|
||||
#define SYSTEM_CALL_xStreamBufferNextMessageLengthBytes 69
|
||||
#define NUM_SYSTEM_CALLS 70 /* Total number of system calls. */
|
||||
|
||||
#endif /* MPU_SYSCALL_NUMBERS_H */
|
||||
287
pico-sensor/McuLib/FreeRTOS/Source/include/mpu_wrappers.h
Normal file
287
pico-sensor/McuLib/FreeRTOS/Source/include/mpu_wrappers.h
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MPU_WRAPPERS_H
|
||||
#define MPU_WRAPPERS_H
|
||||
|
||||
/* This file redefines API functions to be called through a wrapper macro, but
|
||||
* only for ports that are using the MPU. */
|
||||
#if ( portUSING_MPU_WRAPPERS == 1 )
|
||||
|
||||
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is
|
||||
* included from queue.c or task.c to prevent it from having an effect within
|
||||
* those files. */
|
||||
#ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Map standard task.h API functions to the MPU equivalents. */
|
||||
#define vTaskDelay MPU_vTaskDelay
|
||||
#define xTaskDelayUntil MPU_xTaskDelayUntil
|
||||
#define xTaskAbortDelay MPU_xTaskAbortDelay
|
||||
#define uxTaskPriorityGet MPU_uxTaskPriorityGet
|
||||
#define eTaskGetState MPU_eTaskGetState
|
||||
#define vTaskGetInfo MPU_vTaskGetInfo
|
||||
#define vTaskSuspend MPU_vTaskSuspend
|
||||
#define vTaskResume MPU_vTaskResume
|
||||
#define xTaskGetTickCount MPU_xTaskGetTickCount
|
||||
#define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks
|
||||
#define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark
|
||||
#define uxTaskGetStackHighWaterMark2 MPU_uxTaskGetStackHighWaterMark2
|
||||
#define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag
|
||||
#define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag
|
||||
#define vTaskSetThreadLocalStoragePointer MPU_vTaskSetThreadLocalStoragePointer
|
||||
#define pvTaskGetThreadLocalStoragePointer MPU_pvTaskGetThreadLocalStoragePointer
|
||||
#define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle
|
||||
#define uxTaskGetSystemState MPU_uxTaskGetSystemState
|
||||
#define ulTaskGetIdleRunTimeCounter MPU_ulTaskGetIdleRunTimeCounter
|
||||
#define ulTaskGetIdleRunTimePercent MPU_ulTaskGetIdleRunTimePercent
|
||||
#define xTaskGenericNotify MPU_xTaskGenericNotify
|
||||
#define xTaskGenericNotifyWait MPU_xTaskGenericNotifyWait
|
||||
#define ulTaskGenericNotifyTake MPU_ulTaskGenericNotifyTake
|
||||
#define xTaskGenericNotifyStateClear MPU_xTaskGenericNotifyStateClear
|
||||
#define ulTaskGenericNotifyValueClear MPU_ulTaskGenericNotifyValueClear
|
||||
#define vTaskSetTimeOutState MPU_vTaskSetTimeOutState
|
||||
#define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut
|
||||
#define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle
|
||||
#define xTaskGetSchedulerState MPU_xTaskGetSchedulerState
|
||||
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
#define ulTaskGetRunTimeCounter MPU_ulTaskGetRunTimeCounter
|
||||
#define ulTaskGetRunTimePercent MPU_ulTaskGetRunTimePercent
|
||||
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
|
||||
/* Privileged only wrappers for Task APIs. These are needed so that
|
||||
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||
* with all the APIs. */
|
||||
#define xTaskCreate MPU_xTaskCreate
|
||||
#define xTaskCreateStatic MPU_xTaskCreateStatic
|
||||
#define vTaskDelete MPU_vTaskDelete
|
||||
#define vTaskPrioritySet MPU_vTaskPrioritySet
|
||||
#define xTaskGetHandle MPU_xTaskGetHandle
|
||||
#define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook
|
||||
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
#define pcTaskGetName MPU_pcTaskGetName
|
||||
#define xTaskCreateRestricted MPU_xTaskCreateRestricted
|
||||
#define xTaskCreateRestrictedStatic MPU_xTaskCreateRestrictedStatic
|
||||
#define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions
|
||||
#define xTaskGetStaticBuffers MPU_xTaskGetStaticBuffers
|
||||
#define uxTaskPriorityGetFromISR MPU_uxTaskPriorityGetFromISR
|
||||
#define uxTaskBasePriorityGet MPU_uxTaskBasePriorityGet
|
||||
#define uxTaskBasePriorityGetFromISR MPU_uxTaskBasePriorityGetFromISR
|
||||
#define xTaskResumeFromISR MPU_xTaskResumeFromISR
|
||||
#define xTaskGetApplicationTaskTagFromISR MPU_xTaskGetApplicationTaskTagFromISR
|
||||
#define xTaskGenericNotifyFromISR MPU_xTaskGenericNotifyFromISR
|
||||
#define vTaskGenericNotifyGiveFromISR MPU_vTaskGenericNotifyGiveFromISR
|
||||
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
|
||||
/* Map standard queue.h API functions to the MPU equivalents. */
|
||||
#define xQueueGenericSend MPU_xQueueGenericSend
|
||||
#define xQueueReceive MPU_xQueueReceive
|
||||
#define xQueuePeek MPU_xQueuePeek
|
||||
#define xQueueSemaphoreTake MPU_xQueueSemaphoreTake
|
||||
#define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting
|
||||
#define uxQueueSpacesAvailable MPU_uxQueueSpacesAvailable
|
||||
#define xQueueGetMutexHolder MPU_xQueueGetMutexHolder
|
||||
#define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive
|
||||
#define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive
|
||||
#define xQueueAddToSet MPU_xQueueAddToSet
|
||||
#define xQueueSelectFromSet MPU_xQueueSelectFromSet
|
||||
|
||||
#if ( configQUEUE_REGISTRY_SIZE > 0 )
|
||||
#define vQueueAddToRegistry MPU_vQueueAddToRegistry
|
||||
#define vQueueUnregisterQueue MPU_vQueueUnregisterQueue
|
||||
#define pcQueueGetName MPU_pcQueueGetName
|
||||
#endif /* #if ( configQUEUE_REGISTRY_SIZE > 0 ) */
|
||||
|
||||
/* Privileged only wrappers for Queue APIs. These are needed so that
|
||||
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||
* with all the APIs. */
|
||||
#define vQueueDelete MPU_vQueueDelete
|
||||
#define xQueueCreateMutex MPU_xQueueCreateMutex
|
||||
#define xQueueCreateMutexStatic MPU_xQueueCreateMutexStatic
|
||||
#define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore
|
||||
#define xQueueCreateCountingSemaphoreStatic MPU_xQueueCreateCountingSemaphoreStatic
|
||||
#define xQueueGenericCreate MPU_xQueueGenericCreate
|
||||
#define xQueueGenericCreateStatic MPU_xQueueGenericCreateStatic
|
||||
#define xQueueGenericReset MPU_xQueueGenericReset
|
||||
#define xQueueCreateSet MPU_xQueueCreateSet
|
||||
#define xQueueRemoveFromSet MPU_xQueueRemoveFromSet
|
||||
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
#define xQueueGenericGetStaticBuffers MPU_xQueueGenericGetStaticBuffers
|
||||
#define xQueueGenericSendFromISR MPU_xQueueGenericSendFromISR
|
||||
#define xQueueGiveFromISR MPU_xQueueGiveFromISR
|
||||
#define xQueuePeekFromISR MPU_xQueuePeekFromISR
|
||||
#define xQueueReceiveFromISR MPU_xQueueReceiveFromISR
|
||||
#define xQueueIsQueueEmptyFromISR MPU_xQueueIsQueueEmptyFromISR
|
||||
#define xQueueIsQueueFullFromISR MPU_xQueueIsQueueFullFromISR
|
||||
#define uxQueueMessagesWaitingFromISR MPU_uxQueueMessagesWaitingFromISR
|
||||
#define xQueueGetMutexHolderFromISR MPU_xQueueGetMutexHolderFromISR
|
||||
#define xQueueSelectFromSetFromISR MPU_xQueueSelectFromSetFromISR
|
||||
#endif /* if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
|
||||
/* Map standard timer.h API functions to the MPU equivalents. */
|
||||
#define pvTimerGetTimerID MPU_pvTimerGetTimerID
|
||||
#define vTimerSetTimerID MPU_vTimerSetTimerID
|
||||
#define xTimerIsTimerActive MPU_xTimerIsTimerActive
|
||||
#define xTimerGetTimerDaemonTaskHandle MPU_xTimerGetTimerDaemonTaskHandle
|
||||
#define xTimerGenericCommandFromTask MPU_xTimerGenericCommandFromTask
|
||||
#define pcTimerGetName MPU_pcTimerGetName
|
||||
#define vTimerSetReloadMode MPU_vTimerSetReloadMode
|
||||
#define uxTimerGetReloadMode MPU_uxTimerGetReloadMode
|
||||
#define xTimerGetPeriod MPU_xTimerGetPeriod
|
||||
#define xTimerGetExpiryTime MPU_xTimerGetExpiryTime
|
||||
|
||||
/* Privileged only wrappers for Timer APIs. These are needed so that
|
||||
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||
* with all the APIs. */
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
#define xTimerGetReloadMode MPU_xTimerGetReloadMode
|
||||
#define xTimerCreate MPU_xTimerCreate
|
||||
#define xTimerCreateStatic MPU_xTimerCreateStatic
|
||||
#define xTimerGetStaticBuffer MPU_xTimerGetStaticBuffer
|
||||
#define xTimerGenericCommandFromISR MPU_xTimerGenericCommandFromISR
|
||||
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
|
||||
/* Map standard event_group.h API functions to the MPU equivalents. */
|
||||
#define xEventGroupWaitBits MPU_xEventGroupWaitBits
|
||||
#define xEventGroupClearBits MPU_xEventGroupClearBits
|
||||
#define xEventGroupSetBits MPU_xEventGroupSetBits
|
||||
#define xEventGroupSync MPU_xEventGroupSync
|
||||
|
||||
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||
#define uxEventGroupGetNumber MPU_uxEventGroupGetNumber
|
||||
#define vEventGroupSetNumber MPU_vEventGroupSetNumber
|
||||
#endif /* #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) */
|
||||
|
||||
/* Privileged only wrappers for Event Group APIs. These are needed so that
|
||||
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||
* with all the APIs. */
|
||||
#define xEventGroupCreate MPU_xEventGroupCreate
|
||||
#define xEventGroupCreateStatic MPU_xEventGroupCreateStatic
|
||||
#define vEventGroupDelete MPU_vEventGroupDelete
|
||||
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
#define xEventGroupGetStaticBuffer MPU_xEventGroupGetStaticBuffer
|
||||
#define xEventGroupClearBitsFromISR MPU_xEventGroupClearBitsFromISR
|
||||
#define xEventGroupSetBitsFromISR MPU_xEventGroupSetBitsFromISR
|
||||
#define xEventGroupGetBitsFromISR MPU_xEventGroupGetBitsFromISR
|
||||
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
|
||||
/* Map standard message/stream_buffer.h API functions to the MPU
|
||||
* equivalents. */
|
||||
#define xStreamBufferSend MPU_xStreamBufferSend
|
||||
#define xStreamBufferReceive MPU_xStreamBufferReceive
|
||||
#define xStreamBufferIsFull MPU_xStreamBufferIsFull
|
||||
#define xStreamBufferIsEmpty MPU_xStreamBufferIsEmpty
|
||||
#define xStreamBufferSpacesAvailable MPU_xStreamBufferSpacesAvailable
|
||||
#define xStreamBufferBytesAvailable MPU_xStreamBufferBytesAvailable
|
||||
#define xStreamBufferSetTriggerLevel MPU_xStreamBufferSetTriggerLevel
|
||||
#define xStreamBufferNextMessageLengthBytes MPU_xStreamBufferNextMessageLengthBytes
|
||||
|
||||
/* Privileged only wrappers for Stream Buffer APIs. These are needed so that
|
||||
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||
* with all the APIs. */
|
||||
|
||||
#define xStreamBufferGenericCreate MPU_xStreamBufferGenericCreate
|
||||
#define xStreamBufferGenericCreateStatic MPU_xStreamBufferGenericCreateStatic
|
||||
#define vStreamBufferDelete MPU_vStreamBufferDelete
|
||||
#define xStreamBufferReset MPU_xStreamBufferReset
|
||||
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
#define xStreamBufferGetStaticBuffers MPU_xStreamBufferGetStaticBuffers
|
||||
#define xStreamBufferSendFromISR MPU_xStreamBufferSendFromISR
|
||||
#define xStreamBufferReceiveFromISR MPU_xStreamBufferReceiveFromISR
|
||||
#define xStreamBufferSendCompletedFromISR MPU_xStreamBufferSendCompletedFromISR
|
||||
#define xStreamBufferReceiveCompletedFromISR MPU_xStreamBufferReceiveCompletedFromISR
|
||||
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
|
||||
/* Remove the privileged function macro, but keep the PRIVILEGED_DATA
|
||||
* macro so applications can place data in privileged access sections
|
||||
* (useful when using statically allocated objects). */
|
||||
#define PRIVILEGED_FUNCTION
|
||||
#define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) )
|
||||
#define FREERTOS_SYSTEM_CALL
|
||||
|
||||
|
||||
#if ( ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
|
||||
|
||||
#define vGrantAccessToTask( xTask, xTaskToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xTaskToGrantAccess ) )
|
||||
#define vRevokeAccessToTask( xTask, xTaskToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xTaskToRevokeAccess ) )
|
||||
|
||||
#define vGrantAccessToSemaphore( xTask, xSemaphoreToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xSemaphoreToGrantAccess ) )
|
||||
#define vRevokeAccessToSemaphore( xTask, xSemaphoreToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xSemaphoreToRevokeAccess ) )
|
||||
|
||||
#define vGrantAccessToQueue( xTask, xQueueToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xQueueToGrantAccess ) )
|
||||
#define vRevokeAccessToQueue( xTask, xQueueToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xQueueToRevokeAccess ) )
|
||||
|
||||
#define vGrantAccessToQueueSet( xTask, xQueueSetToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xQueueSetToGrantAccess ) )
|
||||
#define vRevokeAccessToQueueSet( xTask, xQueueSetToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xQueueSetToRevokeAccess ) )
|
||||
|
||||
#define vGrantAccessToEventGroup( xTask, xEventGroupToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xEventGroupToGrantAccess ) )
|
||||
#define vRevokeAccessToEventGroup( xTask, xEventGroupToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xEventGroupToRevokeAccess ) )
|
||||
|
||||
#define vGrantAccessToStreamBuffer( xTask, xStreamBufferToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xStreamBufferToGrantAccess ) )
|
||||
#define vRevokeAccessToStreamBuffer( xTask, xStreamBufferToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xStreamBufferToRevokeAccess ) )
|
||||
|
||||
#define vGrantAccessToMessageBuffer( xTask, xMessageBufferToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xMessageBufferToGrantAccess ) )
|
||||
#define vRevokeAccessToMessageBuffer( xTask, xMessageBufferToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xMessageBufferToRevokeAccess ) )
|
||||
|
||||
#define vGrantAccessToTimer( xTask, xTimerToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xTimerToGrantAccess ) )
|
||||
#define vRevokeAccessToTimer( xTask, xTimerToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xTimerToRevokeAccess ) )
|
||||
|
||||
#endif /* #if ( ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) ) */
|
||||
|
||||
#else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
|
||||
|
||||
/* Ensure API functions go in the privileged execution section. */
|
||||
#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 */
|
||||
|
||||
#else /* portUSING_MPU_WRAPPERS */
|
||||
|
||||
#define PRIVILEGED_FUNCTION
|
||||
#define PRIVILEGED_DATA
|
||||
#define FREERTOS_SYSTEM_CALL
|
||||
|
||||
#endif /* portUSING_MPU_WRAPPERS */
|
||||
|
||||
|
||||
#endif /* MPU_WRAPPERS_H */
|
||||
|
||||
63
pico-sensor/McuLib/FreeRTOS/Source/include/newlib-freertos.h
Normal file
63
pico-sensor/McuLib/FreeRTOS/Source/include/newlib-freertos.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef INC_NEWLIB_FREERTOS_H
|
||||
#define INC_NEWLIB_FREERTOS_H
|
||||
|
||||
/* Note Newlib support has been included by popular demand, but is not
|
||||
* used by the FreeRTOS maintainers themselves. FreeRTOS is not
|
||||
* responsible for resulting newlib operation. User must be familiar with
|
||||
* newlib and must provide system-wide implementations of the necessary
|
||||
* stubs. Be warned that (at the time of writing) the current newlib design
|
||||
* implements a system-wide malloc() that must be provided with locks.
|
||||
*
|
||||
* See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html
|
||||
* for additional information. */
|
||||
|
||||
#include <reent.h>
|
||||
|
||||
#define configUSE_C_RUNTIME_TLS_SUPPORT 1
|
||||
|
||||
#ifndef configTLS_BLOCK_TYPE
|
||||
#define configTLS_BLOCK_TYPE struct _reent
|
||||
#endif
|
||||
|
||||
#ifndef configINIT_TLS_BLOCK
|
||||
#define configINIT_TLS_BLOCK( xTLSBlock, pxTopOfStack ) _REENT_INIT_PTR( &( xTLSBlock ) )
|
||||
#endif
|
||||
|
||||
#ifndef configSET_TLS_BLOCK
|
||||
#define configSET_TLS_BLOCK( xTLSBlock ) ( _impure_ptr = &( xTLSBlock ) )
|
||||
#endif
|
||||
|
||||
#ifndef configDEINIT_TLS_BLOCK
|
||||
#define configDEINIT_TLS_BLOCK( xTLSBlock ) _reclaim_reent( &( xTLSBlock ) )
|
||||
#endif
|
||||
|
||||
#endif /* INC_NEWLIB_FREERTOS_H */
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef INC_PICOLIBC_FREERTOS_H
|
||||
#define INC_PICOLIBC_FREERTOS_H
|
||||
|
||||
/* Use picolibc TLS support to allocate space for __thread variables,
|
||||
* initialize them at thread creation and set the TLS context at
|
||||
* thread switch time.
|
||||
*
|
||||
* See the picolibc TLS docs:
|
||||
* https://github.com/picolibc/picolibc/blob/main/doc/tls.md
|
||||
* for additional information. */
|
||||
|
||||
#include <picotls.h>
|
||||
|
||||
#define configUSE_C_RUNTIME_TLS_SUPPORT 1
|
||||
|
||||
#define configTLS_BLOCK_TYPE void *
|
||||
|
||||
#define picolibcTLS_SIZE ( ( portPOINTER_SIZE_TYPE ) _tls_size() )
|
||||
#define picolibcSTACK_ALIGNMENT_MASK ( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK )
|
||||
|
||||
#if __PICOLIBC_MAJOR__ > 1 || __PICOLIBC_MINOR__ >= 8
|
||||
|
||||
/* Picolibc 1.8 and newer have explicit alignment values provided
|
||||
* by the _tls_align() inline */
|
||||
#define picolibcTLS_ALIGNMENT_MASK ( ( portPOINTER_SIZE_TYPE ) ( _tls_align() - 1 ) )
|
||||
#else
|
||||
|
||||
/* For older Picolibc versions, use the general port alignment value */
|
||||
#define picolibcTLS_ALIGNMENT_MASK ( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK )
|
||||
#endif
|
||||
|
||||
/* Allocate thread local storage block off the end of the
|
||||
* stack. The picolibcTLS_SIZE macro returns the size (in
|
||||
* bytes) of the total TLS area used by the application.
|
||||
* Calculate the top of stack address. */
|
||||
#if ( portSTACK_GROWTH < 0 )
|
||||
|
||||
#define configINIT_TLS_BLOCK( xTLSBlock, pxTopOfStack ) \
|
||||
do { \
|
||||
xTLSBlock = ( void * ) ( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) - \
|
||||
picolibcTLS_SIZE ) & \
|
||||
~picolibcTLS_ALIGNMENT_MASK ); \
|
||||
pxTopOfStack = ( StackType_t * ) ( ( ( ( portPOINTER_SIZE_TYPE ) xTLSBlock ) - 1 ) & \
|
||||
~picolibcSTACK_ALIGNMENT_MASK ); \
|
||||
_init_tls( xTLSBlock ); \
|
||||
} while( 0 )
|
||||
#else /* portSTACK_GROWTH */
|
||||
#define configINIT_TLS_BLOCK( xTLSBlock, pxTopOfStack ) \
|
||||
do { \
|
||||
xTLSBlock = ( void * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack + \
|
||||
picolibcTLS_ALIGNMENT_MASK ) & ~picolibcTLS_ALIGNMENT_MASK ); \
|
||||
pxTopOfStack = ( StackType_t * ) ( ( ( ( ( portPOINTER_SIZE_TYPE ) xTLSBlock ) + \
|
||||
picolibcTLS_SIZE ) + picolibcSTACK_ALIGNMENT_MASK ) & \
|
||||
~picolibcSTACK_ALIGNMENT_MASK ); \
|
||||
_init_tls( xTLSBlock ); \
|
||||
} while( 0 )
|
||||
#endif /* portSTACK_GROWTH */
|
||||
|
||||
#define configSET_TLS_BLOCK( xTLSBlock ) _set_tls( xTLSBlock )
|
||||
|
||||
#define configDEINIT_TLS_BLOCK( xTLSBlock )
|
||||
|
||||
#endif /* INC_PICOLIBC_FREERTOS_H */
|
||||
|
||||
274
pico-sensor/McuLib/FreeRTOS/Source/include/portable.h
Normal file
274
pico-sensor/McuLib/FreeRTOS/Source/include/portable.h
Normal file
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Portable layer API. Each function must be defined for each port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
#ifndef PORTABLE_H
|
||||
#define PORTABLE_H
|
||||
|
||||
/* Each FreeRTOS port has a unique portmacro.h header file. Originally a
|
||||
* pre-processor definition was used to ensure the pre-processor found the correct
|
||||
* portmacro.h file for the port being used. That scheme was deprecated in favour
|
||||
* of setting the compiler's include path such that it found the correct
|
||||
* portmacro.h file - removing the need for the constant and allowing the
|
||||
* portmacro.h file to be located anywhere in relation to the port being used.
|
||||
* Purely for reasons of backward compatibility the old method is still valid, but
|
||||
* to make it clear that new projects should not use it, support for the port
|
||||
* 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
|
||||
* must be set in the compiler's include path. */
|
||||
#ifndef portENTER_CRITICAL
|
||||
#include "portmacro.h"
|
||||
#endif
|
||||
|
||||
#if portBYTE_ALIGNMENT == 32
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x001f )
|
||||
#elif portBYTE_ALIGNMENT == 16
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x000f )
|
||||
#elif portBYTE_ALIGNMENT == 8
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x0007 )
|
||||
#elif portBYTE_ALIGNMENT == 4
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x0003 )
|
||||
#elif portBYTE_ALIGNMENT == 2
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x0001 )
|
||||
#elif portBYTE_ALIGNMENT == 1
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x0000 )
|
||||
#else /* if portBYTE_ALIGNMENT == 32 */
|
||||
#error "Invalid portBYTE_ALIGNMENT definition"
|
||||
#endif /* if portBYTE_ALIGNMENT == 32 */
|
||||
|
||||
#ifndef portUSING_MPU_WRAPPERS
|
||||
#define portUSING_MPU_WRAPPERS 0
|
||||
#endif
|
||||
|
||||
#ifndef portNUM_CONFIGURABLE_REGIONS
|
||||
#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
|
||||
|
||||
#ifndef configSTACK_ALLOCATION_FROM_SEPARATE_HEAP
|
||||
/* Defaults to 0 for backward compatibility. */
|
||||
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
|
||||
#endif
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
/*
|
||||
* Setup the stack of a new task so it is ready to be placed under the
|
||||
* scheduler control. The registers have to be placed on the stack in
|
||||
* the order that the port expects to find them.
|
||||
*
|
||||
*/
|
||||
#if ( portUSING_MPU_WRAPPERS == 1 )
|
||||
#if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
StackType_t * pxEndOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters,
|
||||
BaseType_t xRunPrivileged,
|
||||
xMPU_SETTINGS * xMPUSettings ) PRIVILEGED_FUNCTION;
|
||||
#else
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters,
|
||||
BaseType_t xRunPrivileged,
|
||||
xMPU_SETTINGS * xMPUSettings ) PRIVILEGED_FUNCTION;
|
||||
#endif /* if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) */
|
||||
#else /* if ( portUSING_MPU_WRAPPERS == 1 ) */
|
||||
#if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
|
||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
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 /* if ( portUSING_MPU_WRAPPERS == 1 ) */
|
||||
|
||||
/* 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 *pvPortMallocExt(size_t xWantedSize, unsigned int heapTag) PRIVILEGED_FUNCTION; /* << EST: used with SystemView */
|
||||
void * pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION;
|
||||
void * pvPortCalloc( size_t xNum,
|
||||
size_t xSize ) PRIVILEGED_FUNCTION;
|
||||
void vPortFree( void * pv ) PRIVILEGED_FUNCTION;
|
||||
void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION;
|
||||
size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION;
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION;
|
||||
void vPortInitializeHeap(void) PRIVILEGED_FUNCTION; /* << EST */
|
||||
|
||||
#if ( configSTACK_ALLOCATION_FROM_SEPARATE_HEAP == 1 )
|
||||
void * pvPortMallocStack( size_t xSize ) PRIVILEGED_FUNCTION;
|
||||
void vPortFreeStack( void * pv ) PRIVILEGED_FUNCTION;
|
||||
#else
|
||||
#define pvPortMallocStack pvPortMalloc
|
||||
#define vPortFreeStack vPortFree
|
||||
#endif
|
||||
|
||||
#if ( configUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
|
||||
/**
|
||||
* task.h
|
||||
* @code{c}
|
||||
* void vApplicationMallocFailedHook( void )
|
||||
* @endcode
|
||||
*
|
||||
* This hook function is called when allocation failed.
|
||||
*/
|
||||
void vApplicationMallocFailedHook( void );
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Undo any hardware/ISR setup that was performed by xPortStartScheduler() so
|
||||
* the hardware is left in its original condition after the scheduler stops
|
||||
* executing.
|
||||
*/
|
||||
void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* 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 ulStackDepth ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Checks if the calling task is authorized to access the given buffer.
|
||||
*
|
||||
* @param pvBuffer The buffer which the calling task wants to access.
|
||||
* @param ulBufferLength The length of the pvBuffer.
|
||||
* @param ulAccessRequested The permissions that the calling task wants.
|
||||
*
|
||||
* @return pdTRUE if the calling task is authorized to access the buffer,
|
||||
* pdFALSE otherwise.
|
||||
*/
|
||||
#if ( portUSING_MPU_WRAPPERS == 1 )
|
||||
BaseType_t xPortIsAuthorizedToAccessBuffer( const void * pvBuffer,
|
||||
uint32_t ulBufferLength,
|
||||
uint32_t ulAccessRequested ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Checks if the calling task is authorized to access the given kernel object.
|
||||
*
|
||||
* @param lInternalIndexOfKernelObject The index of the kernel object in the kernel
|
||||
* object handle pool.
|
||||
*
|
||||
* @return pdTRUE if the calling task is authorized to access the kernel object,
|
||||
* pdFALSE otherwise.
|
||||
*/
|
||||
#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||
|
||||
BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* PORTABLE_H */
|
||||
|
||||
139
pico-sensor/McuLib/FreeRTOS/Source/include/projdefs.h
Normal file
139
pico-sensor/McuLib/FreeRTOS/Source/include/projdefs.h
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PROJDEFS_H
|
||||
#define PROJDEFS_H
|
||||
|
||||
/*
|
||||
* Defines the prototype to which task functions must conform. Defined in this
|
||||
* file to ensure the type is known before portable.h is included.
|
||||
*/
|
||||
typedef void (* TaskFunction_t)( void * arg );
|
||||
|
||||
/* Converts a time in milliseconds to a time in ticks. This macro can be
|
||||
* overridden by a macro of the same name defined in FreeRTOSConfig.h in case the
|
||||
* definition here is not suitable for your application. */
|
||||
#ifndef pdMS_TO_TICKS
|
||||
#define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( uint64_t ) ( xTimeInMs ) * ( uint64_t ) configTICK_RATE_HZ ) / ( uint64_t ) 1000U ) )
|
||||
#endif
|
||||
|
||||
/* Converts a time in ticks to a time in milliseconds. This macro can be
|
||||
* overridden by a macro of the same name defined in FreeRTOSConfig.h in case the
|
||||
* definition here is not suitable for your application. */
|
||||
#ifndef pdTICKS_TO_MS
|
||||
#define pdTICKS_TO_MS( xTimeInTicks ) ( ( TickType_t ) ( ( ( uint64_t ) ( xTimeInTicks ) * ( uint64_t ) 1000U ) / ( uint64_t ) configTICK_RATE_HZ ) )
|
||||
#endif
|
||||
|
||||
#define pdFALSE ( ( BaseType_t ) 0 )
|
||||
#define pdTRUE ( ( BaseType_t ) 1 )
|
||||
#define pdFALSE_SIGNED ( ( BaseType_t ) 0 )
|
||||
#define pdTRUE_SIGNED ( ( BaseType_t ) 1 )
|
||||
#define pdFALSE_UNSIGNED ( ( UBaseType_t ) 0 )
|
||||
#define pdTRUE_UNSIGNED ( ( UBaseType_t ) 1 )
|
||||
|
||||
#define pdPASS ( pdTRUE )
|
||||
#define pdFAIL ( pdFALSE )
|
||||
#define errQUEUE_EMPTY ( ( BaseType_t ) 0 )
|
||||
#define errQUEUE_FULL ( ( BaseType_t ) 0 )
|
||||
|
||||
/* FreeRTOS error definitions. */
|
||||
#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 )
|
||||
#define errQUEUE_BLOCKED ( -4 )
|
||||
#define errQUEUE_YIELD ( -5 )
|
||||
|
||||
/* Macros used for basic data corruption checks. */
|
||||
#ifndef configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES
|
||||
#define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0
|
||||
#endif
|
||||
|
||||
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
|
||||
#define pdINTEGRITY_CHECK_VALUE 0x5a5a
|
||||
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
|
||||
#define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL
|
||||
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_64_BITS )
|
||||
#define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5a5a5a5a5aULL
|
||||
#else
|
||||
#error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width.
|
||||
#endif
|
||||
|
||||
/* The following errno values are used by FreeRTOS+ components, not FreeRTOS
|
||||
* 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_EAFNOSUPPORT 97 /* Address family not supported by protocol */
|
||||
#define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */
|
||||
#define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */
|
||||
#define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */
|
||||
#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 */
|
||||
|
||||
1813
pico-sensor/McuLib/FreeRTOS/Source/include/queue.h
Normal file
1813
pico-sensor/McuLib/FreeRTOS/Source/include/queue.h
Normal file
File diff suppressed because it is too large
Load Diff
1216
pico-sensor/McuLib/FreeRTOS/Source/include/semphr.h
Normal file
1216
pico-sensor/McuLib/FreeRTOS/Source/include/semphr.h
Normal file
File diff suppressed because it is too large
Load Diff
142
pico-sensor/McuLib/FreeRTOS/Source/include/stack_macros.h
Normal file
142
pico-sensor/McuLib/FreeRTOS/Source/include/stack_macros.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef STACK_MACROS_H
|
||||
#define STACK_MACROS_H
|
||||
|
||||
/*
|
||||
* Call the stack overflow hook function if the stack of the task being swapped
|
||||
* out is currently overflowed, or looks like it might have overflowed in the
|
||||
* past.
|
||||
*
|
||||
* Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check
|
||||
* the current stack state only - comparing the current top of stack value to
|
||||
* the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1
|
||||
* will also cause the last few stack bytes to be checked to ensure the value
|
||||
* to which the bytes were set when the task was created have not been
|
||||
* overwritten. Note this second test does not guarantee that an overflowed
|
||||
* stack will always be recognised.
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* portSTACK_LIMIT_PADDING is a number of extra words to consider to be in
|
||||
* use on the stack.
|
||||
*/
|
||||
#ifndef portSTACK_LIMIT_PADDING
|
||||
#define portSTACK_LIMIT_PADDING 0
|
||||
#endif
|
||||
|
||||
#if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) )
|
||||
|
||||
/* Only the current stack state is to be checked. */
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||
do { \
|
||||
/* Is the currently saved stack pointer within the stack limit? */ \
|
||||
if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack + portSTACK_LIMIT_PADDING ) \
|
||||
{ \
|
||||
char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
|
||||
configCHECK_FOR_STACK_OVERFLOW_NAME( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); /* << EST: use macro name */ \
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) )
|
||||
|
||||
/* Only the current stack state is to be checked. */
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||
do { \
|
||||
\
|
||||
/* Is the currently saved stack pointer within the stack limit? */ \
|
||||
if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) \
|
||||
{ \
|
||||
char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
|
||||
configCHECK_FOR_STACK_OVERFLOW_NAME( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); /* << EST: use macro name */ \
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) )
|
||||
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||
do { \
|
||||
const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \
|
||||
const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5U; \
|
||||
\
|
||||
if( ( pulStack[ 0 ] != ulCheckValue ) || \
|
||||
( pulStack[ 1 ] != ulCheckValue ) || \
|
||||
( pulStack[ 2 ] != ulCheckValue ) || \
|
||||
( pulStack[ 3 ] != ulCheckValue ) ) \
|
||||
{ \
|
||||
char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
|
||||
configCHECK_FOR_STACK_OVERFLOW_NAME( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); /* << EST: use macro name */ \
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) )
|
||||
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||
do { \
|
||||
int8_t * pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \
|
||||
static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \
|
||||
\
|
||||
\
|
||||
pcEndOfStack -= sizeof( ucExpectedStackBytes ); \
|
||||
\
|
||||
/* Has the extremity of the task stack ever been written over? */ \
|
||||
if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \
|
||||
{ \
|
||||
char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
|
||||
configCHECK_FOR_STACK_OVERFLOW_NAME( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); /* << EST: use macro name */ \
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Remove stack overflow macro if not being used. */
|
||||
#ifndef taskCHECK_FOR_STACK_OVERFLOW
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW()
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif /* STACK_MACROS_H */
|
||||
|
||||
947
pico-sensor/McuLib/FreeRTOS/Source/include/stream_buffer.h
Normal file
947
pico-sensor/McuLib/FreeRTOS/Source/include/stream_buffer.h
Normal file
@@ -0,0 +1,947 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 xStreamBufferReceive()) 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
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#if defined( __cplusplus )
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Type used as a stream buffer's optional callback.
|
||||
*/
|
||||
typedef void (* StreamBufferCallbackFunction_t)( StreamBufferHandle_t xStreamBuffer,
|
||||
BaseType_t xIsInsideISR,
|
||||
BaseType_t * const pxHigherPriorityTaskWoken );
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* StreamBufferHandle_t xStreamBufferCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes );
|
||||
* @endcode
|
||||
*
|
||||
* Creates a new stream buffer using dynamically allocated memory. See
|
||||
* xStreamBufferCreateStatic() for a version that uses statically allocated
|
||||
* 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.
|
||||
*
|
||||
* @param pxSendCompletedCallback Callback invoked when number of bytes at least equal to
|
||||
* trigger level is sent to the stream buffer. If the parameter is NULL, it will use the default
|
||||
* implementation provided by sbSEND_COMPLETED macro. To enable the callback,
|
||||
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
|
||||
*
|
||||
* @param pxReceiveCompletedCallback Callback invoked when more than zero bytes are read from a
|
||||
* stream buffer. If the parameter is NULL, it will use the default
|
||||
* implementation provided by sbRECEIVE_COMPLETED macro. To enable the callback,
|
||||
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
|
||||
*
|
||||
* @return If NULL is returned, then the stream buffer cannot be created
|
||||
* because there is insufficient heap memory available for FreeRTOS to allocate
|
||||
* the stream buffer data structures and storage area. A non-NULL value being
|
||||
* 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
|
||||
* \defgroup xStreamBufferCreate xStreamBufferCreate
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
|
||||
#define xStreamBufferCreate( xBufferSizeBytes, xTriggerLevelBytes ) \
|
||||
xStreamBufferGenericCreate( ( xBufferSizeBytes ), ( xTriggerLevelBytes ), pdFALSE, NULL, NULL )
|
||||
|
||||
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
|
||||
#define xStreamBufferCreateWithCallback( xBufferSizeBytes, xTriggerLevelBytes, pxSendCompletedCallback, pxReceiveCompletedCallback ) \
|
||||
xStreamBufferGenericCreate( ( xBufferSizeBytes ), ( xTriggerLevelBytes ), pdFALSE, ( pxSendCompletedCallback ), ( pxReceiveCompletedCallback ) )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* StreamBufferHandle_t xStreamBufferCreateStatic( size_t xBufferSizeBytes,
|
||||
* size_t xTriggerLevelBytes,
|
||||
* uint8_t *pucStreamBufferStorageArea,
|
||||
* StaticStreamBuffer_t *pxStaticStreamBuffer );
|
||||
* @endcode
|
||||
* Creates a new stream buffer using statically allocated memory. See
|
||||
* xStreamBufferCreate() for a version that uses dynamically allocated memory.
|
||||
*
|
||||
* 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 big. This is the array to which streams are
|
||||
* copied when they are written to the stream buffer.
|
||||
*
|
||||
* @param pxStaticStreamBuffer Must point to a variable of type
|
||||
* StaticStreamBuffer_t, which will be used to hold the stream buffer's data
|
||||
* structure.
|
||||
*
|
||||
* @param pxSendCompletedCallback Callback invoked when number of bytes at least equal to
|
||||
* trigger level is sent to the stream buffer. If the parameter is NULL, it will use the default
|
||||
* implementation provided by sbSEND_COMPLETED macro. To enable the callback,
|
||||
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
|
||||
*
|
||||
* @param pxReceiveCompletedCallback Callback invoked when more than zero bytes are read from a
|
||||
* stream buffer. If the parameter is NULL, it will use the default
|
||||
* implementation provided by sbRECEIVE_COMPLETED macro. To enable the callback,
|
||||
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
|
||||
*
|
||||
* @return If the stream buffer is created successfully then a handle to the
|
||||
* created stream buffer is returned. If either pucStreamBufferStorageArea or
|
||||
* pxStaticstreamBuffer are NULL then NULL is returned.
|
||||
*
|
||||
* Example use:
|
||||
* @code{c}
|
||||
*
|
||||
* // Used to dimension the array used to hold the streams. The available space
|
||||
* // will actually be one less than this, so 999.
|
||||
#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( ucStorageBuffer ),
|
||||
* xTriggerLevel,
|
||||
* ucStorageBuffer,
|
||||
* &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
|
||||
* \defgroup xStreamBufferCreateStatic xStreamBufferCreateStatic
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
|
||||
#define xStreamBufferCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer ) \
|
||||
xStreamBufferGenericCreateStatic( ( xBufferSizeBytes ), ( xTriggerLevelBytes ), pdFALSE, ( pucStreamBufferStorageArea ), ( pxStaticStreamBuffer ), NULL, NULL )
|
||||
|
||||
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
|
||||
#define xStreamBufferCreateStaticWithCallback( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback ) \
|
||||
xStreamBufferGenericCreateStatic( ( xBufferSizeBytes ), ( xTriggerLevelBytes ), pdFALSE, ( pucStreamBufferStorageArea ), ( pxStaticStreamBuffer ), ( pxSendCompletedCallback ), ( pxReceiveCompletedCallback ) )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* BaseType_t xStreamBufferGetStaticBuffers( StreamBufferHandle_t xStreamBuffer,
|
||||
* uint8_t ** ppucStreamBufferStorageArea,
|
||||
* StaticStreamBuffer_t ** ppxStaticStreamBuffer );
|
||||
* @endcode
|
||||
*
|
||||
* Retrieve pointers to a statically created stream buffer's data structure
|
||||
* buffer and storage area buffer. These are the same buffers that are supplied
|
||||
* at the time of creation.
|
||||
*
|
||||
* @param xStreamBuffer The stream buffer for which to retrieve the buffers.
|
||||
*
|
||||
* @param ppucStreamBufferStorageArea Used to return a pointer to the stream
|
||||
* buffer's storage area buffer.
|
||||
*
|
||||
* @param ppxStaticStreamBuffer Used to return a pointer to the stream
|
||||
* buffer's data structure buffer.
|
||||
*
|
||||
* @return pdTRUE if buffers were retrieved, pdFALSE otherwise.
|
||||
*
|
||||
* \defgroup xStreamBufferGetStaticBuffers xStreamBufferGetStaticBuffers
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
BaseType_t xStreamBufferGetStaticBuffers( StreamBufferHandle_t xStreamBuffer,
|
||||
uint8_t ** ppucStreamBufferStorageArea,
|
||||
StaticStreamBuffer_t ** ppxStaticStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
|
||||
* const void *pvTxData,
|
||||
* size_t xDataLengthBytes,
|
||||
* TickType_t xTicksToWait );
|
||||
* @endcode
|
||||
*
|
||||
* Sends bytes to a stream buffer. The bytes are copied into the stream buffer.
|
||||
*
|
||||
* ***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 xStreamBufferReceive()) 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
|
||||
* \defgroup xStreamBufferSend xStreamBufferSend
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
|
||||
const void * pvTxData,
|
||||
size_t xDataLengthBytes,
|
||||
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||
* const void *pvTxData,
|
||||
* size_t xDataLengthBytes,
|
||||
* BaseType_t *pxHigherPriorityTaskWoken );
|
||||
* @endcode
|
||||
*
|
||||
* Interrupt safe version of the API function that sends a stream of bytes to
|
||||
* the stream buffer.
|
||||
*
|
||||
* ***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 xStreamBufferReceive()) 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 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
|
||||
* \defgroup xStreamBufferSendFromISR xStreamBufferSendFromISR
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||
const void * pvTxData,
|
||||
size_t xDataLengthBytes,
|
||||
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
|
||||
* void *pvRxData,
|
||||
* size_t xBufferLengthBytes,
|
||||
* TickType_t xTicksToWait );
|
||||
* @endcode
|
||||
*
|
||||
* Receives bytes from a stream buffer.
|
||||
*
|
||||
* ***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 xStreamBufferReceive()) 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 xReceivedBytes bytes of data, which can
|
||||
* // be processed here....
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
* \defgroup xStreamBufferReceive xStreamBufferReceive
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
|
||||
void * pvRxData,
|
||||
size_t xBufferLengthBytes,
|
||||
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||
* void *pvRxData,
|
||||
* size_t xBufferLengthBytes,
|
||||
* BaseType_t *pxHigherPriorityTaskWoken );
|
||||
* @endcode
|
||||
*
|
||||
* An interrupt safe version of the API function that receives bytes from a
|
||||
* stream buffer.
|
||||
*
|
||||
* 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 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
|
||||
* \defgroup xStreamBufferReceiveFromISR xStreamBufferReceiveFromISR
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||
void * pvRxData,
|
||||
size_t xBufferLengthBytes,
|
||||
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer );
|
||||
* @endcode
|
||||
*
|
||||
* Deletes a stream buffer that was previously created using a call to
|
||||
* xStreamBufferCreate() or xStreamBufferCreateStatic(). If the stream
|
||||
* 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.
|
||||
*
|
||||
* \defgroup vStreamBufferDelete vStreamBufferDelete
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer );
|
||||
* @endcode
|
||||
*
|
||||
* Queries a stream buffer to see if it is full. A stream buffer is full if it
|
||||
* does not have any free space, and therefore cannot accept any more data.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* \defgroup xStreamBufferIsFull xStreamBufferIsFull
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer );
|
||||
* @endcode
|
||||
*
|
||||
* Queries a stream buffer to see if it is empty. A stream buffer is empty if
|
||||
* it does not contain any data.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* \defgroup xStreamBufferIsEmpty xStreamBufferIsEmpty
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer );
|
||||
* @endcode
|
||||
*
|
||||
* Resets a stream buffer to its initial, empty, state. Any data that was in
|
||||
* the stream buffer is discarded. A stream buffer can only be reset if there
|
||||
* 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.
|
||||
*
|
||||
* \defgroup xStreamBufferReset xStreamBufferReset
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer );
|
||||
* @endcode
|
||||
*
|
||||
* Queries a stream buffer to see how much free space it contains, which is
|
||||
* equal to the amount of data that can be sent to the stream buffer before it
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer );
|
||||
* @endcode
|
||||
*
|
||||
* Queries a stream buffer to see how much data it contains, which is equal to
|
||||
* the number of bytes that can be read from the stream buffer before the stream
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel );
|
||||
* @endcode
|
||||
*
|
||||
* A stream buffer's trigger level is the number of bytes that must be in the
|
||||
* stream buffer before a task that is blocked on the stream buffer to
|
||||
* 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.
|
||||
*
|
||||
* \defgroup xStreamBufferSetTriggerLevel xStreamBufferSetTriggerLevel
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer,
|
||||
size_t xTriggerLevel ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
|
||||
* @endcode
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* \defgroup xStreamBufferSendCompletedFromISR xStreamBufferSendCompletedFromISR
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* stream_buffer.h
|
||||
*
|
||||
* @code{c}
|
||||
* BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
|
||||
* @endcode
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* \defgroup xStreamBufferReceiveCompletedFromISR xStreamBufferReceiveCompletedFromISR
|
||||
* \ingroup StreamBufferManagement
|
||||
*/
|
||||
BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/* Functions below here are not part of the public API. */
|
||||
StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes,
|
||||
size_t xTriggerLevelBytes,
|
||||
BaseType_t xIsMessageBuffer,
|
||||
StreamBufferCallbackFunction_t pxSendCompletedCallback,
|
||||
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
|
||||
size_t xTriggerLevelBytes,
|
||||
BaseType_t xIsMessageBuffer,
|
||||
uint8_t * const pucStreamBufferStorageArea,
|
||||
StaticStreamBuffer_t * const pxStaticStreamBuffer,
|
||||
StreamBufferCallbackFunction_t pxSendCompletedCallback,
|
||||
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#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
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#if defined( __cplusplus )
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* !defined( STREAM_BUFFER_H ) */
|
||||
|
||||
3801
pico-sensor/McuLib/FreeRTOS/Source/include/task.h
Normal file
3801
pico-sensor/McuLib/FreeRTOS/Source/include/task.h
Normal file
File diff suppressed because it is too large
Load Diff
1426
pico-sensor/McuLib/FreeRTOS/Source/include/timers.h
Normal file
1426
pico-sensor/McuLib/FreeRTOS/Source/include/timers.h
Normal file
File diff suppressed because it is too large
Load Diff
248
pico-sensor/McuLib/FreeRTOS/Source/list.c
Normal file
248
pico-sensor/McuLib/FreeRTOS/Source/list.c
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||
* all the API functions to use the MPU wrappers. That should only be done when
|
||||
* task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "list.h"
|
||||
|
||||
/* 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
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* PUBLIC LIST API documented in list.h
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
void vListInitialise( List_t * const pxList )
|
||||
{
|
||||
traceENTER_vListInitialise( pxList );
|
||||
|
||||
/* The list structure contains a list item which is used to mark the
|
||||
* end of the list. To initialise the list the list end is inserted
|
||||
* as the only list entry. */
|
||||
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );
|
||||
|
||||
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) );
|
||||
|
||||
/* The list end value is the highest possible value in the list to
|
||||
* ensure it remains at the end of the list. */
|
||||
pxList->xListEnd.xItemValue = portMAX_DELAY;
|
||||
|
||||
/* 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 );
|
||||
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );
|
||||
|
||||
/* Initialize the remaining fields of xListEnd when it is a proper ListItem_t */
|
||||
#if ( configUSE_MINI_LIST_ITEM == 0 )
|
||||
{
|
||||
pxList->xListEnd.pvOwner = NULL;
|
||||
pxList->xListEnd.pxContainer = NULL;
|
||||
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
|
||||
|
||||
/* Write known values into the list if
|
||||
* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
|
||||
listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
|
||||
|
||||
traceRETURN_vListInitialise();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vListInitialiseItem( ListItem_t * const pxItem )
|
||||
{
|
||||
traceENTER_vListInitialiseItem( pxItem );
|
||||
|
||||
/* Make sure the list item is not recorded as being on a list. */
|
||||
pxItem->pxContainer = NULL;
|
||||
|
||||
/* Write known values into the list item if
|
||||
* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
|
||||
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
|
||||
|
||||
traceRETURN_vListInitialiseItem();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vListInsertEnd( List_t * const pxList,
|
||||
ListItem_t * const pxNewListItem )
|
||||
{
|
||||
ListItem_t * const pxIndex = pxList->pxIndex;
|
||||
|
||||
traceENTER_vListInsertEnd( pxList, pxNewListItem );
|
||||
|
||||
/* Only effective when configASSERT() is also defined, these tests may catch
|
||||
* the list data structures being overwritten in memory. They will not catch
|
||||
* data errors caused by incorrect configuration or use of FreeRTOS. */
|
||||
listTEST_LIST_INTEGRITY( pxList );
|
||||
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
|
||||
|
||||
/* Insert a new list item into pxList, but rather than sort the list,
|
||||
* makes the new list item the last item to be removed by a call to
|
||||
* listGET_OWNER_OF_NEXT_ENTRY(). */
|
||||
pxNewListItem->pxNext = pxIndex;
|
||||
pxNewListItem->pxPrevious = pxIndex->pxPrevious;
|
||||
|
||||
/* Only used during decision coverage testing. */
|
||||
mtCOVERAGE_TEST_DELAY();
|
||||
|
||||
pxIndex->pxPrevious->pxNext = pxNewListItem;
|
||||
pxIndex->pxPrevious = pxNewListItem;
|
||||
|
||||
/* Remember which list the item is in. */
|
||||
pxNewListItem->pxContainer = pxList;
|
||||
|
||||
( pxList->uxNumberOfItems )++;
|
||||
|
||||
traceRETURN_vListInsertEnd();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vListInsert( List_t * const pxList,
|
||||
ListItem_t * const pxNewListItem )
|
||||
{
|
||||
ListItem_t * pxIterator;
|
||||
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
|
||||
|
||||
traceENTER_vListInsert( pxList, pxNewListItem );
|
||||
|
||||
/* Only effective when configASSERT() is also defined, these tests may catch
|
||||
* the list data structures being overwritten in memory. They will not catch
|
||||
* data errors caused by incorrect configuration or use of FreeRTOS. */
|
||||
listTEST_LIST_INTEGRITY( pxList );
|
||||
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
|
||||
|
||||
/* 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 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
|
||||
* first, and the algorithm slightly modified if necessary. */
|
||||
if( xValueOfInsertion == portMAX_DELAY )
|
||||
{
|
||||
pxIterator = pxList->xListEnd.pxPrevious;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* *** NOTE ***********************************************************
|
||||
* If you find your application is crashing here then likely causes are
|
||||
* listed below. In addition see https://www.FreeRTOS.org/FAQHelp.html for
|
||||
* more tips, and ensure configASSERT() is defined!
|
||||
* https://www.FreeRTOS.org/a00110.html#configASSERT
|
||||
*
|
||||
* 1) Stack overflow -
|
||||
* 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
|
||||
* https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html and the definition
|
||||
* of configMAX_SYSCALL_INTERRUPT_PRIORITY on
|
||||
* 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.
|
||||
* 4) Using a queue or semaphore before it has been initialised or
|
||||
* before the scheduler has been started (are interrupts firing
|
||||
* before vTaskStartScheduler() has been called?).
|
||||
* 5) If the FreeRTOS port supports interrupt nesting then ensure that
|
||||
* the priority of the tick interrupt is at or below
|
||||
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
**********************************************************************/
|
||||
|
||||
for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext )
|
||||
{
|
||||
/* There is nothing to do here, just iterating to the wanted
|
||||
* insertion position. */
|
||||
}
|
||||
}
|
||||
|
||||
pxNewListItem->pxNext = pxIterator->pxNext;
|
||||
pxNewListItem->pxNext->pxPrevious = pxNewListItem;
|
||||
pxNewListItem->pxPrevious = pxIterator;
|
||||
pxIterator->pxNext = pxNewListItem;
|
||||
|
||||
/* Remember which list the item is in. This allows fast removal of the
|
||||
* item later. */
|
||||
pxNewListItem->pxContainer = pxList;
|
||||
|
||||
( pxList->uxNumberOfItems )++;
|
||||
|
||||
traceRETURN_vListInsert();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
|
||||
{
|
||||
/* The list item knows which list it is in. Obtain the list from the list
|
||||
* item. */
|
||||
List_t * const pxList = pxItemToRemove->pxContainer;
|
||||
|
||||
traceENTER_uxListRemove( pxItemToRemove );
|
||||
|
||||
|
||||
|
||||
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 )
|
||||
{
|
||||
pxList->pxIndex = pxItemToRemove->pxPrevious;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
pxItemToRemove->pxContainer = NULL;
|
||||
( pxList->uxNumberOfItems )--;
|
||||
|
||||
traceRETURN_uxListRemove( pxList->uxNumberOfItems );
|
||||
|
||||
return pxList->uxNumberOfItems;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
2522
pico-sensor/McuLib/FreeRTOS/Source/portable/Common/mpu_wrappers.c
Normal file
2522
pico-sensor/McuLib/FreeRTOS/Source/portable/Common/mpu_wrappers.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,899 @@
|
||||
/*
|
||||
* 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!
|
||||
*/
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||
* all the API functions to use the MPU wrappers. That should only be done when
|
||||
* task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* MPU wrappers includes. */
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
/* Portasm includes. */
|
||||
#include "portasm.h"
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/* Secure components includes. */
|
||||
#include "secure_context.h"
|
||||
#include "secure_init.h"
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/**
|
||||
* The FreeRTOS Cortex M33 port can be configured to run on the Secure Side only
|
||||
* i.e. the processor boots as secure and never jumps to the non-secure side.
|
||||
* The Trust Zone support in the port must be disabled in order to run FreeRTOS
|
||||
* on the secure side. The following are the valid configuration seetings:
|
||||
*
|
||||
* 1. Run FreeRTOS on the Secure Side:
|
||||
* configRUN_FREERTOS_SECURE_ONLY = 1 and configENABLE_TRUSTZONE = 0
|
||||
*
|
||||
* 2. Run FreeRTOS on the Non-Secure Side with Secure Side function call support:
|
||||
* configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 1
|
||||
*
|
||||
* 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support:
|
||||
* configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0
|
||||
*/
|
||||
#if( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) )
|
||||
#error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the NVIC.
|
||||
*/
|
||||
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 )
|
||||
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 )
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE ( ( volatile uint32_t * ) 0xe000e018 )
|
||||
#define portNVIC_INT_CTRL ( ( volatile uint32_t * ) 0xe000ed04 )
|
||||
#define portNVIC_SYSPRI2 ( ( volatile uint32_t * ) 0xe000ed20 )
|
||||
#define portNVIC_SYSTICK_CLK ( 0x00000004 )
|
||||
#define portNVIC_SYSTICK_INT ( 0x00000002 )
|
||||
#define portNVIC_SYSTICK_ENABLE ( 0x00000001 )
|
||||
#define portNVIC_PENDSVSET ( 0x10000000 )
|
||||
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||
#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
|
||||
#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the SCB.
|
||||
*/
|
||||
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 )
|
||||
#define portSCB_MEM_FAULT_ENABLE ( 1UL << 16UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the FPU.
|
||||
*/
|
||||
#define portCPACR ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
|
||||
#define portCPACR_CP10_VALUE ( 3UL )
|
||||
#define portCPACR_CP11_VALUE portCPACR_CP10_VALUE
|
||||
#define portCPACR_CP10_POS ( 20UL )
|
||||
#define portCPACR_CP11_POS ( 22UL )
|
||||
|
||||
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
|
||||
#define portFPCCR_ASPEN_POS ( 31UL )
|
||||
#define portFPCCR_ASPEN_MASK ( 1UL << portFPCCR_ASPEN_POS )
|
||||
#define portFPCCR_LSPEN_POS ( 30UL )
|
||||
#define portFPCCR_LSPEN_MASK ( 1UL << portFPCCR_LSPEN_POS )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the MPU.
|
||||
*/
|
||||
#define portMPU_TYPE_REG ( * ( ( volatile uint32_t * ) 0xe000ed90 ) )
|
||||
#define portMPU_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed94 ) )
|
||||
#define portMPU_RNR_REG ( * ( ( volatile uint32_t * ) 0xe000ed98 ) )
|
||||
|
||||
#define portMPU_RBAR_REG ( * ( ( volatile uint32_t * ) 0xe000ed9c ) )
|
||||
#define portMPU_RLAR_REG ( * ( ( volatile uint32_t * ) 0xe000eda0 ) )
|
||||
|
||||
#define portMPU_RBAR_A1_REG ( * ( ( volatile uint32_t * ) 0xe000eda4 ) )
|
||||
#define portMPU_RLAR_A1_REG ( * ( ( volatile uint32_t * ) 0xe000eda8 ) )
|
||||
|
||||
#define portMPU_RBAR_A2_REG ( * ( ( volatile uint32_t * ) 0xe000edac ) )
|
||||
#define portMPU_RLAR_A2_REG ( * ( ( volatile uint32_t * ) 0xe000edb0 ) )
|
||||
|
||||
#define portMPU_RBAR_A3_REG ( * ( ( volatile uint32_t * ) 0xe000edb4 ) )
|
||||
#define portMPU_RLAR_A3_REG ( * ( ( volatile uint32_t * ) 0xe000edb8 ) )
|
||||
|
||||
#define portMPU_MAIR0_REG ( * ( ( volatile uint32_t * ) 0xe000edc0 ) )
|
||||
#define portMPU_MAIR1_REG ( * ( ( volatile uint32_t * ) 0xe000edc4 ) )
|
||||
|
||||
#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
|
||||
#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
|
||||
|
||||
#define portMPU_MAIR_ATTR0_POS ( 0UL )
|
||||
#define portMPU_MAIR_ATTR0_MASK ( 0x000000ff )
|
||||
|
||||
#define portMPU_MAIR_ATTR1_POS ( 8UL )
|
||||
#define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 )
|
||||
|
||||
#define portMPU_MAIR_ATTR2_POS ( 16UL )
|
||||
#define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 )
|
||||
|
||||
#define portMPU_MAIR_ATTR3_POS ( 24UL )
|
||||
#define portMPU_MAIR_ATTR3_MASK ( 0xff000000 )
|
||||
|
||||
#define portMPU_MAIR_ATTR4_POS ( 0UL )
|
||||
#define portMPU_MAIR_ATTR4_MASK ( 0x000000ff )
|
||||
|
||||
#define portMPU_MAIR_ATTR5_POS ( 8UL )
|
||||
#define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 )
|
||||
|
||||
#define portMPU_MAIR_ATTR6_POS ( 16UL )
|
||||
#define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 )
|
||||
|
||||
#define portMPU_MAIR_ATTR7_POS ( 24UL )
|
||||
#define portMPU_MAIR_ATTR7_MASK ( 0xff000000 )
|
||||
|
||||
#define portMPU_RLAR_ATTR_INDEX0 ( 0UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX1 ( 1UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX2 ( 2UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX3 ( 3UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX4 ( 4UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX5 ( 5UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX6 ( 6UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX7 ( 7UL << 1UL )
|
||||
|
||||
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
||||
|
||||
/* Enable privileged access to unmapped region. */
|
||||
#define portMPU_PRIV_BACKGROUND_ENABLE ( 1UL << 2UL )
|
||||
|
||||
/* Enable MPU. */
|
||||
#define portMPU_ENABLE ( 1UL << 0UL )
|
||||
|
||||
/* Expected value of the portMPU_TYPE register. */
|
||||
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to set up the initial stack.
|
||||
*/
|
||||
#define portINITIAL_XPSR ( 0x01000000 )
|
||||
|
||||
#if( configRUN_FREERTOS_SECURE_ONLY == 1 )
|
||||
/**
|
||||
* @brief Initial EXC_RETURN value.
|
||||
*
|
||||
* FF FF FF FD
|
||||
* 1111 1111 1111 1111 1111 1111 1111 1101
|
||||
*
|
||||
* Bit[6] - 1 --> The exception was taken from the Secure state.
|
||||
* Bit[5] - 1 --> Do not skip stacking of additional state context.
|
||||
* Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
|
||||
* Bit[3] - 1 --> Return to the Thread mode.
|
||||
* Bit[2] - 1 --> Restore registers from the process stack.
|
||||
* Bit[1] - 0 --> Reserved, 0.
|
||||
* Bit[0] - 1 --> The exception was taken to the Secure state.
|
||||
*/
|
||||
#define portINITIAL_EXC_RETURN ( 0xfffffffd )
|
||||
#else
|
||||
/**
|
||||
* @brief Initial EXC_RETURN value.
|
||||
*
|
||||
* FF FF FF BC
|
||||
* 1111 1111 1111 1111 1111 1111 1011 1100
|
||||
*
|
||||
* Bit[6] - 0 --> The exception was taken from the Non-Secure state.
|
||||
* Bit[5] - 1 --> Do not skip stacking of additional state context.
|
||||
* Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
|
||||
* Bit[3] - 1 --> Return to the Thread mode.
|
||||
* Bit[2] - 1 --> Restore registers from the process stack.
|
||||
* Bit[1] - 0 --> Reserved, 0.
|
||||
* Bit[0] - 0 --> The exception was taken to the Non-Secure state.
|
||||
*/
|
||||
#define portINITIAL_EXC_RETURN ( 0xffffffbc )
|
||||
#endif /* configRUN_FREERTOS_SECURE_ONLY */
|
||||
|
||||
/**
|
||||
* @brief CONTROL register privileged bit mask.
|
||||
*
|
||||
* Bit[0] in CONTROL register tells the privilege:
|
||||
* Bit[0] = 0 ==> The task is privileged.
|
||||
* Bit[0] = 1 ==> The task is not privileged.
|
||||
*/
|
||||
#define portCONTROL_PRIVILEGED_MASK ( 1UL << 0UL )
|
||||
|
||||
/**
|
||||
* @brief Initial CONTROL register values.
|
||||
*/
|
||||
#define portINITIAL_CONTROL_UNPRIVILEGED ( 0x3 )
|
||||
#define portINITIAL_CONTROL_PRIVILEGED ( 0x2 )
|
||||
|
||||
/**
|
||||
* @brief Let the user override the pre-loading of the initial LR with the
|
||||
* address of prvTaskExitError() in case it messes up unwinding of the stack
|
||||
* in the debugger.
|
||||
*/
|
||||
#ifdef configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#else
|
||||
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief If portPRELOAD_REGISTERS then registers will be given an initial value
|
||||
* when a task is created. This helps in debugging at the cost of code size.
|
||||
*/
|
||||
#define portPRELOAD_REGISTERS 1
|
||||
|
||||
/**
|
||||
* @brief A task is created without a secure context, and must call
|
||||
* portALLOCATE_SECURE_CONTEXT() to give itself a secure context before it makes
|
||||
* any secure calls.
|
||||
*/
|
||||
#define portNO_SECURE_CONTEXT 0
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Setup the timer to generate the tick interrupts.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Used to catch tasks that attempt to return from their implementing
|
||||
* function.
|
||||
*/
|
||||
static void prvTaskExitError( void );
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
/**
|
||||
* @brief Setup the Memory Protection Unit (MPU).
|
||||
*/
|
||||
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if( configENABLE_FPU == 1 )
|
||||
/**
|
||||
* @brief Setup the Floating Point Unit (FPU).
|
||||
*/
|
||||
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
/**
|
||||
* @brief Yield the processor.
|
||||
*/
|
||||
void vPortYield( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enter critical section.
|
||||
*/
|
||||
void vPortEnterCritical( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Exit from critical section.
|
||||
*/
|
||||
void vPortExitCritical( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SysTick handler.
|
||||
*/
|
||||
void SysTick_Handler( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief C part of SVC handler.
|
||||
*/
|
||||
portDONT_DISCARD void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) PRIVILEGED_FUNCTION;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Each task maintains its own interrupt status in the critical nesting
|
||||
* variable.
|
||||
*/
|
||||
static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/**
|
||||
* @brief Saved as part of the task context to indicate which context the
|
||||
* task is using on the secure side.
|
||||
*/
|
||||
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Stop and reset the SysTick. */
|
||||
*( portNVIC_SYSTICK_CTRL ) = 0UL;
|
||||
*( portNVIC_SYSTICK_CURRENT_VALUE ) = 0UL;
|
||||
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
*( portNVIC_SYSTICK_LOAD ) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
*( portNVIC_SYSTICK_CTRL ) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvTaskExitError( void )
|
||||
{
|
||||
volatile uint32_t ulDummy = 0UL;
|
||||
|
||||
/* A function that implements a task must not exit or attempt to return to
|
||||
* its caller as there is nothing to return to. If a task wants to exit it
|
||||
* should instead call vTaskDelete( NULL ). Artificially force an assert()
|
||||
* to be triggered if configASSERT() is defined, then stop here so
|
||||
* application writers can catch the error. */
|
||||
configASSERT( ulCriticalNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
while( ulDummy == 0 )
|
||||
{
|
||||
/* This file calls prvTaskExitError() after the scheduler has been
|
||||
* started to remove a compiler warning about the function being
|
||||
* defined but never called. ulDummy is used purely to quieten other
|
||||
* warnings about code appearing after this function is called - making
|
||||
* ulDummy volatile makes the compiler think the function could return
|
||||
* and therefore not output an 'unreachable code' warning for code that
|
||||
* appears after it. */
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
#if defined( __ARMCC_VERSION )
|
||||
/* Declaration when these variable are defined in code instead of being
|
||||
* exported from linker scripts. */
|
||||
extern uint32_t * __privileged_functions_start__;
|
||||
extern uint32_t * __privileged_functions_end__;
|
||||
extern uint32_t * __syscalls_flash_start__;
|
||||
extern uint32_t * __syscalls_flash_end__;
|
||||
extern uint32_t * __unprivileged_flash_start__;
|
||||
extern uint32_t * __unprivileged_flash_end__;
|
||||
extern uint32_t * __privileged_sram_start__;
|
||||
extern uint32_t * __privileged_sram_end__;
|
||||
#else
|
||||
/* Declaration when these variable are exported from linker scripts. */
|
||||
extern uint32_t __privileged_functions_start__[];
|
||||
extern uint32_t __privileged_functions_end__[];
|
||||
extern uint32_t __syscalls_flash_start__[];
|
||||
extern uint32_t __syscalls_flash_end__[];
|
||||
extern uint32_t __unprivileged_flash_start__[];
|
||||
extern uint32_t __unprivileged_flash_end__[];
|
||||
extern uint32_t __privileged_sram_start__[];
|
||||
extern uint32_t __privileged_sram_end__[];
|
||||
#endif /* defined( __ARMCC_VERSION ) */
|
||||
|
||||
/* Check that the MPU is present. */
|
||||
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
|
||||
{
|
||||
/* MAIR0 - Index 0. */
|
||||
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
|
||||
/* MAIR0 - Index 1. */
|
||||
portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
|
||||
|
||||
/* Setup privileged flash as Read Only so that privileged tasks can
|
||||
* read it but not modify. */
|
||||
portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_PRIVILEGED_READ_ONLY );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Setup unprivileged flash as Read Only by both privileged and
|
||||
* unprivileged tasks. All tasks can read it but no-one can modify. */
|
||||
portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_READ_ONLY );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Setup unprivileged syscalls flash as Read Only by both privileged
|
||||
* and unprivileged tasks. All tasks can read it but no-one can modify. */
|
||||
portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_READ_ONLY );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Setup RAM containing kernel data for privileged access only. */
|
||||
portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
|
||||
( portMPU_REGION_EXECUTE_NEVER );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Enable mem fault. */
|
||||
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE;
|
||||
|
||||
/* Enable MPU with privileged background access i.e. unmapped
|
||||
* regions have privileged access. */
|
||||
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE | portMPU_ENABLE );
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_FPU == 1 )
|
||||
static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
/* Enable non-secure access to the FPU. */
|
||||
SecureInit_EnableNSFPUAccess();
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
/* CP10 = 11 ==> Full access to FPU i.e. both privileged and
|
||||
* unprivileged code should be able to access FPU. CP11 should be
|
||||
* programmed to the same value as CP10. */
|
||||
*( portCPACR ) |= ( ( portCPACR_CP10_VALUE << portCPACR_CP10_POS ) |
|
||||
( portCPACR_CP11_VALUE << portCPACR_CP11_POS )
|
||||
);
|
||||
|
||||
/* ASPEN = 1 ==> Hardware should automatically preserve floating point
|
||||
* context on exception entry and restore on exception return.
|
||||
* LSPEN = 1 ==> Enable lazy context save of FP state. */
|
||||
*( portFPCCR ) |= ( portFPCCR_ASPEN_MASK | portFPCCR_LSPEN_MASK );
|
||||
}
|
||||
#endif /* configENABLE_FPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Set a PendSV to request a context switch. */
|
||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
||||
|
||||
/* Barriers are normally not required but do ensure the code is
|
||||
* completely within the specified behaviour for the architecture. */
|
||||
__asm volatile( "dsb" ::: "memory" );
|
||||
__asm volatile( "isb" );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
ulCriticalNesting++;
|
||||
|
||||
/* Barriers are normally not required but do ensure the code is
|
||||
* completely within the specified behaviour for the architecture. */
|
||||
__asm volatile( "dsb" ::: "memory" );
|
||||
__asm volatile( "isb" );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
configASSERT( ulCriticalNesting );
|
||||
ulCriticalNesting--;
|
||||
|
||||
if( ulCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
uint32_t ulPreviousMask;
|
||||
|
||||
ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Pend a context switch. */
|
||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
||||
}
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */
|
||||
{
|
||||
#if( configENABLE_MPU == 1 )
|
||||
#if defined( __ARMCC_VERSION )
|
||||
/* Declaration when these variable are defined in code instead of being
|
||||
* exported from linker scripts. */
|
||||
extern uint32_t * __syscalls_flash_start__;
|
||||
extern uint32_t * __syscalls_flash_end__;
|
||||
#else
|
||||
/* Declaration when these variable are exported from linker scripts. */
|
||||
extern uint32_t __syscalls_flash_start__[];
|
||||
extern uint32_t __syscalls_flash_end__[];
|
||||
#endif /* defined( __ARMCC_VERSION ) */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
uint32_t ulPC;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
uint32_t ulR0;
|
||||
#if( configENABLE_MPU == 1 )
|
||||
uint32_t ulControl, ulIsTaskPrivileged;
|
||||
#endif /* configENABLE_MPU */
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
uint8_t ucSVCNumber;
|
||||
|
||||
/* Register are stored on the stack in the following order - R0, R1, R2, R3,
|
||||
* R12, LR, PC, xPSR. */
|
||||
ulPC = pulCallerStackAddress[ 6 ];
|
||||
ucSVCNumber = ( ( uint8_t *) ulPC )[ -2 ];
|
||||
|
||||
switch( ucSVCNumber )
|
||||
{
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
case portSVC_ALLOCATE_SECURE_CONTEXT:
|
||||
{
|
||||
/* R0 contains the stack size passed as parameter to the
|
||||
* vPortAllocateSecureContext function. */
|
||||
ulR0 = pulCallerStackAddress[ 0 ];
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Read the CONTROL register value. */
|
||||
__asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
|
||||
|
||||
/* The task that raised the SVC is privileged if Bit[0]
|
||||
* in the CONTROL register is 0. */
|
||||
ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
|
||||
|
||||
/* Allocate and load a context for the secure task. */
|
||||
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* Allocate and load a context for the secure task. */
|
||||
xSecureContext = SecureContext_AllocateContext( ulR0 );
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
configASSERT( xSecureContext != NULL );
|
||||
SecureContext_LoadContext( xSecureContext );
|
||||
}
|
||||
break;
|
||||
|
||||
case portSVC_FREE_SECURE_CONTEXT:
|
||||
{
|
||||
/* R0 contains the secure context handle to be freed. */
|
||||
ulR0 = pulCallerStackAddress[ 0 ];
|
||||
|
||||
/* Free the secure context. */
|
||||
SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 );
|
||||
}
|
||||
break;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
case portSVC_START_SCHEDULER:
|
||||
{
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
/* De-prioritize the non-secure exceptions so that the
|
||||
* non-secure pendSV runs at the lowest priority. */
|
||||
SecureInit_DePrioritizeNSExceptions();
|
||||
|
||||
/* Initialize the secure context management system. */
|
||||
SecureContext_Init();
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#if( configENABLE_FPU == 1 )
|
||||
{
|
||||
/* Setup the Floating Point Unit (FPU). */
|
||||
prvSetupFPU();
|
||||
}
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
/* Setup the context of the first task so that the first task starts
|
||||
* executing. */
|
||||
vRestoreContextOfFirstTask();
|
||||
}
|
||||
break;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
case portSVC_RAISE_PRIVILEGE:
|
||||
{
|
||||
/* Only raise the privilege, if the svc was raised from any of
|
||||
* the system calls. */
|
||||
if( ulPC >= ( uint32_t ) __syscalls_flash_start__ &&
|
||||
ulPC <= ( uint32_t ) __syscalls_flash_end__ )
|
||||
{
|
||||
vRaisePrivilege();
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
default:
|
||||
{
|
||||
/* Incorrect SVC call. */
|
||||
configASSERT( pdFALSE );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 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, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters ) /* PRIVILEGED_FUNCTION */
|
||||
#endif /* configENABLE_MPU */
|
||||
{
|
||||
/* Simulate the stack frame as it would be created by a context switch
|
||||
* interrupt. */
|
||||
#if( portPRELOAD_REGISTERS == 0 )
|
||||
{
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
|
||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
|
||||
*pxTopOfStack = portINITIAL_EXC_RETURN;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
if( xRunPrivileged == pdTRUE )
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
else
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
}
|
||||
#else /* portPRELOAD_REGISTERS */
|
||||
{
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
if( xRunPrivileged == pdTRUE )
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
else
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
}
|
||||
#endif /* portPRELOAD_REGISTERS */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
||||
*( portNVIC_SYSPRI2 ) |= portNVIC_PENDSV_PRI;
|
||||
*( portNVIC_SYSPRI2 ) |= portNVIC_SYSTICK_PRI;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Setup the Memory Protection Unit (MPU). */
|
||||
prvSetupMPU();
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
* here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Initialize the critical nesting count ready for the first task. */
|
||||
ulCriticalNesting = 0;
|
||||
|
||||
/* Start the first task. */
|
||||
vStartFirstTask();
|
||||
|
||||
/* Should never get here as the tasks will now be executing. Call the task
|
||||
* exit error function to prevent compiler warnings about a static function
|
||||
* not being called in the case that the application writer overrides this
|
||||
* functionality by defining configTASK_RETURN_ADDRESS. Call
|
||||
* vTaskSwitchContext() so link time optimization does not remove the
|
||||
* symbol. */
|
||||
vTaskSwitchContext();
|
||||
prvTaskExitError();
|
||||
|
||||
/* Should not get here. */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
* Artificially force an assert. */
|
||||
configASSERT( ulCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth )
|
||||
{
|
||||
uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber;
|
||||
int32_t lIndex = 0;
|
||||
|
||||
/* Setup MAIR0. */
|
||||
xMPUSettings->ulMAIR0 = ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
|
||||
xMPUSettings->ulMAIR0 |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
|
||||
|
||||
/* This function is called automatically when the task is created - in
|
||||
* which case the stack region parameters will be valid. At all other
|
||||
* times the stack parameters will not be valid and it is assumed that
|
||||
* the stack region has already been configured. */
|
||||
if( ulStackDepth > 0 )
|
||||
{
|
||||
/* Define the region that allows access to the stack. */
|
||||
ulRegionStartAddress = ( ( uint32_t ) pxBottomOfStack ) & portMPU_RBAR_ADDRESS_MASK;
|
||||
ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1;
|
||||
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
|
||||
|
||||
xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_READ_WRITE ) |
|
||||
( portMPU_REGION_EXECUTE_NEVER );
|
||||
|
||||
xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
}
|
||||
|
||||
/* User supplied configurable regions. */
|
||||
for( ulRegionNumber = 1; ulRegionNumber <= portNUM_CONFIGURABLE_REGIONS; ulRegionNumber++ )
|
||||
{
|
||||
/* If xRegions is NULL i.e. the task has not specified any MPU
|
||||
* region, the else part ensures that all the configurable MPU
|
||||
* regions are invalidated. */
|
||||
if( ( xRegions != NULL ) && ( xRegions[ lIndex ].ulLengthInBytes > 0UL ) )
|
||||
{
|
||||
/* Translate the generic region definition contained in xRegions
|
||||
* into the ARMv8 specific MPU settings that are then stored in
|
||||
* xMPUSettings. */
|
||||
ulRegionStartAddress = ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) & portMPU_RBAR_ADDRESS_MASK;
|
||||
ulRegionEndAddress = ( uint32_t ) xRegions[ lIndex ].pvBaseAddress + xRegions[ lIndex ].ulLengthInBytes - 1;
|
||||
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
|
||||
|
||||
/* Start address. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) |
|
||||
( portMPU_REGION_NON_SHAREABLE );
|
||||
|
||||
/* RO/RW. */
|
||||
if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_READ_ONLY ) != 0 )
|
||||
{
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_ONLY );
|
||||
}
|
||||
else
|
||||
{
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_WRITE );
|
||||
}
|
||||
|
||||
/* XN. */
|
||||
if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 )
|
||||
{
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER );
|
||||
}
|
||||
|
||||
/* End Address. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Normal memory/ Device memory. */
|
||||
if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_DEVICE_MEMORY ) != 0 )
|
||||
{
|
||||
/* Attr1 in MAIR0 is configured as device memory. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Attr1 in MAIR0 is configured as normal memory. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalidate the region. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = 0UL;
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = 0UL;
|
||||
}
|
||||
|
||||
lIndex++;
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* portTicks.c
|
||||
*
|
||||
* Created on: 24.04.2019
|
||||
* Author: Erich Styger
|
||||
*/
|
||||
|
||||
#include "FreeRTOSConfig.h"
|
||||
#include "portTicks.h"
|
||||
|
||||
/* --------------------------------------------------- */
|
||||
/* macros dealing with tick counter */
|
||||
#if configSYSTICK_USE_LOW_POWER_TIMER
|
||||
#if !McuLib_CONFIG_PEX_SDK_USED
|
||||
/*! \todo */
|
||||
#define LPTMR0_BASE_PTR LPTMR0 /* low power timer address base */
|
||||
#define configLOW_POWER_TIMER_VECTOR_NUMBER LPTMR0_IRQn /* low power timer IRQ number */
|
||||
#define ENABLE_TICK_COUNTER() LPTMR_StartTimer(LPTMR0_BASE_PTR); LPTMR_EnableInterrupts(LPTMR0_BASE_PTR, kLPTMR_TimerInterruptEnable)
|
||||
#define DISABLE_TICK_COUNTER() LPTMR_StopTimer(LPTMR0_BASE_PTR)
|
||||
#define RESET_TICK_COUNTER_VAL() LPTMR_StopTimer(LPTMR0_BASE_PTR); LPTMR_DisableInterrupts(LPTMR0_BASE_PTR, kLPTMR_TimerInterruptEnable)
|
||||
#define ACKNOWLEDGE_TICK_ISR() LPTMR_ClearStatusFlags(LPTMR0_BASE_PTR, kLPTMR_TimerCompareFlag);
|
||||
#elif McuLib_CONFIG_SDK_VERSION_USED == McuLib_CONFIG_SDK_PROCESSOR_EXPERT
|
||||
#define ENABLE_TICK_COUNTER() LPTMR_PDD_EnableDevice(LPTMR0_BASE_PTR, PDD_ENABLE); LPTMR_PDD_EnableInterrupt(LPTMR0_BASE_PTR)
|
||||
#define DISABLE_TICK_COUNTER() LPTMR_PDD_EnableDevice(LPTMR0_BASE_PTR, PDD_DISABLE); LPTMR_PDD_DisableInterrupt(LPTMR0_BASE_PTR)
|
||||
#define RESET_TICK_COUNTER_VAL() DISABLE_TICK_COUNTER() /* CNR is reset when the LPTMR is disabled or counter register overflows */
|
||||
#define ACKNOWLEDGE_TICK_ISR() LPTMR_PDD_ClearInterruptFlag(LPTMR0_BASE_PTR)
|
||||
#if defined(LDD_ivIndex_INT_LPTimer) /* Earlier version of Processor Expert use this vector name */
|
||||
#define configLOW_POWER_TIMER_VECTOR_NUMBER LDD_ivIndex_INT_LPTimer
|
||||
#elif defined(LDD_ivIndex_INT_LPTMR0) /* Newer versions (Processor Expert for Kinetis v3.0.1 uses this name */
|
||||
#define configLOW_POWER_TIMER_VECTOR_NUMBER LDD_ivIndex_INT_LPTMR0
|
||||
#else
|
||||
#error "Unknown Low Power Timer Interrupt Number?"
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#define ENABLE_TICK_COUNTER() portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT
|
||||
#define DISABLE_TICK_COUNTER() portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT
|
||||
#define RESET_TICK_COUNTER_VAL() portNVIC_SYSTICK_CURRENT_VALUE_REG = 0 /*portNVIC_SYSTICK_LOAD_REG*/
|
||||
#define ACKNOWLEDGE_TICK_ISR() /* not needed */
|
||||
#endif
|
||||
|
||||
typedef unsigned long TickCounter_t; /* enough for 24 bit Systick */
|
||||
#if configSYSTICK_USE_LOW_POWER_TIMER
|
||||
#define TICK_NOF_BITS 16
|
||||
#define COUNTS_UP 1 /* LPTMR is counting up */
|
||||
#if !McuLib_CONFIG_PEX_SDK_USED
|
||||
#define SET_TICK_DURATION(val) LPTMR_SetTimerPeriod(LPTMR0_BASE_PTR, val);
|
||||
#define GET_TICK_DURATION() LPTMR0_BASE_PTR->CNR /*! \todo SDK has no access method for this */
|
||||
#define GET_TICK_CURRENT_VAL(addr) *(addr)=LPTMR_GetCurrentTimerCount(LPTMR0_BASE_PTR)
|
||||
#else
|
||||
#define SET_TICK_DURATION(val) LPTMR_PDD_WriteCompareReg(LPTMR0_BASE_PTR, val)
|
||||
#define GET_TICK_DURATION() LPTMR_PDD_ReadCompareReg(LPTMR0_BASE_PTR)
|
||||
#define GET_TICK_CURRENT_VAL(addr) *(addr)=LPTMR_PDD_ReadCounterReg(LPTMR0_BASE_PTR)
|
||||
#endif
|
||||
#else
|
||||
#define TICK_NOF_BITS 24
|
||||
#define COUNTS_UP 0 /* SysTick is counting down to zero */
|
||||
#define SET_TICK_DURATION(val) portNVIC_SYSTICK_LOAD_REG = val
|
||||
#define GET_TICK_DURATION() portNVIC_SYSTICK_LOAD_REG
|
||||
#define GET_TICK_CURRENT_VAL(addr) *(addr)=portNVIC_SYSTICK_CURRENT_VALUE_REG
|
||||
#endif
|
||||
|
||||
#if configSYSTICK_USE_LOW_POWER_TIMER
|
||||
#define TIMER_COUNTS_FOR_ONE_TICK (configSYSTICK_LOW_POWER_TIMER_CLOCK_HZ/configTICK_RATE_HZ)
|
||||
#else
|
||||
#define TIMER_COUNTS_FOR_ONE_TICK (configSYSTICK_CLOCK_HZ/configTICK_RATE_HZ)
|
||||
#endif
|
||||
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configCPU_FAMILY==configCPU_FAMILY_ARM_M0P
|
||||
unsigned int SEGGER_SYSVIEW_TickCnt; /* tick counter for Segger SystemViewer */
|
||||
#endif
|
||||
|
||||
#if configUSE_TICKLESS_IDLE
|
||||
#define UL_TIMER_COUNTS_FOR_ONE_TICK ((TickCounter_t)(TIMER_COUNTS_FOR_ONE_TICK))
|
||||
#if configCPU_FAMILY_IS_ARM(configCPU_FAMILY)
|
||||
#define TICKLESS_DISABLE_INTERRUPTS() __asm volatile("cpsid i") /* disable interrupts. Note that the wfi (wait for interrupt) instruction later will still be able to wait for interrupts! */
|
||||
#define TICKLESS_ENABLE_INTERRUPTS() __asm volatile("cpsie i") /* re-enable interrupts. */
|
||||
#elif (configCPU_FAMILY==configCPU_FAMILY_S08) || (configCPU_FAMILY==configCPU_FAMILY_S12)
|
||||
#define TICKLESS_DISABLE_INTERRUPTS() __asm("sei"); /* disable interrupts */
|
||||
#define TICKLESS_ENABLE_INTERRUPTS() __asm("cli"); /* re-enable interrupts */
|
||||
#else
|
||||
#define TICKLESS_DISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() /* this disables interrupts! Make sure they are re-enabled in vOnPreSleepProcessing()! */
|
||||
#define TICKLESS_ENABLE_INTERRUPTS() portENABLE_INTERRUPTS() /* re-enable interrupts */
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#if configSYSTICK_USE_LOW_POWER_TIMER
|
||||
/* using Low Power Timer */
|
||||
#if CONFIG_PEX_SDK_USEDMcuLib_CONFIG_PEX_SDK_USED
|
||||
#define LPTMR_CSR_TCF_MASK 0x80u
|
||||
#define TICK_INTERRUPT_HAS_FIRED() (LPTMR0_BASE_PTR->CSR&LPTMR_CSR_TCF_MASK)!=0/*! \todo */ /* returns TRUE if tick interrupt had fired */
|
||||
#else
|
||||
#define TICK_INTERRUPT_HAS_FIRED() (LPTMR_PDD_GetInterruptFlag(LPTMR0_BASE_PTR)!=0) /* returns TRUE if tick interrupt had fired */
|
||||
#endif
|
||||
#define TICK_INTERRUPT_FLAG_RESET() /* not needed */
|
||||
#define TICK_INTERRUPT_FLAG_SET() /* not needed */
|
||||
#else
|
||||
/* using directly SysTick Timer */
|
||||
#define TICK_INTERRUPT_HAS_FIRED() ((portNVIC_SYSTICK_CTRL_REG&portNVIC_SYSTICK_COUNT_FLAG_BIT)!=0) /* returns TRUE if tick interrupt had fired */
|
||||
#define TICK_INTERRUPT_FLAG_RESET() /* not needed */
|
||||
#define TICK_INTERRUPT_FLAG_SET() /* not needed */
|
||||
#endif
|
||||
#else
|
||||
/* using global variable to find out if interrupt has fired */
|
||||
volatile uint8_t portTickCntr; /* used to find out if we woke up by the tick interrupt */
|
||||
#define TICK_INTERRUPT_HAS_FIRED() (portTickCntr!=0) /* returns TRUE if tick interrupt had fired */
|
||||
#define TICK_INTERRUPT_FLAG_RESET() portTickCntr=0
|
||||
#define TICK_INTERRUPT_FLAG_SET() portTickCntr=1
|
||||
#endif
|
||||
#endif /* configUSE_TICKLESS_IDLE == 1 */
|
||||
|
||||
/*
|
||||
* The maximum number of tick periods that can be suppressed is limited by the
|
||||
* resolution of the tick timer.
|
||||
*/
|
||||
#if configUSE_TICKLESS_IDLE == 1
|
||||
static TickCounter_t xMaximumPossibleSuppressedTicks = 0;
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/*
|
||||
* Compensate for the CPU cycles that pass while the tick timer is stopped (low
|
||||
* power functionality only).
|
||||
*/
|
||||
#if configUSE_TICKLESS_IDLE == 1
|
||||
static TickCounter_t ulStoppedTimerCompensation = 0; /* number of timer ticks to compensate */
|
||||
#ifndef configSTOPPED_TIMER_COMPENSATION
|
||||
#define configSTOPPED_TIMER_COMPENSATION 45UL /* number of CPU cycles to compensate. ulStoppedTimerCompensation will contain the number of timer ticks. */
|
||||
#endif
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/* Flag indicating that the tick counter interval needs to be restored back to
|
||||
* the normal setting. Used when woken up from a low power mode using the LPTMR.
|
||||
*/
|
||||
#if configUSE_TICKLESS_IDLE && configSYSTICK_USE_LOW_POWER_TIMER
|
||||
static uint8_t restoreTickInterval = 0; /* used to flag in tick ISR that compare register needs to be reloaded */
|
||||
#endif
|
||||
|
||||
#if (configCPU_FAMILY==configCPU_FAMILY_CF1) || (configCPU_FAMILY==configCPU_FAMILY_CF2)
|
||||
#define portINITIAL_FORMAT_VECTOR ((portSTACK_TYPE)0x4000)
|
||||
#define portINITIAL_STATUS_REGISTER ((portSTACK_TYPE)0x2000) /* Supervisor mode set. */
|
||||
#endif
|
||||
|
||||
#if configCPU_FAMILY_IS_ARM(configCPU_FAMILY)
|
||||
|
||||
/* For strict compliance with the Cortex-M spec the task start address should
|
||||
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
|
||||
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
||||
|
||||
/* Constants required to manipulate the core.
|
||||
* SysTick register: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0662b/CIAGECDD.html
|
||||
* Registers first...
|
||||
*/
|
||||
#define portNVIC_SYSTICK_CTRL_REG (*((volatile unsigned long *)0xe000e010)) /* SYST_CSR, SysTick Control and Status Register */
|
||||
#define portNVIC_SYSTICK_LOAD_REG (*((volatile unsigned long *)0xe000e014)) /* SYST_RVR, SysTick reload value register */
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE_REG (*((volatile unsigned long *)0xe000e018)) /* SYST_CVR, SysTick current value register */
|
||||
#define portNVIC_SYSTICK_CALIB_VALUE_REG (*((volatile unsigned long *)0xe000e01C)) /* SYST_CALIB, SysTick calibration value register */
|
||||
/* ...then bits in the registers. */
|
||||
#define portNVIC_SYSTICK_COUNT_FLAG_BIT (1UL<<16UL) /* returns 1 if timer counted to 0 since the last read of the register */
|
||||
#if configSYSTICK_USE_CORE_CLOCK
|
||||
#define portNVIC_SYSTICK_CLK_BIT (1UL<<2UL) /* clock source. 1: core clock, 0: external reference clock */
|
||||
#else
|
||||
#define portNVIC_SYSTICK_CLK_BIT (0UL<<2UL) /* clock source. 1: core clock, 0: external reference clock */
|
||||
#endif
|
||||
#define portNVIC_SYSTICK_INT_BIT (1UL<<1UL) /* SysTick interrupt enable bit */
|
||||
#define portNVIC_SYSTICK_ENABLE_BIT (1UL<<0UL) /* SysTick enable bit */
|
||||
|
||||
#if 0
|
||||
/* Constants required to manipulate the NVIC: */
|
||||
#define portNVIC_INT_CTRL ((volatile unsigned long*)0xe000ed04) /* interrupt control and state register (ICSR) */
|
||||
#define portNVIC_PENDSVSET_BIT (1UL<<28UL) /* bit 28 in portNVIC_INT_CTRL (PENDSVSET), see http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihfaaha.html */
|
||||
#define portNVIC_PENDSVCLEAR_BIT (1UL<<27UL) /* bit 27 in portNVIC_INT_CTRL (PENDSVCLR) */
|
||||
#define portNVIC_PEND_SYSTICK_SET_BIT (1UL<<26UL) /* bit 26 in portNVIC_INT_CTRL (PENDSTSET) */
|
||||
#define portNVIC_PEND_SYSTICK_CLEAR_BIT (1UL<<25UL) /* bit 25 in portNVIC_INT_CTRL (PENDSTCLR) */
|
||||
|
||||
#define portNVIC_SYSPRI2 ((volatile unsigned long*)0xe000ed1c) /* system handler priority register 2 (SHPR2), used for SVCall priority, http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0662b/CIAGECDD.html */
|
||||
#define portNVIC_SVCALL_PRI (((unsigned long)configKERNEL_INTERRUPT_PRIORITY)<<24) /* priority of SVCall interrupt (in portNVIC_SYSPRI2) */
|
||||
|
||||
#define portNVIC_SYSPRI3 ((volatile unsigned long*)0xe000ed20) /* system handler priority register 3 (SHPR3), used for SysTick and PendSV priority, http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0662b/CIAGECDD.html */
|
||||
#define portNVIC_SYSTICK_PRI (((unsigned long)configKERNEL_INTERRUPT_PRIORITY)<<24) /* priority of SysTick interrupt (in portNVIC_SYSPRI3) */
|
||||
#define portNVIC_PENDSV_PRI (((unsigned long)configKERNEL_INTERRUPT_PRIORITY)<<16) /* priority of PendableService interrupt (in portNVIC_SYSPRI3) */
|
||||
|
||||
#define portNVIC_SYSPRI7 ((volatile unsigned long*)0xe000e41c) /* system handler priority register 7, PRI_28 is LPTMR */
|
||||
#define portNVIC_LP_TIMER_PRI (((unsigned long)configKERNEL_INTERRUPT_PRIORITY)<<0) /* priority of low power timer interrupt */
|
||||
#endif
|
||||
|
||||
#if configSYSTICK_USE_LOW_POWER_TIMER && McuLib_CONFIG_SDK_VERSION_USED == McuLib_CONFIG_SDK_PROCESSOR_EXPERT
|
||||
#define IRQn_Type int
|
||||
#define __NVIC_PRIO_BITS configPRIO_BITS
|
||||
#define __O volatile /*!< Defines 'write only' permissions */
|
||||
#define __IO volatile /*!< Defines 'read / write' permissions */
|
||||
/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
|
||||
*/
|
||||
#if configCPU_FAMILY_IS_ARM_M4_M7(configCPU_FAMILY) || configCPU_FAMILY_IS_ARM_M33(configCPU_FAMILY) /* ARM M4(F)/M7/M33 core */
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
|
||||
uint32_t RESERVED0[24];
|
||||
__IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
|
||||
uint32_t RSERVED1[24];
|
||||
__IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
|
||||
uint32_t RESERVED2[24];
|
||||
__IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
|
||||
uint32_t RESERVED3[24];
|
||||
__IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
|
||||
uint32_t RESERVED4[56];
|
||||
__IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
|
||||
uint32_t RESERVED5[644];
|
||||
__O uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
|
||||
} NVIC_Type;
|
||||
#else /* M0+ */
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t ISER[1]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
|
||||
uint32_t RESERVED0[31];
|
||||
__IO uint32_t ICER[1]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
|
||||
uint32_t RSERVED1[31];
|
||||
__IO uint32_t ISPR[1]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
|
||||
uint32_t RESERVED2[31];
|
||||
__IO uint32_t ICPR[1]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
|
||||
uint32_t RESERVED3[31];
|
||||
uint32_t RESERVED4[64];
|
||||
__IO uint32_t IP[8]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
|
||||
} NVIC_Type;
|
||||
#endif
|
||||
|
||||
/* Memory mapping of Cortex-M0+ Hardware */
|
||||
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
|
||||
#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
|
||||
#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
|
||||
|
||||
/* Interrupt Priorities are WORD accessible only under ARMv6M */
|
||||
/* The following MACROS handle generation of the register offset and byte masks */
|
||||
#define _BIT_SHIFT(IRQn) ( (((uint32_t)(IRQn) ) & 0x03) * 8 )
|
||||
#define _IP_IDX(IRQn) ( ((uint32_t)(IRQn) >> 2) )
|
||||
|
||||
/** \brief Set Interrupt Priority
|
||||
The function sets the priority of an interrupt.
|
||||
\note The priority cannot be set for every core interrupt.
|
||||
\param [in] IRQn Interrupt number.
|
||||
\param [in] priority Priority to set.
|
||||
*/
|
||||
static void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) {
|
||||
IRQn -= 16; /* PEx starts numbers with zero, while system interrupts would be negative */
|
||||
#if configCPU_FAMILY_IS_ARM_M4_M7(configCPU_FAMILY) || configCPU_FAMILY_IS_ARM_M33(configCPU_FAMILY) /* ARM M4(F)/M7/M33 core */
|
||||
NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); /* set Priority for device specific Interrupts */
|
||||
#else /* M0+ */
|
||||
NVIC->IP[_IP_IDX(IRQn)] = (NVIC->IP[_IP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |
|
||||
(((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); /* set Priority for device specific Interrupts */
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \brief Enable External Interrupt
|
||||
The function enables a device-specific interrupt in the NVIC interrupt controller.
|
||||
\param [in] IRQn External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
static void NVIC_EnableIRQ(IRQn_Type IRQn) {
|
||||
IRQn -= 16; /* PEx starts numbers with zero, while system interrupts would be negative */
|
||||
#if configCPU_FAMILY_IS_ARM_M4_M7(configCPU_FAMILY) || configCPU_FAMILY_IS_ARM_M33(configCPU_FAMILY) /* ARM M4(F)/M7/M33 core */
|
||||
NVIC->ISER[(uint32_t)((int32_t)IRQn) >> 5] = (uint32_t)(1 << ((uint32_t)((int32_t)IRQn) & (uint32_t)0x1F)); /* enable interrupt */
|
||||
#else /* M0+ */
|
||||
NVIC->ISER[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */
|
||||
#endif
|
||||
}
|
||||
#endif /* configSYSTICK_USE_LOW_POWER_TIMER */
|
||||
|
||||
#endif /* #if configCPU_FAMILY_IS_ARM(configCPU_FAMILY) */
|
||||
|
||||
void vPortStopTickTimer(void) {
|
||||
DISABLE_TICK_COUNTER();
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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 PORTTICKS_H_
|
||||
#define PORTTICKS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Interface header file to the Processor Expert Tick counter.
|
||||
* This file is used to access the interface, especially for performance
|
||||
* counters (e.g. for Percepio Trace).
|
||||
* That way the a module can interface this wrapper header file instead
|
||||
* of one of the standard FreeRTOS header files.
|
||||
*/
|
||||
#include "McuLib.h" /* include SDK and API used */
|
||||
|
||||
#include "FreeRTOSConfig.h"
|
||||
#include "portmacro.h"
|
||||
|
||||
#if !McuLib_CONFIG_PEX_SDK_USED
|
||||
extern uint32_t SystemCoreClock; /* in Kinetis SDK, this contains the system core clock speed */
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief Return the tick raw counter value. It is assumed that the counter register has been reset at the last tick time
|
||||
* \return Tick counter value. The value is reset at tick interrupt time.
|
||||
* */
|
||||
uint32_t uxGetTickCounterValue(void);
|
||||
|
||||
#if configSYSTICK_USE_LOW_POWER_TIMER
|
||||
#define FREERTOS_HWTC_DOWN_COUNTER 0 /* LPTM is counting up */
|
||||
#define FREERTOS_HWTC_PERIOD ((1000/configSYSTICK_LOW_POWER_TIMER_CLOCK_HZ)-1UL) /* counter is incrementing from zero to this value */
|
||||
#else
|
||||
#define FREERTOS_HWTC_DOWN_COUNTER 1 /* SysTick is counting down */
|
||||
#define FREERTOS_HWTC_PERIOD ((configCPU_CLOCK_HZ/configTICK_RATE_HZ)-1UL) /* counter is decrementing from this value to zero */
|
||||
#endif
|
||||
|
||||
#if configUSE_TICKLESS_IDLE == 1
|
||||
extern volatile uint8_t portTickCntr; /* used to find out if we woke up by the tick interrupt */
|
||||
#endif
|
||||
|
||||
#define FREERTOS_HWTC_FREQ_HZ configTICK_RATE_HZ
|
||||
|
||||
#if configUSE_PERCEPIO_TRACE_HOOKS /* using Percepio Trace */
|
||||
#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_PROCESSOR_EXPERT)
|
||||
/* tick information for Percepio Trace */
|
||||
|
||||
/* undefine previous values, where dummy anyway: make sure this header file is included last! */
|
||||
#undef TRC_HWTC_COUNT_DIRECTION
|
||||
#undef TRC_HWTC_PERIOD
|
||||
#undef TRC_HWTC_DIVISOR
|
||||
#undef TRC_HWTC_COUNT
|
||||
|
||||
#if FREERTOS_HWTC_DOWN_COUNTER
|
||||
#define TRC_HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
|
||||
#define TRC_HWTC_PERIOD FREERTOS_HWTC_PERIOD /* counter is decrementing from this value to zero */
|
||||
#else
|
||||
#define TRC_HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
|
||||
#define TRC_HWTC_PERIOD FREERTOS_HWTC_PERIOD /* counter is incrementing from zero to this value */
|
||||
#endif
|
||||
|
||||
#if configCPU_FAMILY_IS_ARM(configCPU_FAMILY)
|
||||
#if configSYSTICK_USE_LOW_POWER_TIMER
|
||||
#define TRC_HWTC_DIVISOR 1 /* divisor for slow counter tick value */
|
||||
#else
|
||||
#define TRC_HWTC_DIVISOR 2 /* divisor for fast counter tick value */
|
||||
#endif
|
||||
#else
|
||||
#define TRC_HWTC_DIVISOR 1
|
||||
#endif
|
||||
|
||||
#define TRC_HWTC_COUNT (uxGetTickCounterValue())
|
||||
#define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR
|
||||
#define TRC_IRQ_PRIORITY_ORDER 0 /* 0: lower IRQ prios mean higher priority, 1: otherwise */
|
||||
#define TRC_HWTC_FREQ_HZ FREERTOS_HWTC_FREQ_HZ
|
||||
#endif
|
||||
#endif /* configUSE_PERCEPIO_TRACE_HOOKS */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTTICKS_H_ */
|
||||
|
||||
@@ -0,0 +1,417 @@
|
||||
/*
|
||||
* 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 <stdint.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
|
||||
* is defined correctly and privileged functions are placed in correct sections. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Portasm includes. */
|
||||
#include "portasm.h"
|
||||
|
||||
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
|
||||
* header files. */
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r3, [r2] \n" /* Read pxCurrentTCB. */
|
||||
" ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" bic r4, #1 \n" /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n" /* Disable MPU. */
|
||||
" \n"
|
||||
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r3] \n" /* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n" /* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n" /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r4, #4 \n" /* r4 = 4. */
|
||||
" str r4, [r2] \n" /* Program RNR = 4. */
|
||||
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
" ldr r2, xRBARConst2 \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r3!, {r4-r11} \n" /* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" orr r4, #1 \n" /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n" /* Enable MPU. */
|
||||
" dsb \n" /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r4} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
|
||||
" ldr r5, xSecureContextConst2 \n"
|
||||
" str r1, [r5] \n" /* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n" /* Set this task's PSPLIM value. */
|
||||
" msr control, r3 \n" /* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n" /* Discard everything up to r0. */
|
||||
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r4 \n" /* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||
" ldr r4, xSecureContextConst2 \n"
|
||||
" str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n" /* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n" /* r1 = 2. */
|
||||
" msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n" /* Discard everything up to r0. */
|
||||
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r3 \n" /* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
#if( configENABLE_MPU == 1 ) /* << EST */
|
||||
"xSecureContextConst2: .word xSecureContext \n"
|
||||
#endif
|
||||
#if( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||
" tst r0, #1 \n" /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||
" ite ne \n"
|
||||
" movne r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" moveq r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n" /* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n" /* Read the CONTROL register. */
|
||||
" bic r0, #1 \n" /* Clear the bit 0. */
|
||||
" msr control, r0 \n" /* Write back the new CONTROL value. */
|
||||
" bx lr \n" /* Return to the caller. */
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||
" orr r0, #1 \n" /* r0 = r0 | 1. */
|
||||
" msr control, r0 \n" /* CONTROL = r0. */
|
||||
" bx lr \n" /* Return to the caller. */
|
||||
:::"r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" ldr r0, xVTORConst \n" /* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n" /* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n" /* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n" /* Globally enable interrupts. */
|
||||
" cpsie f \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n" /* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
:: "i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulSetInterruptMaskFromISR( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, PRIMASK \n"
|
||||
" cpsid i \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
|
||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
/* To avoid compiler warnings. The return statement will never be reached,
|
||||
* but some compilers warn if it is not included, while others won't compile
|
||||
* if it is. */
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vClearInterruptMaskFromISR( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr PRIMASK, r0 \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
|
||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
/* Just to avoid compiler warning. ulMask is used from the asm code but
|
||||
* the compiler can't see that. Some compilers generate warnings without
|
||||
* the following line, while others generate warnings if the line is
|
||||
* included. */
|
||||
( void ) ulMask;
|
||||
#endif
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" .extern SecureContext_SaveContext \n"
|
||||
" .extern SecureContext_LoadContext \n"
|
||||
" \n"
|
||||
" mrs r1, psp \n" /* Read PSP in r1. */
|
||||
" ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" ldr r0, [r2] \n" /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
" \n"
|
||||
" cbz r0, save_ns_context \n" /* No secure context to save. */
|
||||
" push {r0-r2, r14} \n"
|
||||
" bl SecureContext_SaveContext \n"
|
||||
" pop {r0-r3} \n" /* LR is now in r3. */
|
||||
" mov lr, r3 \n" /* LR = r3. */
|
||||
" lsls r2, r3, #25 \n" /* r2 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl save_ns_context \n" /* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" ldr r3, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r2, [r3] \n" /* Read pxCurrentTCB. */
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" subs r1, r1, #16 \n" /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
" str r1, [r2] \n" /* Save the new top of stack in TCB. */
|
||||
" mrs r2, psplim \n" /* r2 = PSPLIM. */
|
||||
" mrs r3, control \n" /* r3 = CONTROL. */
|
||||
" mov r4, lr \n" /* r4 = LR/EXC_RETURN. */
|
||||
" stmia r1!, {r0, r2-r4} \n" /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r1, r1, #12 \n" /* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||
" str r1, [r2] \n" /* Save the new top of stack in TCB. */
|
||||
" mrs r2, psplim \n" /* r2 = PSPLIM. */
|
||||
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
|
||||
" stmia r1!, {r0, r2-r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" b select_next_task \n"
|
||||
" \n"
|
||||
" save_ns_context: \n"
|
||||
" ldr r3, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r2, [r3] \n" /* Read pxCurrentTCB. */
|
||||
#if( configENABLE_FPU == 1 )
|
||||
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
|
||||
" it eq \n"
|
||||
" vstmdbeq r1!, {s16-s31} \n" /* Store the FPU registers which are not saved automatically. */
|
||||
#endif /* configENABLE_FPU */
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" subs r1, r1, #48 \n" /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
" str r1, [r2] \n" /* Save the new top of stack in TCB. */
|
||||
" adds r1, r1, #16 \n" /* r1 = r1 + 16. */
|
||||
" stm r1, {r4-r11} \n" /* Store the registers that are not saved automatically. */
|
||||
" mrs r2, psplim \n" /* r2 = PSPLIM. */
|
||||
" mrs r3, control \n" /* r3 = CONTROL. */
|
||||
" mov r4, lr \n" /* r4 = LR/EXC_RETURN. */
|
||||
" subs r1, r1, #16 \n" /* r1 = r1 - 16. */
|
||||
" stm r1, {r0, r2-r4} \n" /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r1, r1, #44 \n" /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||
" str r1, [r2] \n" /* Save the new top of stack in TCB. */
|
||||
" adds r1, r1, #12 \n" /* r1 = r1 + 12. */
|
||||
" stm r1, {r4-r11} \n" /* Store the registers that are not saved automatically. */
|
||||
" mrs r2, psplim \n" /* r2 = PSPLIM. */
|
||||
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
|
||||
" subs r1, r1, #12 \n" /* r1 = r1 - 12. */
|
||||
" stmia r1!, {r0, r2-r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" select_next_task: \n"
|
||||
" cpsid i \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" cpsie i \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r3, [r2] \n" /* Read pxCurrentTCB. */
|
||||
" ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. r1 now points to the top of stack. */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" bic r4, #1 \n" /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n" /* Disable MPU. */
|
||||
" \n"
|
||||
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r3] \n" /* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n" /* Program MAIR0. */
|
||||
" ldr r2, xRNRConst \n" /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r4, #4 \n" /* r4 = 4. */
|
||||
" str r4, [r2] \n" /* Program RNR = 4. */
|
||||
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
" ldr r2, xRBARConst \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r3!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||
" orr r4, #1 \n" /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n" /* Enable MPU. */
|
||||
" dsb \n" /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" ldmia r1!, {r0, r2-r4} \n" /* Read from stack - r0 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = LR. */
|
||||
" msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r3 \n" /* Restore the CONTROL register value for the task. */
|
||||
" mov lr, r4 \n" /* LR = r4. */
|
||||
" ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r2] \n" /* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */
|
||||
" push {r1,r4} \n"
|
||||
" bl SecureContext_LoadContext \n" /* Restore the secure context. */
|
||||
" pop {r1,r4} \n"
|
||||
" mov lr, r4 \n" /* LR = r4. */
|
||||
" lsls r2, r4, #25 \n" /* r2 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n" /* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r1 \n" /* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#else /* configENABLE_MPU */
|
||||
" ldmia r1!, {r0, r2-r3} \n" /* Read from stack - r0 = xSecureContext, r2 = PSPLIM and r3 = LR. */
|
||||
" msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */
|
||||
" mov lr, r3 \n" /* LR = r3. */
|
||||
" ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r2] \n" /* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */
|
||||
" push {r1,r3} \n"
|
||||
" bl SecureContext_LoadContext \n" /* Restore the secure context. */
|
||||
" pop {r1,r3} \n"
|
||||
" mov lr, r3 \n" /* LR = r3. */
|
||||
" lsls r2, r3, #25 \n" /* r2 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n" /* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r1 \n" /* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" restore_ns_context: \n"
|
||||
" ldmia r1!, {r4-r11} \n" /* Restore the registers that are not automatically restored. */
|
||||
#if( configENABLE_FPU == 1 )
|
||||
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
|
||||
" it eq \n"
|
||||
" vldmiaeq r1!, {s16-s31} \n" /* Restore the FPU registers which are not restored automatically. */
|
||||
#endif /* configENABLE_FPU */
|
||||
" msr psp, r1 \n" /* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst: .word xSecureContext \n"
|
||||
#if( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" tst lr, #4 \n"
|
||||
" ite eq \n"
|
||||
" mrseq r0, msp \n"
|
||||
" mrsne r0, psp \n"
|
||||
" ldr r1, svchandler_address_const \n"
|
||||
" bx r1 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" svc %0 \n" /* Secure context is allocated in the supervisor call. */
|
||||
" bx lr \n" /* Return. */
|
||||
:: "i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" ldr r1, [r0] \n" /* The first item in the TCB is the top of the stack. */
|
||||
" ldr r0, [r1] \n" /* The first item on the stack is the task's xSecureContext. */
|
||||
" cmp r0, #0 \n" /* Raise svc if task's xSecureContext is not NULL. */
|
||||
" it ne \n"
|
||||
" svcne %0 \n" /* Secure context is freed in the supervisor call. */
|
||||
" bx lr \n" /* Return. */
|
||||
:: "i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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 __PORT_ASM_H__
|
||||
#define __PORT_ASM_H__
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* MPU wrappers includes. */
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
/**
|
||||
* @brief Restore the context of the first task so that the first task starts
|
||||
* executing.
|
||||
*/
|
||||
void vRestoreContextOfFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
BaseType_t xIsPrivileged( void ) __attribute__ (( naked ));
|
||||
|
||||
/**
|
||||
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* @note This is a privileged function and should only be called from the kenrel
|
||||
* code.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vResetPrivilege( void ) __attribute__ (( naked ));
|
||||
|
||||
/**
|
||||
* @brief Starts the first task.
|
||||
*/
|
||||
void vStartFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Disables interrupts.
|
||||
*/
|
||||
uint32_t ulSetInterruptMaskFromISR( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enables interrupts.
|
||||
*/
|
||||
void vClearInterruptMaskFromISR( uint32_t ulMask ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief PendSV Exception handler.
|
||||
*/
|
||||
void PendSV_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SVC Handler.
|
||||
*/
|
||||
void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Allocate a Secure context for the calling task.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the stack to be allocated on the
|
||||
* secure side for the calling task.
|
||||
*/
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__ (( naked ));
|
||||
|
||||
/**
|
||||
* @brief Free the task's secure context.
|
||||
*
|
||||
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
|
||||
*/
|
||||
void vPortFreeSecureContext( uint32_t *pulTCB ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* __PORT_ASM_H__ */
|
||||
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
* 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 PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef configENABLE_FPU
|
||||
#error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU.
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
#ifndef configENABLE_MPU
|
||||
#error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU.
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#ifndef configENABLE_TRUSTZONE
|
||||
#error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Type definitions.
|
||||
*/
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M33"
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP()
|
||||
#define portINLINE __inline
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline ))
|
||||
#endif
|
||||
#define portHAS_STACK_OVERFLOW_CHECKING 1
|
||||
#define portDONT_DISCARD __attribute__(( used ))
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Extern declarations.
|
||||
*/
|
||||
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern uint32_t ulSetInterruptMaskFromISR( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
extern void vClearInterruptMaskFromISR( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
|
||||
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
|
||||
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief MPU specific constants.
|
||||
*/
|
||||
#if( configENABLE_MPU == 1 )
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
#else
|
||||
#define portPRIVILEGE_BIT ( 0x0UL )
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
|
||||
/* MPU regions. */
|
||||
#define portPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
|
||||
/* Device memory attributes used in MPU_MAIR registers.
|
||||
*
|
||||
* 8-bit values encoded as follows:
|
||||
* Bit[7:4] - 0000 - Device Memory
|
||||
* Bit[3:2] - 00 --> Device-nGnRnE
|
||||
* 01 --> Device-nGnRE
|
||||
* 10 --> Device-nGRE
|
||||
* 11 --> Device-GRE
|
||||
* Bit[1:0] - 00, Reserved.
|
||||
*/
|
||||
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
|
||||
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
|
||||
|
||||
/* Normal memory attributes used in MPU_MAIR registers. */
|
||||
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */
|
||||
#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
|
||||
|
||||
/* Attributes used in MPU_RBAR registers. */
|
||||
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
|
||||
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
|
||||
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
|
||||
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
|
||||
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
|
||||
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 1UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Settings to define an MPU region.
|
||||
*/
|
||||
typedef struct MPURegionSettings
|
||||
{
|
||||
uint32_t ulRBAR; /**< RBAR for the region. */
|
||||
uint32_t ulRLAR; /**< RLAR for the region. */
|
||||
} MPURegionSettings_t;
|
||||
|
||||
/**
|
||||
* @brief MPU settings as stored in the TCB.
|
||||
*/
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */
|
||||
MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
|
||||
} xMPU_SETTINGS;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief SVC numbers.
|
||||
*/
|
||||
#define portSVC_ALLOCATE_SECURE_CONTEXT 0
|
||||
#define portSVC_FREE_SECURE_CONTEXT 1
|
||||
#define portSVC_START_SCHEDULER 2
|
||||
#define portSVC_RAISE_PRIVILEGE 3
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Scheduler utilities.
|
||||
*/
|
||||
#define portYIELD() vPortYield()
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMaskFromISR( x )
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if 1 /* << EST */
|
||||
#define portDISABLE_ALL_INTERRUPTS() __asm volatile("cpsid i")
|
||||
#define portENABLE_ALL_INTERRUPTS() __asm volatile("cpsie i")
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||
*/
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/**
|
||||
* @brief Allocate a secure context for the task.
|
||||
*
|
||||
* Tasks are not created with a secure context. Any task that is going to call
|
||||
* secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a
|
||||
* secure context before it calls any secure function.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the secure stack to be allocated.
|
||||
*/
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
|
||||
|
||||
/**
|
||||
* @brief Called when a task is deleted to delete the task's secure context,
|
||||
* if it has one.
|
||||
*
|
||||
* @param[in] pxTCB The TCB of the task being deleted.
|
||||
*/
|
||||
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
|
||||
#else
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
|
||||
#define portCLEAN_UP_TCB( pxTCB )
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
|
||||
/**
|
||||
* @brief Raise an SVC request to raise privilege.
|
||||
*
|
||||
* The SVC handler checks that the SVC was raised from a system call and only
|
||||
* then it raises the privilege. If this is called from any other place,
|
||||
* the privilege is not raised.
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*/
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
#else
|
||||
#define portIS_PRIVILEGED()
|
||||
#define portRAISE_PRIVILEGE()
|
||||
#define portRESET_PRIVILEGE()
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Barriers.
|
||||
*/
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* 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!
|
||||
*/
|
||||
|
||||
/* Secure context includes. */
|
||||
#include "secure_context.h"
|
||||
|
||||
/* Secure heap includes. */
|
||||
#include "secure_heap.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief CONTROL value for privileged tasks.
|
||||
*
|
||||
* Bit[0] - 0 --> Thread mode is privileged.
|
||||
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||
*/
|
||||
#define securecontextCONTROL_VALUE_PRIVILEGED 0x02
|
||||
|
||||
/**
|
||||
* @brief CONTROL value for un-privileged tasks.
|
||||
*
|
||||
* Bit[0] - 1 --> Thread mode is un-privileged.
|
||||
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||
*/
|
||||
#define securecontextCONTROL_VALUE_UNPRIVILEGED 0x03
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Structure to represent secure context.
|
||||
*
|
||||
* @note Since stack grows down, pucStackStart is the highest address while
|
||||
* pucStackLimit is the first addess of the allocated memory.
|
||||
*/
|
||||
typedef struct SecureContext
|
||||
{
|
||||
uint8_t *pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
|
||||
uint8_t *pucStackLimit; /**< Last location of the stack memory (PSPLIM). */
|
||||
uint8_t *pucStackStart; /**< First location of the stack memory. */
|
||||
} SecureContext_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* No stack for thread mode until a task's context is loaded. */
|
||||
secureportSET_PSPLIM( securecontextNO_STACK );
|
||||
secureportSET_PSP( securecontextNO_STACK );
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be unprivileged. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be privileged.. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged )
|
||||
#else /* configENABLE_MPU */
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize )
|
||||
#endif /* configENABLE_MPU */
|
||||
{
|
||||
uint8_t *pucStackMemory = NULL;
|
||||
uint32_t ulIPSR;
|
||||
SecureContextHandle_t xSecureContextHandle = NULL;
|
||||
#if( configENABLE_MPU == 1 )
|
||||
uint32_t *pulCurrentStackPointer = NULL;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* Allocate the context structure. */
|
||||
xSecureContextHandle = ( SecureContextHandle_t ) pvPortMalloc( sizeof( SecureContext_t ) );
|
||||
|
||||
if( xSecureContextHandle != NULL )
|
||||
{
|
||||
/* Allocate the stack space. */
|
||||
pucStackMemory = pvPortMalloc( ulSecureStackSize );
|
||||
|
||||
if( pucStackMemory != NULL )
|
||||
{
|
||||
/* Since stack grows down, the starting point will be the last
|
||||
* location. Note that this location is next to the last
|
||||
* allocated byte because the hardware decrements the stack
|
||||
* pointer before writing i.e. if stack pointer is 0x2, a push
|
||||
* operation will decrement the stack pointer to 0x1 and then
|
||||
* write at 0x1. */
|
||||
xSecureContextHandle->pucStackStart = pucStackMemory + ulSecureStackSize;
|
||||
|
||||
/* The stack cannot go beyond this location. This value is
|
||||
* programmed in the PSPLIM register on context switch.*/
|
||||
xSecureContextHandle->pucStackLimit = pucStackMemory;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Store the correct CONTROL value for the task on the stack.
|
||||
* This value is programmed in the CONTROL register on
|
||||
* context switch. */
|
||||
pulCurrentStackPointer = ( uint32_t * ) xSecureContextHandle->pucStackStart;
|
||||
pulCurrentStackPointer--;
|
||||
if( ulIsTaskPrivileged )
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
|
||||
}
|
||||
else
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED;
|
||||
}
|
||||
|
||||
/* Store the current stack pointer. This value is programmed in
|
||||
* the PSP register on context switch. */
|
||||
xSecureContextHandle->pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Current SP is set to the starting of the stack. This
|
||||
* value programmed in the PSP register on context switch. */
|
||||
xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart;
|
||||
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Free the context to avoid memory leak and make sure to return
|
||||
* NULL to indicate failure. */
|
||||
vPortFree( xSecureContextHandle );
|
||||
xSecureContextHandle = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xSecureContextHandle;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* Ensure that valid parameters are passed. */
|
||||
secureportASSERT( xSecureContextHandle != NULL );
|
||||
|
||||
/* Free the stack space. */
|
||||
vPortFree( xSecureContextHandle->pucStackLimit );
|
||||
|
||||
/* Free the context itself. */
|
||||
vPortFree( xSecureContextHandle );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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 __SECURE_CONTEXT_H__
|
||||
#define __SECURE_CONTEXT_H__
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
/**
|
||||
* @brief PSP value when no task's context is loaded.
|
||||
*/
|
||||
#define securecontextNO_STACK 0x0
|
||||
|
||||
/**
|
||||
* @brief Opaque handle.
|
||||
*/
|
||||
struct SecureContext;
|
||||
typedef struct SecureContext* SecureContextHandle_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the secure context management system.
|
||||
*
|
||||
* PSP is set to NULL and therefore a task must allocate and load a context
|
||||
* before calling any secure side function in the thread mode.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureContext_Init( void );
|
||||
|
||||
/**
|
||||
* @brief Allocates a context on the secure side.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] ulSecureStackSize Size of the stack to allocate on secure side.
|
||||
* @param[in] ulIsTaskPrivileged 1 if the calling task is privileged, 0 otherwise.
|
||||
*
|
||||
* @return Opaque context handle if context is successfully allocated, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
#if( configENABLE_MPU == 1 )
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged );
|
||||
#else /* configENABLE_MPU */
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize );
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/**
|
||||
* @brief Frees the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the
|
||||
* context to be freed.
|
||||
*/
|
||||
void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle );
|
||||
|
||||
/**
|
||||
* @brief Loads the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the context
|
||||
* to be loaded.
|
||||
*/
|
||||
void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle );
|
||||
|
||||
/**
|
||||
* @brief Saves the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the context
|
||||
* to be saved.
|
||||
*/
|
||||
void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle );
|
||||
|
||||
#endif /* __SECURE_CONTEXT_H__ */
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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!
|
||||
*/
|
||||
|
||||
/* Secure context includes. */
|
||||
#include "secure_context.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )
|
||||
{
|
||||
/* xSecureContextHandle value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||
" cbz r1, load_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||
" ldmia r0!, {r1, r2} \n" /* r1 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" ldmia r1!, {r3} \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||
" msr control, r3 \n" /* CONTROL = r3. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" msr psplim, r2 \n" /* PSPLIM = r2. */
|
||||
" msr psp, r1 \n" /* PSP = r1. */
|
||||
" \n"
|
||||
" load_ctx_therad_mode: \n"
|
||||
" nop \n"
|
||||
" \n"
|
||||
:::"r0", "r1", "r2"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )
|
||||
{
|
||||
/* xSecureContextHandle value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||
" cbz r1, save_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||
" mrs r1, psp \n" /* r1 = PSP. */
|
||||
#if( configENABLE_FPU == 1 )
|
||||
" vstmdb r1!, {s0} \n" /* Trigger the defferred stacking of FPU registers. */
|
||||
" vldmia r1!, {s0} \n" /* Nullify the effect of the pervious statement. */
|
||||
#endif /* configENABLE_FPU */
|
||||
#if( configENABLE_MPU == 1 )
|
||||
" mrs r2, control \n" /* r2 = CONTROL. */
|
||||
" stmdb r1!, {r2} \n" /* Store CONTROL value on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" str r1, [r0] \n" /* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */
|
||||
" movs r1, %0 \n" /* r1 = securecontextNO_STACK. */
|
||||
" msr psplim, r1 \n" /* PSPLIM = securecontextNO_STACK. */
|
||||
" msr psp, r1 \n" /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||
" \n"
|
||||
" save_ctx_therad_mode: \n"
|
||||
" nop \n"
|
||||
" \n"
|
||||
:: "i" ( securecontextNO_STACK ) : "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
@@ -0,0 +1,450 @@
|
||||
/*
|
||||
* 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 <stdint.h>
|
||||
|
||||
/* Secure context heap includes. */
|
||||
#include "secure_heap.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief Total heap size.
|
||||
*/
|
||||
#define secureconfigTOTAL_HEAP_SIZE ( ( ( size_t ) ( 10 * 1024 ) ) )
|
||||
|
||||
/* No test marker by default. */
|
||||
#ifndef mtCOVERAGE_TEST_MARKER
|
||||
#define mtCOVERAGE_TEST_MARKER()
|
||||
#endif
|
||||
|
||||
/* No tracing by default. */
|
||||
#ifndef traceMALLOC
|
||||
#define traceMALLOC( pvReturn, xWantedSize )
|
||||
#endif
|
||||
|
||||
/* No tracing by default. */
|
||||
#ifndef traceFREE
|
||||
#define traceFREE( pv, xBlockSize )
|
||||
#endif
|
||||
|
||||
/* Block sizes must not get too small. */
|
||||
#define secureheapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
|
||||
|
||||
/* Assumes 8bit bytes! */
|
||||
#define secureheapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Allocate the memory for the heap. */
|
||||
#if( configAPPLICATION_ALLOCATED_HEAP == 1 )
|
||||
/* The application writer has already defined the array used for the RTOS
|
||||
* heap - probably so it can be placed in a special segment or address. */
|
||||
extern uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#else /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#endif /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
|
||||
/**
|
||||
* @brief The linked list structure.
|
||||
*
|
||||
* This is used to link free blocks in order of their memory address.
|
||||
*/
|
||||
typedef struct A_BLOCK_LINK
|
||||
{
|
||||
struct A_BLOCK_LINK *pxNextFreeBlock; /**< The next free block in the list. */
|
||||
size_t xBlockSize; /**< The size of the free block. */
|
||||
} BlockLink_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Called automatically to setup the required heap structures the first
|
||||
* time pvPortMalloc() is called.
|
||||
*/
|
||||
static void prvHeapInit( void );
|
||||
|
||||
/**
|
||||
* @brief Inserts a block of memory that is being freed into the correct
|
||||
* position in the list of free memory blocks.
|
||||
*
|
||||
* The block being freed will be merged with the block in front it and/or the
|
||||
* block behind it if the memory blocks are adjacent to each other.
|
||||
*
|
||||
* @param[in] pxBlockToInsert The block being freed.
|
||||
*/
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief The size of the structure placed at the beginning of each allocated
|
||||
* memory block must by correctly byte aligned.
|
||||
*/
|
||||
static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( secureportBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
|
||||
/**
|
||||
* @brief Create a couple of list links to mark the start and end of the list.
|
||||
*/
|
||||
static BlockLink_t xStart, *pxEnd = NULL;
|
||||
|
||||
/**
|
||||
* @brief Keeps track of the number of free bytes remaining, but says nothing
|
||||
* about fragmentation.
|
||||
*/
|
||||
static size_t xFreeBytesRemaining = 0U;
|
||||
static size_t xMinimumEverFreeBytesRemaining = 0U;
|
||||
|
||||
/**
|
||||
* @brief Gets set to the top bit of an size_t type.
|
||||
*
|
||||
* When this bit in the xBlockSize member of an BlockLink_t structure is set
|
||||
* then the block belongs to the application. When the bit is free the block is
|
||||
* still part of the free heap space.
|
||||
*/
|
||||
static size_t xBlockAllocatedBit = 0;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvHeapInit( void )
|
||||
{
|
||||
BlockLink_t *pxFirstFreeBlock;
|
||||
uint8_t *pucAlignedHeap;
|
||||
size_t uxAddress;
|
||||
size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
|
||||
|
||||
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||
uxAddress = ( size_t ) ucHeap;
|
||||
|
||||
if( ( uxAddress & secureportBYTE_ALIGNMENT_MASK ) != 0 )
|
||||
{
|
||||
uxAddress += ( secureportBYTE_ALIGNMENT - 1 );
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;
|
||||
}
|
||||
|
||||
pucAlignedHeap = ( uint8_t * ) uxAddress;
|
||||
|
||||
/* xStart is used to hold a pointer to the first item in the list of free
|
||||
* blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
|
||||
xStart.xBlockSize = ( size_t ) 0;
|
||||
|
||||
/* pxEnd is used to mark the end of the list of free blocks and is inserted
|
||||
* at the end of the heap space. */
|
||||
uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
|
||||
uxAddress -= xHeapStructSize;
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
pxEnd = ( void * ) uxAddress;
|
||||
pxEnd->xBlockSize = 0;
|
||||
pxEnd->pxNextFreeBlock = NULL;
|
||||
|
||||
/* To start with there is a single free block that is sized to take up the
|
||||
* entire heap space, minus the space taken by pxEnd. */
|
||||
pxFirstFreeBlock = ( void * ) pucAlignedHeap;
|
||||
pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
|
||||
pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
|
||||
|
||||
/* Only one block exists - and it covers the entire usable heap space. */
|
||||
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
|
||||
/* Work out the position of the top bit in a size_t variable. */
|
||||
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert )
|
||||
{
|
||||
BlockLink_t *pxIterator;
|
||||
uint8_t *puc;
|
||||
|
||||
/* Iterate through the list until a block is found that has a higher address
|
||||
* than the block being inserted. */
|
||||
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
/* Nothing to do here, just iterate to the right position. */
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted after
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxIterator;
|
||||
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
|
||||
{
|
||||
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||
pxBlockToInsert = pxIterator;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted before
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxBlockToInsert;
|
||||
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
if( pxIterator->pxNextFreeBlock != pxEnd )
|
||||
{
|
||||
/* Form one big block from the two blocks. */
|
||||
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxEnd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the block being inserted plugged a gab, so was merged with the block
|
||||
* before and the block after, then it's pxNextFreeBlock pointer will have
|
||||
* already been set, and should not be set here as that would make it point
|
||||
* to itself. */
|
||||
if( pxIterator != pxBlockToInsert )
|
||||
{
|
||||
pxIterator->pxNextFreeBlock = pxBlockToInsert;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void *pvPortMalloc( size_t xWantedSize )
|
||||
{
|
||||
BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
|
||||
void *pvReturn = NULL;
|
||||
|
||||
/* If this is the first call to malloc then the heap will require
|
||||
* initialisation to setup the list of free blocks. */
|
||||
if( pxEnd == NULL )
|
||||
{
|
||||
prvHeapInit();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Check the requested block size is not so large that the top bit is set.
|
||||
* The top bit of the block size member of the BlockLink_t structure is used
|
||||
* to determine who owns the block - the application or the kernel, so it
|
||||
* must be free. */
|
||||
if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
|
||||
{
|
||||
/* The wanted size is increased so it can contain a BlockLink_t
|
||||
* structure in addition to the requested amount of bytes. */
|
||||
if( xWantedSize > 0 )
|
||||
{
|
||||
xWantedSize += xHeapStructSize;
|
||||
|
||||
/* Ensure that blocks are always aligned to the required number of
|
||||
* bytes. */
|
||||
if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||
{
|
||||
/* Byte alignment required. */
|
||||
xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) );
|
||||
secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
||||
{
|
||||
/* Traverse the list from the start (lowest address) block until
|
||||
* one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||
{
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the end marker was reached then a block of adequate size was
|
||||
* not found. */
|
||||
if( pxBlock != pxEnd )
|
||||
{
|
||||
/* Return the memory space pointed to - jumping over the
|
||||
* BlockLink_t structure at its start. */
|
||||
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
|
||||
|
||||
/* This block is being returned for use so must be taken out
|
||||
* of the list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
|
||||
/* If the block is larger than required it can be split into
|
||||
* two. */
|
||||
if( ( pxBlock->xBlockSize - xWantedSize ) > secureheapMINIMUM_BLOCK_SIZE )
|
||||
{
|
||||
/* This block is to be split into two. Create a new
|
||||
* block following the number of bytes requested. The void
|
||||
* cast is used to prevent byte alignment warnings from the
|
||||
* compiler. */
|
||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||
secureportASSERT( ( ( ( size_t ) pxNewBlockLink ) & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
|
||||
/* Calculate the sizes of two blocks split from the single
|
||||
* block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
|
||||
/* Insert the new block into the list of free blocks. */
|
||||
prvInsertBlockIntoFreeList( pxNewBlockLink );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
|
||||
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
||||
{
|
||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* The block is being returned - it is allocated and owned by
|
||||
* the application and has no "next" block. */
|
||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
|
||||
#if( secureconfigUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
extern void vApplicationMallocFailedHook( void );
|
||||
vApplicationMallocFailedHook();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFree( void *pv )
|
||||
{
|
||||
uint8_t *puc = ( uint8_t * ) pv;
|
||||
BlockLink_t *pxLink;
|
||||
|
||||
if( pv != NULL )
|
||||
{
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
* before it. */
|
||||
puc -= xHeapStructSize;
|
||||
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = ( void * ) puc;
|
||||
|
||||
/* Check the block is actually allocated. */
|
||||
secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
||||
secureportASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||
|
||||
if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
|
||||
{
|
||||
if( pxLink->pxNextFreeBlock == NULL )
|
||||
{
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
* allocated. */
|
||||
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
traceFREE( pv, pxLink->xBlockSize );
|
||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||
}
|
||||
secureportENABLE_NON_SECURE_INTERRUPTS();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetFreeHeapSize( void )
|
||||
{
|
||||
return xFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void )
|
||||
{
|
||||
return xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortInitialiseBlocks( void )
|
||||
{
|
||||
/* This just exists to keep the linker quiet. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 __SECURE_HEAP_H__
|
||||
#define __SECURE_HEAP_H__
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* @brief Allocates memory from heap.
|
||||
*
|
||||
* @param[in] xWantedSize The size of the memory to be allocated.
|
||||
*
|
||||
* @return Pointer to the memory region if the allocation is successful, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
void *pvPortMalloc( size_t xWantedSize );
|
||||
|
||||
/**
|
||||
* @brief Frees the previously allocated memory.
|
||||
*
|
||||
* @param[in] pv Pointer to the memory to be freed.
|
||||
*/
|
||||
void vPortFree( void *pv );
|
||||
|
||||
#endif /* __SECURE_HEAP_H__ */
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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 <stdint.h>
|
||||
|
||||
/* Secure init includes. */
|
||||
#include "secure_init.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the SCB.
|
||||
*/
|
||||
#define secureinitSCB_AIRCR ( ( volatile uint32_t * ) 0xe000ed0c ) /* Application Interrupt and Reset Control Register. */
|
||||
#define secureinitSCB_AIRCR_VECTKEY_POS ( 16UL )
|
||||
#define secureinitSCB_AIRCR_VECTKEY_MASK ( 0xFFFFUL << secureinitSCB_AIRCR_VECTKEY_POS )
|
||||
#define secureinitSCB_AIRCR_PRIS_POS ( 14UL )
|
||||
#define secureinitSCB_AIRCR_PRIS_MASK ( 1UL << secureinitSCB_AIRCR_PRIS_POS )
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the FPU.
|
||||
*/
|
||||
#define secureinitFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
|
||||
#define secureinitFPCCR_LSPENS_POS ( 29UL )
|
||||
#define secureinitFPCCR_LSPENS_MASK ( 1UL << secureinitFPCCR_LSPENS_POS )
|
||||
#define secureinitFPCCR_TS_POS ( 26UL )
|
||||
#define secureinitFPCCR_TS_MASK ( 1UL << secureinitFPCCR_TS_POS )
|
||||
|
||||
#define secureinitNSACR ( ( volatile uint32_t * ) 0xe000ed8c ) /* Non-secure Access Control Register. */
|
||||
#define secureinitNSACR_CP10_POS ( 10UL )
|
||||
#define secureinitNSACR_CP10_MASK ( 1UL << secureinitNSACR_CP10_POS )
|
||||
#define secureinitNSACR_CP11_POS ( 11UL )
|
||||
#define secureinitNSACR_CP11_MASK ( 1UL << secureinitNSACR_CP11_POS )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureInit_DePrioritizeNSExceptions( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
*( secureinitSCB_AIRCR ) = ( *( secureinitSCB_AIRCR ) & ~( secureinitSCB_AIRCR_VECTKEY_MASK | secureinitSCB_AIRCR_PRIS_MASK ) ) |
|
||||
( ( 0x05FAUL << secureinitSCB_AIRCR_VECTKEY_POS ) & secureinitSCB_AIRCR_VECTKEY_MASK ) |
|
||||
( ( 0x1UL << secureinitSCB_AIRCR_PRIS_POS ) & secureinitSCB_AIRCR_PRIS_MASK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureInit_EnableNSFPUAccess( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* CP10 = 1 ==> Non-secure access to the Floating Point Unit is
|
||||
* permitted. CP11 should be programmed to the same value as CP10. */
|
||||
*( secureinitNSACR ) |= ( secureinitNSACR_CP10_MASK | secureinitNSACR_CP11_MASK );
|
||||
|
||||
/* LSPENS = 0 ==> LSPEN is writable fron non-secure state. This ensures
|
||||
* that we can enable/disable lazy stacking in port.c file. */
|
||||
*( secureinitFPCCR ) &= ~ ( secureinitFPCCR_LSPENS_MASK );
|
||||
|
||||
/* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP
|
||||
* registers (S16-S31) are also pushed to stack on exception entry and
|
||||
* restored on exception return. */
|
||||
*( secureinitFPCCR ) |= ( secureinitFPCCR_TS_MASK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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 __SECURE_INIT_H__
|
||||
#define __SECURE_INIT_H__
|
||||
|
||||
/**
|
||||
* @brief De-prioritizes the non-secure exceptions.
|
||||
*
|
||||
* This is needed to ensure that the non-secure PendSV runs at the lowest
|
||||
* priority. Context switch is done in the non-secure PendSV handler.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureInit_DePrioritizeNSExceptions( void );
|
||||
|
||||
/**
|
||||
* @brief Sets up the Floating Point Unit (FPU) for Non-Secure access.
|
||||
*
|
||||
* Also sets FPCCR.TS=1 to ensure that the content of the Floating Point
|
||||
* Registers are not leaked to the non-secure side.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureInit_EnableNSFPUAccess( void );
|
||||
|
||||
#endif /* __SECURE_INIT_H__ */
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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 __SECURE_PORT_MACROS_H__
|
||||
#define __SECURE_PORT_MACROS_H__
|
||||
|
||||
/**
|
||||
* @brief Byte alignment requirements.
|
||||
*/
|
||||
#define secureportBYTE_ALIGNMENT 8
|
||||
#define secureportBYTE_ALIGNMENT_MASK ( 0x0007 )
|
||||
|
||||
/**
|
||||
* @brief Macro to declare a function as non-secure callable.
|
||||
*/
|
||||
#if defined( __IAR_SYSTEMS_ICC__ )
|
||||
#define secureportNON_SECURE_CALLABLE __cmse_nonsecure_entry __root
|
||||
#else
|
||||
#define secureportNON_SECURE_CALLABLE __attribute__((cmse_nonsecure_entry)) __attribute__((used))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set the secure PRIMASK value.
|
||||
*/
|
||||
#define secureportSET_SECURE_PRIMASK( ulPrimaskValue ) \
|
||||
__asm volatile ( "msr primask, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Set the non-secure PRIMASK value.
|
||||
*/
|
||||
#define secureportSET_NON_SECURE_PRIMASK( ulPrimaskValue ) \
|
||||
__asm volatile ( "msr primask_ns, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Read the PSP value in the given variable.
|
||||
*/
|
||||
#define secureportREAD_PSP( pucOutCurrentStackPointer ) \
|
||||
__asm volatile ( "mrs %0, psp" : "=r" ( pucOutCurrentStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the PSP to the given value.
|
||||
*/
|
||||
#define secureportSET_PSP( pucCurrentStackPointer ) \
|
||||
__asm volatile ( "msr psp, %0" : : "r" ( pucCurrentStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the PSPLIM to the given value.
|
||||
*/
|
||||
#define secureportSET_PSPLIM( pucStackLimit ) \
|
||||
__asm volatile ( "msr psplim, %0" : : "r" ( pucStackLimit ) )
|
||||
|
||||
/**
|
||||
* @brief Set the NonSecure MSP to the given value.
|
||||
*/
|
||||
#define secureportSET_MSP_NS( pucMainStackPointer ) \
|
||||
__asm volatile ( "msr msp_ns, %0" : : "r" ( pucMainStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the CONTROL register to the given value.
|
||||
*/
|
||||
#define secureportSET_CONTROL( ulControl ) \
|
||||
__asm volatile ( "msr control, %0" : : "r" ( ulControl ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Read the Interrupt Program Status Register (IPSR) value in the given
|
||||
* variable.
|
||||
*/
|
||||
#define secureportREAD_IPSR( ulIPSR ) \
|
||||
__asm volatile ( "mrs %0, ipsr" : "=r" ( ulIPSR ) )
|
||||
|
||||
/**
|
||||
* @brief PRIMASK value to enable interrupts.
|
||||
*/
|
||||
#define secureportPRIMASK_ENABLE_INTERRUPTS_VAL 0
|
||||
|
||||
/**
|
||||
* @brief PRIMASK value to disable interrupts.
|
||||
*/
|
||||
#define secureportPRIMASK_DISABLE_INTERRUPTS_VAL 1
|
||||
|
||||
/**
|
||||
* @brief Disable secure interrupts.
|
||||
*/
|
||||
#define secureportDISABLE_SECURE_INTERRUPTS() secureportSET_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Disable non-secure interrupts.
|
||||
*
|
||||
* This effectively disables context switches.
|
||||
*/
|
||||
#define secureportDISABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Enable non-secure interrupts.
|
||||
*/
|
||||
#define secureportENABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_ENABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Assert definition.
|
||||
*/
|
||||
#define secureportASSERT( x ) \
|
||||
if( ( x ) == 0 ) \
|
||||
{ \
|
||||
secureportDISABLE_SECURE_INTERRUPTS(); \
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS(); \
|
||||
for( ;; ); \
|
||||
}
|
||||
|
||||
#endif /* __SECURE_PORT_MACROS_H__ */
|
||||
@@ -0,0 +1,155 @@
|
||||
#################################################################################
|
||||
# .gdbinit-FreeRTOS-helpers
|
||||
#
|
||||
# Created on: 29.03.2013
|
||||
# Author: Artem Pisarenko
|
||||
#
|
||||
# Helper script providing support for FreeRTOS-aware debugging
|
||||
# Supported architectures: Cortex-M3
|
||||
# Features:
|
||||
# - showing tasks (handle and name);
|
||||
# - switching context to specified task from almost any context (excluding system exceptions);
|
||||
# - restore current running context.
|
||||
#################################################################################
|
||||
|
||||
# Command "freertos_show_threads"
|
||||
# Shows tasks table: handle(xTaskHandle) and name
|
||||
define freertos_show_threads
|
||||
set $thread_list_size = 0
|
||||
set $thread_list_size = uxCurrentNumberOfTasks
|
||||
if ($thread_list_size == 0)
|
||||
echo FreeRTOS missing or scheduler isn't started\n
|
||||
else
|
||||
set $current_thread = pxCurrentTCB
|
||||
set $tasks_found = 0
|
||||
set $idx = 0
|
||||
|
||||
set $task_list = pxReadyTasksLists
|
||||
set $task_list_size = sizeof(pxReadyTasksLists)/sizeof(pxReadyTasksLists[0])
|
||||
while ($idx < $task_list_size)
|
||||
_freertos_show_thread_item $task_list[$idx]
|
||||
set $idx = $idx + 1
|
||||
end
|
||||
|
||||
_freertos_show_thread_item xDelayedTaskList1
|
||||
_freertos_show_thread_item xDelayedTaskList2
|
||||
_freertos_show_thread_item xPendingReadyList
|
||||
|
||||
set $VAL_dbgFreeRTOSConfig_suspend = dbgFreeRTOSConfig_suspend_value
|
||||
if ($VAL_dbgFreeRTOSConfig_suspend != 0)
|
||||
_freertos_show_thread_item xSuspendedTaskList
|
||||
end
|
||||
|
||||
set $VAL_dbgFreeRTOSConfig_delete = dbgFreeRTOSConfig_delete_value
|
||||
if ($VAL_dbgFreeRTOSConfig_delete != 0)
|
||||
_freertos_show_thread_item xTasksWaitingTermination
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Command "freertos_switch_to_task"
|
||||
# Switches debugging context to specified task, argument - task handle
|
||||
define freertos_switch_to_task
|
||||
set var dbgPendingTaskHandle = $arg0
|
||||
set $current_IPSR_val = $xpsr & 0xFF
|
||||
if (($current_IPSR_val >= 1) && ($current_IPSR_val <= 15))
|
||||
echo Switching from system exception context isn't supported
|
||||
else
|
||||
set $VAL_dbgPendSVHookState = dbgPendSVHookState
|
||||
if ($VAL_dbgPendSVHookState == 0)
|
||||
set $last_PRIMASK_val = $PRIMASK
|
||||
set $last_SCB_ICSR_val = *((volatile unsigned long *)0xE000ED04)
|
||||
set $last_SYSPRI2_val = *((volatile unsigned long *)0xE000ED20)
|
||||
set $last_SCB_CCR_val = *((volatile unsigned long *)0xE000ED14)
|
||||
set $running_IPSR_val = $current_IPSR_val
|
||||
set $PRIMASK = 0
|
||||
# *(portNVIC_SYSPRI2) &= ~(255 << 16) // temporary increase PendSV priority to highest
|
||||
set {unsigned int}0xe000ed20 = ($last_SYSPRI2_val & (~(255 << 16)))
|
||||
# set SCB->CCR NONBASETHRDENA bit (allows processor enter thread mode from at any execution priority level)
|
||||
set {unsigned int}0xE000ED14 = (1) | $last_SCB_CCR_val
|
||||
set var dbgPendSVHookState = 1
|
||||
end
|
||||
# *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET
|
||||
set {unsigned int}0xe000ed04 = 0x10000000
|
||||
continue
|
||||
# here we stuck at "bkpt" instruction just before "bx lr" (in helper's xPortPendSVHandler)
|
||||
# force returning to thread mode with process stack
|
||||
set $lr = 0xFFFFFFFD
|
||||
stepi
|
||||
stepi
|
||||
# here we get rewound to task
|
||||
end
|
||||
end
|
||||
|
||||
# Command "freertos_restore_running_context"
|
||||
# Restores context of running task
|
||||
define freertos_restore_running_context
|
||||
set $VAL_dbgPendSVHookState = dbgPendSVHookState
|
||||
if ($VAL_dbgPendSVHookState == 0)
|
||||
echo Current task is RUNNING, ignoring command...
|
||||
else
|
||||
set var dbgPendingTaskHandle = (void *)pxCurrentTCB
|
||||
# *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET
|
||||
set {unsigned int}0xe000ed04 = 0x10000000
|
||||
continue
|
||||
# here we stuck at "bkpt" instruction just before "bx lr" (in helper's xPortPendSVHandler)
|
||||
# check what execution mode was in context we started to switch from
|
||||
if ($running_IPSR_val == 0)
|
||||
# force returning to thread mode with process stack
|
||||
set $lr = 0xFFFFFFFD
|
||||
else
|
||||
# force returning to handler mode
|
||||
set $lr = 0xFFFFFFF1
|
||||
end
|
||||
stepi
|
||||
stepi
|
||||
# here we get rewound to running task at place we started switching
|
||||
# restore processor state
|
||||
set $PRIMASK = $last_PRIMASK_val
|
||||
set {unsigned int}0xe000ed20 = $last_SYSPRI2_val
|
||||
set {unsigned int}0xE000ED14 = $last_SCB_CCR_val
|
||||
if ($last_SCB_ICSR_val & (1 << 28))
|
||||
set {unsigned int}0xe000ed04 = 0x10000000
|
||||
end
|
||||
set var dbgPendSVHookState = 0
|
||||
end
|
||||
end
|
||||
|
||||
# Command "show_broken_backtrace"
|
||||
# Workaround of issue when context is being stuck in the middle of function epilogue (i.e., in vTaskDelay())
|
||||
# This solution is applied to following situation only:
|
||||
### ... function body end
|
||||
### xxxxxxxx+0: add.w r7, r7, #16
|
||||
### xxxxxxxx+4: mov sp, r7 ; <- debug current instruction pointer
|
||||
### xxxxxxxx+6: pop {r7, pc}
|
||||
### }
|
||||
# (Otherwise it will crash !)
|
||||
define show_broken_backtrace
|
||||
# cancel effect of xxxxxxxx+4 instruction twice (because we will step it to update eclipse views)
|
||||
set $r7 = $r7 - 16 - 16
|
||||
set $pc = $pc - 4
|
||||
stepi
|
||||
end
|
||||
|
||||
|
||||
#######################
|
||||
# Internal functions
|
||||
define _freertos_show_thread_item
|
||||
set $list_thread_count = $arg0.uxNumberOfItems
|
||||
set $prev_list_elem_ptr = -1
|
||||
set $list_elem_ptr = $arg0.xListEnd.pxPrevious
|
||||
while (($list_thread_count > 0) && ($list_elem_ptr != 0) && ($list_elem_ptr != $prev_list_elem_ptr) && ($tasks_found < $thread_list_size))
|
||||
set $threadid = $list_elem_ptr->pvOwner
|
||||
set $thread_name_str = (*((tskTCB *)$threadid)).pcTaskName
|
||||
set $tasks_found = $tasks_found + 1
|
||||
set $list_thread_count = $list_thread_count - 1
|
||||
set $prev_list_elem_ptr = $list_elem_ptr
|
||||
set $list_elem_ptr = $prev_list_elem_ptr->pxPrevious
|
||||
if ($threadid == $current_thread)
|
||||
printf "0x%x\t%s\t\t<---RUNNING\n", $threadid, $thread_name_str
|
||||
else
|
||||
printf "0x%x\t%s\n", $threadid, $thread_name_str
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
1789
pico-sensor/McuLib/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c
Normal file
1789
pico-sensor/McuLib/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* portTicks.c
|
||||
*
|
||||
* Created on: 24.04.2019
|
||||
* Author: Erich Styger
|
||||
*/
|
||||
|
||||
#include "FreeRTOSConfig.h"
|
||||
#include "portTicks.h"
|
||||
|
||||
/* --------------------------------------------------- */
|
||||
/* macros dealing with tick counter */
|
||||
#if configSYSTICK_USE_LOW_POWER_TIMER
|
||||
#if !McuLib_CONFIG_PEX_SDK_USED
|
||||
/*! \todo */
|
||||
#define LPTMR0_BASE_PTR LPTMR0 /* low power timer address base */
|
||||
#define configLOW_POWER_TIMER_VECTOR_NUMBER LPTMR0_IRQn /* low power timer IRQ number */
|
||||
#define ENABLE_TICK_COUNTER() LPTMR_StartTimer(LPTMR0_BASE_PTR); LPTMR_EnableInterrupts(LPTMR0_BASE_PTR, kLPTMR_TimerInterruptEnable)
|
||||
#define DISABLE_TICK_COUNTER() LPTMR_StopTimer(LPTMR0_BASE_PTR)
|
||||
#define RESET_TICK_COUNTER_VAL() LPTMR_StopTimer(LPTMR0_BASE_PTR); LPTMR_DisableInterrupts(LPTMR0_BASE_PTR, kLPTMR_TimerInterruptEnable)
|
||||
#define ACKNOWLEDGE_TICK_ISR() LPTMR_ClearStatusFlags(LPTMR0_BASE_PTR, kLPTMR_TimerCompareFlag);
|
||||
#elif McuLib_CONFIG_SDK_VERSION_USED == McuLib_CONFIG_SDK_PROCESSOR_EXPERT
|
||||
#define ENABLE_TICK_COUNTER() LPTMR_PDD_EnableDevice(LPTMR0_BASE_PTR, PDD_ENABLE); LPTMR_PDD_EnableInterrupt(LPTMR0_BASE_PTR)
|
||||
#define DISABLE_TICK_COUNTER() LPTMR_PDD_EnableDevice(LPTMR0_BASE_PTR, PDD_DISABLE); LPTMR_PDD_DisableInterrupt(LPTMR0_BASE_PTR)
|
||||
#define RESET_TICK_COUNTER_VAL() DISABLE_TICK_COUNTER() /* CNR is reset when the LPTMR is disabled or counter register overflows */
|
||||
#define ACKNOWLEDGE_TICK_ISR() LPTMR_PDD_ClearInterruptFlag(LPTMR0_BASE_PTR)
|
||||
#if defined(LDD_ivIndex_INT_LPTimer) /* Earlier version of Processor Expert use this vector name */
|
||||
#define configLOW_POWER_TIMER_VECTOR_NUMBER LDD_ivIndex_INT_LPTimer
|
||||
#elif defined(LDD_ivIndex_INT_LPTMR0) /* Newer versions (Processor Expert for Kinetis v3.0.1 uses this name */
|
||||
#define configLOW_POWER_TIMER_VECTOR_NUMBER LDD_ivIndex_INT_LPTMR0
|
||||
#else
|
||||
#error "Unknown Low Power Timer Interrupt Number?"
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#define ENABLE_TICK_COUNTER() portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT
|
||||
#define DISABLE_TICK_COUNTER() portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT
|
||||
#define RESET_TICK_COUNTER_VAL() portNVIC_SYSTICK_CURRENT_VALUE_REG = 0 /*portNVIC_SYSTICK_LOAD_REG*/
|
||||
#define ACKNOWLEDGE_TICK_ISR() /* not needed */
|
||||
#endif
|
||||
|
||||
typedef unsigned long TickCounter_t; /* enough for 24 bit Systick */
|
||||
#if configSYSTICK_USE_LOW_POWER_TIMER
|
||||
#define TICK_NOF_BITS 16
|
||||
#define COUNTS_UP 1 /* LPTMR is counting up */
|
||||
#if !McuLib_CONFIG_PEX_SDK_USED
|
||||
#define SET_TICK_DURATION(val) LPTMR_SetTimerPeriod(LPTMR0_BASE_PTR, val);
|
||||
#define GET_TICK_DURATION() LPTMR0_BASE_PTR->CNR /*! \todo SDK has no access method for this */
|
||||
#define GET_TICK_CURRENT_VAL(addr) *(addr)=LPTMR_GetCurrentTimerCount(LPTMR0_BASE_PTR)
|
||||
#else
|
||||
#define SET_TICK_DURATION(val) LPTMR_PDD_WriteCompareReg(LPTMR0_BASE_PTR, val)
|
||||
#define GET_TICK_DURATION() LPTMR_PDD_ReadCompareReg(LPTMR0_BASE_PTR)
|
||||
#define GET_TICK_CURRENT_VAL(addr) *(addr)=LPTMR_PDD_ReadCounterReg(LPTMR0_BASE_PTR)
|
||||
#endif
|
||||
#else
|
||||
#define TICK_NOF_BITS 24
|
||||
#define COUNTS_UP 0 /* SysTick is counting down to zero */
|
||||
#define SET_TICK_DURATION(val) portNVIC_SYSTICK_LOAD_REG = val
|
||||
#define GET_TICK_DURATION() portNVIC_SYSTICK_LOAD_REG
|
||||
#define GET_TICK_CURRENT_VAL(addr) *(addr)=portNVIC_SYSTICK_CURRENT_VALUE_REG
|
||||
#endif
|
||||
|
||||
#if configUSE_TICKLESS_IDLE
|
||||
#define UL_TIMER_COUNTS_FOR_ONE_TICK ((TickCounter_t)(TIMER_COUNTS_FOR_ONE_TICK))
|
||||
#if configCPU_FAMILY_IS_ARM(configCPU_FAMILY)
|
||||
#define TICKLESS_DISABLE_INTERRUPTS() __asm volatile("cpsid i") /* disable interrupts. Note that the wfi (wait for interrupt) instruction later will still be able to wait for interrupts! */
|
||||
#define TICKLESS_ENABLE_INTERRUPTS() __asm volatile("cpsie i") /* re-enable interrupts. */
|
||||
#elif (configCPU_FAMILY==configCPU_FAMILY_S08) || (configCPU_FAMILY==configCPU_FAMILY_S12)
|
||||
#define TICKLESS_DISABLE_INTERRUPTS() __asm("sei"); /* disable interrupts */
|
||||
#define TICKLESS_ENABLE_INTERRUPTS() __asm("cli"); /* re-enable interrupts */
|
||||
#else
|
||||
#define TICKLESS_DISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() /* this disables interrupts! Make sure they are re-enabled in vOnPreSleepProcessing()! */
|
||||
#define TICKLESS_ENABLE_INTERRUPTS() portENABLE_INTERRUPTS() /* re-enable interrupts */
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#if configSYSTICK_USE_LOW_POWER_TIMER
|
||||
/* using Low Power Timer */
|
||||
#if CONFIG_PEX_SDK_USEDMcuLib_CONFIG_PEX_SDK_USED
|
||||
#define LPTMR_CSR_TCF_MASK 0x80u
|
||||
#define TICK_INTERRUPT_HAS_FIRED() (LPTMR0_BASE_PTR->CSR&LPTMR_CSR_TCF_MASK)!=0/*! \todo */ /* returns TRUE if tick interrupt had fired */
|
||||
#else
|
||||
#define TICK_INTERRUPT_HAS_FIRED() (LPTMR_PDD_GetInterruptFlag(LPTMR0_BASE_PTR)!=0) /* returns TRUE if tick interrupt had fired */
|
||||
#endif
|
||||
#define TICK_INTERRUPT_FLAG_RESET() /* not needed */
|
||||
#define TICK_INTERRUPT_FLAG_SET() /* not needed */
|
||||
#else
|
||||
/* using directly SysTick Timer */
|
||||
#define TICK_INTERRUPT_HAS_FIRED() ((portNVIC_SYSTICK_CTRL_REG&portNVIC_SYSTICK_COUNT_FLAG_BIT)!=0) /* returns TRUE if tick interrupt had fired */
|
||||
#define TICK_INTERRUPT_FLAG_RESET() /* not needed */
|
||||
#define TICK_INTERRUPT_FLAG_SET() /* not needed */
|
||||
#endif
|
||||
#else
|
||||
/* using global variable to find out if interrupt has fired */
|
||||
volatile uint8_t portTickCntr; /* used to find out if we woke up by the tick interrupt */
|
||||
#define TICK_INTERRUPT_HAS_FIRED() (portTickCntr!=0) /* returns TRUE if tick interrupt had fired */
|
||||
#define TICK_INTERRUPT_FLAG_RESET() portTickCntr=0
|
||||
#define TICK_INTERRUPT_FLAG_SET() portTickCntr=1
|
||||
#endif
|
||||
#endif /* configUSE_TICKLESS_IDLE == 1 */
|
||||
|
||||
#if (configCPU_FAMILY==configCPU_FAMILY_CF1) || (configCPU_FAMILY==configCPU_FAMILY_CF2)
|
||||
#define portINITIAL_FORMAT_VECTOR ((portSTACK_TYPE)0x4000)
|
||||
#define portINITIAL_STATUS_REGISTER ((portSTACK_TYPE)0x2000) /* Supervisor mode set. */
|
||||
#endif
|
||||
|
||||
#if configCPU_FAMILY_IS_ARM(configCPU_FAMILY)
|
||||
|
||||
/* For strict compliance with the Cortex-M spec the task start address should
|
||||
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
|
||||
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
||||
|
||||
/* Constants required to manipulate the core.
|
||||
* SysTick register: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0662b/CIAGECDD.html
|
||||
* Registers first...
|
||||
*/
|
||||
#define portNVIC_SYSTICK_CTRL_REG (*((volatile unsigned long *)0xe000e010)) /* SYST_CSR, SysTick Control and Status Register */
|
||||
#define portNVIC_SYSTICK_LOAD_REG (*((volatile unsigned long *)0xe000e014)) /* SYST_RVR, SysTick reload value register */
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE_REG (*((volatile unsigned long *)0xe000e018)) /* SYST_CVR, SysTick current value register */
|
||||
#define portNVIC_SYSTICK_CALIB_VALUE_REG (*((volatile unsigned long *)0xe000e01C)) /* SYST_CALIB, SysTick calibration value register */
|
||||
/* ...then bits in the registers. */
|
||||
#define portNVIC_SYSTICK_COUNT_FLAG_BIT (1UL<<16UL) /* returns 1 if timer counted to 0 since the last read of the register */
|
||||
#if configSYSTICK_USE_CORE_CLOCK
|
||||
#define portNVIC_SYSTICK_CLK_BIT (1UL<<2UL) /* clock source. 1: core clock, 0: external reference clock */
|
||||
#else
|
||||
#define portNVIC_SYSTICK_CLK_BIT (0UL<<2UL) /* clock source. 1: core clock, 0: external reference clock */
|
||||
#endif
|
||||
#define portNVIC_SYSTICK_INT_BIT (1UL<<1UL) /* SysTick interrupt enable bit */
|
||||
#define portNVIC_SYSTICK_ENABLE_BIT (1UL<<0UL) /* SysTick enable bit */
|
||||
|
||||
#if 0
|
||||
/* Constants required to manipulate the NVIC: */
|
||||
#define portNVIC_INT_CTRL ((volatile unsigned long*)0xe000ed04) /* interrupt control and state register (ICSR) */
|
||||
#define portNVIC_PENDSVSET_BIT (1UL<<28UL) /* bit 28 in portNVIC_INT_CTRL (PENDSVSET), see http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihfaaha.html */
|
||||
#define portNVIC_PENDSVCLEAR_BIT (1UL<<27UL) /* bit 27 in portNVIC_INT_CTRL (PENDSVCLR) */
|
||||
#define portNVIC_PEND_SYSTICK_SET_BIT (1UL<<26UL) /* bit 26 in portNVIC_INT_CTRL (PENDSTSET) */
|
||||
#define portNVIC_PEND_SYSTICK_CLEAR_BIT (1UL<<25UL) /* bit 25 in portNVIC_INT_CTRL (PENDSTCLR) */
|
||||
|
||||
#define portNVIC_SYSPRI2 ((volatile unsigned long*)0xe000ed1c) /* system handler priority register 2 (SHPR2), used for SVCall priority, http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0662b/CIAGECDD.html */
|
||||
#define portNVIC_SVCALL_PRI (((unsigned long)configKERNEL_INTERRUPT_PRIORITY)<<24) /* priority of SVCall interrupt (in portNVIC_SYSPRI2) */
|
||||
|
||||
#define portNVIC_SYSPRI3 ((volatile unsigned long*)0xe000ed20) /* system handler priority register 3 (SHPR3), used for SysTick and PendSV priority, http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0662b/CIAGECDD.html */
|
||||
#define portNVIC_SYSTICK_PRI (((unsigned long)configKERNEL_INTERRUPT_PRIORITY)<<24) /* priority of SysTick interrupt (in portNVIC_SYSPRI3) */
|
||||
#define portNVIC_PENDSV_PRI (((unsigned long)configKERNEL_INTERRUPT_PRIORITY)<<16) /* priority of PendableService interrupt (in portNVIC_SYSPRI3) */
|
||||
|
||||
#define portNVIC_SYSPRI7 ((volatile unsigned long*)0xe000e41c) /* system handler priority register 7, PRI_28 is LPTMR */
|
||||
#define portNVIC_LP_TIMER_PRI (((unsigned long)configKERNEL_INTERRUPT_PRIORITY)<<0) /* priority of low power timer interrupt */
|
||||
#endif
|
||||
|
||||
#if configSYSTICK_USE_LOW_POWER_TIMER && McuLib_CONFIG_SDK_VERSION_USED == McuLib_CONFIG_SDK_PROCESSOR_EXPERT
|
||||
#define IRQn_Type int
|
||||
#define __NVIC_PRIO_BITS configPRIO_BITS
|
||||
#define __O volatile /*!< Defines 'write only' permissions */
|
||||
#define __IO volatile /*!< Defines 'read / write' permissions */
|
||||
/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
|
||||
*/
|
||||
#if configCPU_FAMILY_IS_ARM_M4_M7(configCPU_FAMILY) || configCPU_FAMILY_IS_ARM_M33(configCPU_FAMILY) /* ARM M4(F)/M7/M33 core */
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
|
||||
uint32_t RESERVED0[24];
|
||||
__IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
|
||||
uint32_t RSERVED1[24];
|
||||
__IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
|
||||
uint32_t RESERVED2[24];
|
||||
__IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
|
||||
uint32_t RESERVED3[24];
|
||||
__IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
|
||||
uint32_t RESERVED4[56];
|
||||
__IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
|
||||
uint32_t RESERVED5[644];
|
||||
__O uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
|
||||
} NVIC_Type;
|
||||
#else /* M0+ */
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t ISER[1]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
|
||||
uint32_t RESERVED0[31];
|
||||
__IO uint32_t ICER[1]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
|
||||
uint32_t RSERVED1[31];
|
||||
__IO uint32_t ISPR[1]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
|
||||
uint32_t RESERVED2[31];
|
||||
__IO uint32_t ICPR[1]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
|
||||
uint32_t RESERVED3[31];
|
||||
uint32_t RESERVED4[64];
|
||||
__IO uint32_t IP[8]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
|
||||
} NVIC_Type;
|
||||
#endif
|
||||
|
||||
/* Memory mapping of Cortex-M0+ Hardware */
|
||||
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
|
||||
#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
|
||||
#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
|
||||
|
||||
/* Interrupt Priorities are WORD accessible only under ARMv6M */
|
||||
/* The following MACROS handle generation of the register offset and byte masks */
|
||||
#define _BIT_SHIFT(IRQn) ( (((uint32_t)(IRQn) ) & 0x03) * 8 )
|
||||
#define _IP_IDX(IRQn) ( ((uint32_t)(IRQn) >> 2) )
|
||||
|
||||
/** \brief Set Interrupt Priority
|
||||
The function sets the priority of an interrupt.
|
||||
\note The priority cannot be set for every core interrupt.
|
||||
\param [in] IRQn Interrupt number.
|
||||
\param [in] priority Priority to set.
|
||||
*/
|
||||
static void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) {
|
||||
IRQn -= 16; /* PEx starts numbers with zero, while system interrupts would be negative */
|
||||
#if configCPU_FAMILY_IS_ARM_M4_M7(configCPU_FAMILY) || configCPU_FAMILY_IS_ARM_M33(configCPU_FAMILY) /* ARM M4(F)/M7/M33 core */
|
||||
NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); /* set Priority for device specific Interrupts */
|
||||
#else /* M0+ */
|
||||
NVIC->IP[_IP_IDX(IRQn)] = (NVIC->IP[_IP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |
|
||||
(((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); /* set Priority for device specific Interrupts */
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \brief Enable External Interrupt
|
||||
The function enables a device-specific interrupt in the NVIC interrupt controller.
|
||||
\param [in] IRQn External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
static void NVIC_EnableIRQ(IRQn_Type IRQn) {
|
||||
IRQn -= 16; /* PEx starts numbers with zero, while system interrupts would be negative */
|
||||
#if configCPU_FAMILY_IS_ARM_M4_M7(configCPU_FAMILY) || configCPU_FAMILY_IS_ARM_M33(configCPU_FAMILY) /* ARM M4(F)/M7/M33 core */
|
||||
NVIC->ISER[(uint32_t)((int32_t)IRQn) >> 5] = (uint32_t)(1 << ((uint32_t)((int32_t)IRQn) & (uint32_t)0x1F)); /* enable interrupt */
|
||||
#else /* M0+ */
|
||||
NVIC->ISER[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */
|
||||
#endif
|
||||
}
|
||||
#endif /* configSYSTICK_USE_LOW_POWER_TIMER */
|
||||
|
||||
#endif /* #if configCPU_FAMILY_IS_ARM(configCPU_FAMILY) */
|
||||
|
||||
//void vPortStopTickTimer(void) {
|
||||
// DISABLE_TICK_COUNTER();
|
||||
//}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTTICKS_H_
|
||||
#define PORTTICKS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Interface header file to the Processor Expert Tick counter.
|
||||
* This file is used to access the interface, especially for performance
|
||||
* counters (e.g. for Percepio Trace).
|
||||
* That way the a module can interface this wrapper header file instead
|
||||
* of one of the standard FreeRTOS header files.
|
||||
*/
|
||||
#include "McuLib.h" /* include SDK and API used */
|
||||
|
||||
#include "FreeRTOSConfig.h"
|
||||
#include "portmacro.h"
|
||||
|
||||
#if !McuLib_CONFIG_PEX_SDK_USED
|
||||
extern uint32_t SystemCoreClock; /* in Kinetis SDK, this contains the system core clock speed */
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief Return the tick raw counter value. It is assumed that the counter register has been reset at the last tick time
|
||||
* \return Tick counter value. The value is reset at tick interrupt time.
|
||||
* */
|
||||
uint32_t uxGetTickCounterValue(void);
|
||||
|
||||
#if configSYSTICK_USE_LOW_POWER_TIMER
|
||||
#define FREERTOS_HWTC_DOWN_COUNTER 0 /* LPTM is counting up */
|
||||
#define FREERTOS_HWTC_PERIOD ((1000/configSYSTICK_LOW_POWER_TIMER_CLOCK_HZ)-1UL) /* counter is incrementing from zero to this value */
|
||||
#else
|
||||
#define FREERTOS_HWTC_DOWN_COUNTER 1 /* SysTick is counting down */
|
||||
#define FREERTOS_HWTC_PERIOD ((configCPU_CLOCK_HZ/configTICK_RATE_HZ)-1UL) /* counter is decrementing from this value to zero */
|
||||
#endif
|
||||
|
||||
#if configUSE_TICKLESS_IDLE == 1
|
||||
extern volatile uint8_t portTickCntr; /* used to find out if we woke up by the tick interrupt */
|
||||
#endif
|
||||
|
||||
#define FREERTOS_HWTC_FREQ_HZ configTICK_RATE_HZ
|
||||
|
||||
#if configUSE_PERCEPIO_TRACE_HOOKS /* using Percepio Trace */
|
||||
#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_PROCESSOR_EXPERT)
|
||||
/* tick information for Percepio Trace */
|
||||
|
||||
/* undefine previous values, where dummy anyway: make sure this header file is included last! */
|
||||
#undef TRC_HWTC_COUNT_DIRECTION
|
||||
#undef TRC_HWTC_PERIOD
|
||||
#undef TRC_HWTC_DIVISOR
|
||||
#undef TRC_HWTC_COUNT
|
||||
|
||||
#if FREERTOS_HWTC_DOWN_COUNTER
|
||||
#define TRC_HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
|
||||
#define TRC_HWTC_PERIOD FREERTOS_HWTC_PERIOD /* counter is decrementing from this value to zero */
|
||||
#else
|
||||
#define TRC_HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
|
||||
#define TRC_HWTC_PERIOD FREERTOS_HWTC_PERIOD /* counter is incrementing from zero to this value */
|
||||
#endif
|
||||
|
||||
#if configCPU_FAMILY_IS_ARM(configCPU_FAMILY)
|
||||
#if configSYSTICK_USE_LOW_POWER_TIMER
|
||||
#define TRC_HWTC_DIVISOR 1 /* divisor for slow counter tick value */
|
||||
#else
|
||||
#define TRC_HWTC_DIVISOR 2 /* divisor for fast counter tick value */
|
||||
#endif
|
||||
#else
|
||||
#define TRC_HWTC_DIVISOR 1
|
||||
#endif
|
||||
|
||||
#define TRC_HWTC_COUNT (uxGetTickCounterValue())
|
||||
#define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR
|
||||
#define TRC_IRQ_PRIORITY_ORDER 0 /* 0: lower IRQ prios mean higher priority, 1: otherwise */
|
||||
#define TRC_HWTC_FREQ_HZ FREERTOS_HWTC_FREQ_HZ
|
||||
#endif
|
||||
#endif /* configUSE_PERCEPIO_TRACE_HOOKS */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTTICKS_H_ */
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/* file is intentionally empty as not needed for this GNU gcc FreeRTOS port */
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,630 @@
|
||||
#include "McuLibconfig.h"
|
||||
#if McuLib_CONFIG_CPU_VARIANT==McuLib_CONFIG_CPU_VARIANT_RP2040 && (configNUMBER_OF_CORES == 2)
|
||||
#include "rp2040_portmacro.h"
|
||||
#else
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "FreeRTOSConfig.h"
|
||||
#include "projdefs.h" /* for pdFALSE, pdTRUE */
|
||||
|
||||
void vPortStopTickTimer(void);
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
#ifdef __GNUC__ /* << EST: 'used' attribute need for LTO (Link Time Optimization) */
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
#else
|
||||
#define portDONT_DISCARD /* nothing */
|
||||
#endif
|
||||
|
||||
#ifndef configENABLE_FPU
|
||||
#error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU.
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
#ifndef configENABLE_MPU
|
||||
#error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU.
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#ifndef configENABLE_TRUSTZONE
|
||||
#error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#if (configCOMPILER==configCOMPILER_S12_FSL) || (configCOMPILER==configCOMPILER_S08_FSL)
|
||||
/* disabling some warnings as the RTOS sources are not that clean... */
|
||||
#pragma MESSAGE DISABLE C5909 /* assignment in condition */
|
||||
#pragma MESSAGE DISABLE C2705 /* possible loss of data */
|
||||
#pragma MESSAGE DISABLE C5905 /* multiplication with one */
|
||||
#pragma MESSAGE DISABLE C5904 /* division by one */
|
||||
#pragma MESSAGE DISABLE C5660 /* removed dead code */
|
||||
#pragma MESSAGE DISABLE C5917 /* removed dead assignment */
|
||||
#pragma MESSAGE DISABLE C4001 /* condition always FALSE */
|
||||
#endif
|
||||
#if configCOMPILER==configCOMPILER_S12_FSL
|
||||
#pragma MESSAGE DISABLE C12053 /* SP change not in debug information */
|
||||
#pragma MESSAGE DISABLE C12056 /* SP debug information incorrect */
|
||||
#endif
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#if (configCPU_FAMILY==configCPU_FAMILY_CF1) || (configCPU_FAMILY==configCPU_FAMILY_CF2) || configCPU_FAMILY_IS_ARM(configCPU_FAMILY) || (configCPU_FAMILY==configCPU_FAMILY_DSC)
|
||||
#define portSTACK_TYPE unsigned long
|
||||
#elif (configCPU_FAMILY==configCPU_FAMILY_S08) || (configCPU_FAMILY==configCPU_FAMILY_S12)
|
||||
#define portSTACK_TYPE unsigned char
|
||||
#endif
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
|
||||
#define portUSE_CUSTOM_BASE_TYPE 0 /* 1: use custom base type */
|
||||
|
||||
#if portUSE_CUSTOM_BASE_TYPE
|
||||
#define portBASE_TYPE char /* custom port base type */
|
||||
typedef portBASE_TYPE BaseType_t;
|
||||
typedef unsigned portBASE_TYPE UBaseType_t;
|
||||
#elif (configCPU_FAMILY==configCPU_FAMILY_CF1) || (configCPU_FAMILY==configCPU_FAMILY_CF2) || configCPU_FAMILY_IS_ARM(configCPU_FAMILY) || (configCPU_FAMILY==configCPU_FAMILY_DSC)
|
||||
#define portBASE_TYPE long
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
#elif (configCPU_FAMILY==configCPU_FAMILY_S08) || (configCPU_FAMILY==configCPU_FAMILY_S12)
|
||||
#define portBASE_TYPE char
|
||||
typedef signed char BaseType_t;
|
||||
typedef unsigned char UBaseType_t;
|
||||
#endif
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY (TickType_t)0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY (TickType_t)0xffffffff
|
||||
|
||||
#if (configCPU_FAMILY==configCPU_FAMILY_CF1) || (configCPU_FAMILY==configCPU_FAMILY_CF2) || configCPU_FAMILY_IS_ARM(configCPU_FAMILY)
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif /* 32bit architecture */
|
||||
|
||||
#endif
|
||||
|
||||
#if (configNUMBER_OF_CORES == 2) /* dummy entries for other cores */
|
||||
#define portGET_CORE_ID() 0
|
||||
#define portYIELD_CORE(x) vPortYieldFromISR()
|
||||
|
||||
#define portGET_TASK_LOCK() /* empty */
|
||||
#define portRELEASE_TASK_LOCK() /* empty */
|
||||
|
||||
#define portGET_ISR_LOCK() /* empty */
|
||||
#define portRELEASE_ISR_LOCK() /* empty */
|
||||
|
||||
#define portENTER_CRITICAL_FROM_ISR() vTaskEnterCriticalFromISR()
|
||||
#define portEXIT_CRITICAL_FROM_ISR(x) vTaskExitCriticalFromISR(x)
|
||||
|
||||
/* Critical nesting count management. */
|
||||
extern UBaseType_t uxCriticalNestings[ configNUMBER_OF_CORES ];
|
||||
#define portGET_CRITICAL_NESTING_COUNT() ( uxCriticalNestings[ portGET_CORE_ID() ] )
|
||||
#define portSET_CRITICAL_NESTING_COUNT( x ) ( uxCriticalNestings[ portGET_CORE_ID() ] = ( x ) )
|
||||
#define portINCREMENT_CRITICAL_NESTING_COUNT() ( uxCriticalNestings[ portGET_CORE_ID() ]++ )
|
||||
#define portDECREMENT_CRITICAL_NESTING_COUNT() ( uxCriticalNestings[ portGET_CORE_ID() ]-- )
|
||||
|
||||
#endif
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize );
|
||||
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* PRIVILEGED_FUNCTION */;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
|
||||
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/**
|
||||
* @brief MPU specific constants.
|
||||
*/
|
||||
#if( configENABLE_MPU == 1 )
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
#else
|
||||
#define portPRIVILEGE_BIT ( 0x0UL )
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if configENABLE_MPU
|
||||
/*-----------------------------------------------------------*/
|
||||
/* MPU specific constants. */
|
||||
|
||||
#define portMPU_REGION_READ_WRITE ( 0x03UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
|
||||
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
|
||||
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 2UL )
|
||||
#define portGENERAL_PERIPHERALS_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
|
||||
#define portSWITCH_TO_USER_MODE() __asm volatile ( " mrs r0, control \n orr r0, #1 \n msr control, r0 " :::"r0" )
|
||||
|
||||
typedef struct MPU_REGION_REGISTERS
|
||||
{
|
||||
uint32_t ulRegionBaseAddress;
|
||||
uint32_t ulRegionAttribute;
|
||||
} xMPU_REGION_REGISTERS;
|
||||
|
||||
/* Plus 1 to create space for the stack region. */
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS ];
|
||||
} xMPU_SETTINGS;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if configENABLE_MPU /* check values for LPC55xx! */
|
||||
/* Devices Region. */
|
||||
#define portDEVICE_REGION_START_ADDRESS ( 0x50000000 )
|
||||
#define portDEVICE_REGION_END_ADDRESS ( 0x5FFFFFFF )
|
||||
|
||||
/* Device memory attributes used in MPU_MAIR registers.
|
||||
*
|
||||
* 8-bit values encoded as follows:
|
||||
* Bit[7:4] - 0000 - Device Memory
|
||||
* Bit[3:2] - 00 --> Device-nGnRnE
|
||||
* 01 --> Device-nGnRE
|
||||
* 10 --> Device-nGRE
|
||||
* 11 --> Device-GRE
|
||||
* Bit[1:0] - 00, Reserved.
|
||||
*/
|
||||
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
|
||||
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
|
||||
|
||||
/* Normal memory attributes used in MPU_MAIR registers. */
|
||||
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */
|
||||
#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
|
||||
|
||||
/* Attributes used in MPU_RBAR registers. */
|
||||
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
|
||||
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
|
||||
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
|
||||
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
|
||||
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
|
||||
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 1UL )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Settings to define an MPU region.
|
||||
*/
|
||||
typedef struct MPURegionSettings
|
||||
{
|
||||
uint32_t ulRBAR; /**< RBAR for the region. */
|
||||
uint32_t ulRLAR; /**< RLAR for the region. */
|
||||
} MPURegionSettings_t;
|
||||
|
||||
/**
|
||||
* @brief MPU settings as stored in the TCB.
|
||||
*/
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */
|
||||
MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
|
||||
} xMPU_SETTINGS;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief SVC numbers.
|
||||
*/
|
||||
#define portSVC_ALLOCATE_SECURE_CONTEXT 0
|
||||
#define portSVC_FREE_SECURE_CONTEXT 1
|
||||
#define portSVC_START_SCHEDULER 2
|
||||
#define portSVC_RAISE_PRIVILEGE 3
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
/* Hardware specifics. */
|
||||
#if (configCPU_FAMILY==configCPU_FAMILY_CF1) || (configCPU_FAMILY==configCPU_FAMILY_CF2)
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portSTACK_GROWTH -1 /* stack grows from HIGH to LOW */
|
||||
#elif configCPU_FAMILY_IS_ARM(configCPU_FAMILY)
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portSTACK_GROWTH -1 /* stack grows from HIGH to LOW */
|
||||
#elif (configCPU_FAMILY==configCPU_FAMILY_S08) || (configCPU_FAMILY==configCPU_FAMILY_S12)
|
||||
#define portBYTE_ALIGNMENT 1
|
||||
#define portSTACK_GROWTH -1 /* stack grows from HIGH to LOW */
|
||||
#elif (configCPU_FAMILY==configCPU_FAMILY_DSC)
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portSTACK_GROWTH 1 /* stack grows from LOW to HIGH */
|
||||
#endif
|
||||
|
||||
#define portTICK_PERIOD_MS ((TickType_t)1000/configTICK_RATE_HZ)
|
||||
/*-----------------------------------------------------------*/
|
||||
/* Critical section management. */
|
||||
unsigned long ulPortSetIPL(unsigned portLONG);
|
||||
|
||||
/* If set to 1, then this port uses the critical nesting count from the TCB rather than
|
||||
maintaining a separate value and then saving this value in the task stack. */
|
||||
#define portCRITICAL_NESTING_IN_TCB 0
|
||||
|
||||
|
||||
extern unsigned portBASE_TYPE uxPortSetInterruptMaskFromISR(void);
|
||||
extern void vPortClearInterruptMaskFromISR(unsigned portBASE_TYPE);
|
||||
|
||||
|
||||
#if configCOMPILER==configCOMPILER_DSC_FSL
|
||||
/* for DSC, there is a possible skew after enable/disable Interrupts. */
|
||||
#define portPOST_ENABLE_DISABLE_INTERRUPTS() \
|
||||
asm(nop); asm(nop); asm(nop); asm(nop); asm(nop); asm(nop);
|
||||
#else
|
||||
#define portPOST_ENABLE_DISABLE_INTERRUPTS() /* nothing special needed */
|
||||
#endif
|
||||
|
||||
#if configCPU_FAMILY_IS_ARM_M4_M7(configCPU_FAMILY) || configCPU_FAMILY_IS_ARM_M33(configCPU_FAMILY) /* Cortex M4/M7/M33 */
|
||||
#if (configCOMPILER==configCOMPILER_ARM_KEIL)
|
||||
__asm uint32_t ulPortSetInterruptMask(void);
|
||||
__asm void vPortClearInterruptMask(uint32_t ulNewMask);
|
||||
|
||||
#define portSET_INTERRUPT_MASK() ulPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK(x) vPortClearInterruptMask(x)
|
||||
#elif (configCOMPILER==configCOMPILER_ARM_GCC)
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
|
||||
#define portSET_INTERRUPT_MASK() ulPortRaiseBASEPRI()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
|
||||
#define portCLEAR_INTERRUPT_MASK(x) vPortSetBASEPRI(x)
|
||||
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
|
||||
#define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#elif (configCOMPILER==configCOMPILER_ARM_IAR) /* IAR */ || (configCOMPILER==configCOMPILER_ARM_FSL) /* legacy FSL ARM Compiler */
|
||||
void vPortSetInterruptMask(void); /* prototype, implemented in portasm.s */
|
||||
void vPortClearInterruptMask(void); /* prototype, implemented in portasm.s */
|
||||
#define portSET_INTERRUPT_MASK() vPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK(x) vPortClearInterruptMask(x)
|
||||
#else
|
||||
#error "unknown compiler?"
|
||||
#endif
|
||||
#elif configCPU_FAMILY_IS_ARM_M0(configCPU_FAMILY) /* Cortex-M0+ */
|
||||
#if configCOMPILER==configCOMPILER_ARM_KEIL
|
||||
#define portSET_INTERRUPT_MASK() __disable_irq()
|
||||
#define portCLEAR_INTERRUPT_MASK(x) __enable_irq()
|
||||
#else /* IAR, CW ARM or GNU ARM gcc */
|
||||
/* Critical section management. */
|
||||
#define portSET_INTERRUPT_MASK() __asm volatile("cpsid i")
|
||||
#define portCLEAR_INTERRUPT_MASK(x) __asm volatile("cpsie i")
|
||||
extern void vPortEnterCritical(void);
|
||||
extern void vPortExitCritical(void);
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() 0;portSET_INTERRUPT_MASK()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) portCLEAR_INTERRUPT_MASK();(void)x
|
||||
#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK()
|
||||
#define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK(0)
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if configCOMPILER==configCOMPILER_ARM_KEIL
|
||||
#define portDISABLE_ALL_INTERRUPTS() __disable_irq()
|
||||
#define portENABLE_ALL_INTERRUPTS() __enable_irq()
|
||||
#else /* IAR, CW ARM or GNU ARM gcc */
|
||||
#define portDISABLE_ALL_INTERRUPTS() __asm volatile("cpsid i")
|
||||
#define portENABLE_ALL_INTERRUPTS() __asm volatile("cpsie i")
|
||||
#endif
|
||||
|
||||
/* There are an uneven number of items on the initial stack, so
|
||||
portALIGNMENT_ASSERT_pxCurrentTCB() will trigger false positive asserts. */
|
||||
#define portALIGNMENT_ASSERT_pxCurrentTCB (void)
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/**
|
||||
* @brief Allocate a secure context for the task.
|
||||
*
|
||||
* Tasks are not created with a secure context. Any task that is going to call
|
||||
* secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a
|
||||
* secure context before it calls any secure function.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the secure stack to be allocated.
|
||||
*/
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
|
||||
|
||||
/**
|
||||
* @brief Called when a task is deleted to delete the task's secure context,
|
||||
* if it has one.
|
||||
*
|
||||
* @param[in] pxTCB The TCB of the task being deleted.
|
||||
*/
|
||||
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
|
||||
#else
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
|
||||
#define portCLEAN_UP_TCB( pxTCB )
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
|
||||
/**
|
||||
* @brief Raise an SVC request to raise privilege.
|
||||
*
|
||||
* The SVC handler checks that the SVC was raised from a system call and only
|
||||
* then it raises the privilege. If this is called from any other place,
|
||||
* the privilege is not raised.
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*/
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
#else
|
||||
#define portIS_PRIVILEGED()
|
||||
#define portRAISE_PRIVILEGE()
|
||||
#define portRESET_PRIVILEGE()
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
/* Scheduler utilities. */
|
||||
|
||||
extern void vPortYieldFromISR(void);
|
||||
#define portYIELD() vPortYieldFromISR()
|
||||
#define portEND_SWITCHING_ISR(xSwitchRequired) { if( xSwitchRequired != pdFALSE ) { traceISR_EXIT_TO_SCHEDULER(); portYIELD(); } else { traceISR_EXIT(); } }
|
||||
#define portYIELD_FROM_ISR(x) portEND_SWITCHING_ISR(x)
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimizations. */
|
||||
#if configCPU_FAMILY_IS_ARM_M4_M7(configCPU_FAMILY)
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
/* Generic helper function. */
|
||||
#if (configCOMPILER==configCOMPILER_ARM_GCC)
|
||||
__attribute__((always_inline)) static inline unsigned char ucPortCountLeadingZeros(unsigned long ulBitmap)
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) );
|
||||
return ucReturn;
|
||||
}
|
||||
#endif
|
||||
/* Check the configuration. */
|
||||
#if( configMAX_PRIORITIES > 32 )
|
||||
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||
#endif
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
#if (configCOMPILER==configCOMPILER_ARM_GCC)
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
#elif (configCOMPILER==configCOMPILER_ARM_KEIL)
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) __clz( ( uxReadyPriorities ) ) )
|
||||
#elif (configCOMPILER==configCOMPILER_ARM_IAR)
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( ( uint32_t ) __CLZ( ( uxReadyPriorities ) ) ) )
|
||||
#endif
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
#endif /* configCPU_FAMILY_IS_ARM_M4_M7 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
#if configCPU_FAMILY_IS_ARM_M4_M7(configCPU_FAMILY) /* ARM M4/M7(F) core */
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#else
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
/* Tickless idle/low power functionality. */
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime);
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP(xExpectedIdleTime) vPortSuppressTicksAndSleep(xExpectedIdleTime)
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters)
|
||||
#define portTASK_FUNCTION(vFunction, pvParameters) void vFunction(void *pvParameters)
|
||||
/*-----------------------------------------------------------*/
|
||||
void vPortStartFirstTask(void);
|
||||
/* starts the first task, called from xPortStartScheduler() */
|
||||
|
||||
void vPortYieldHandler(void);
|
||||
/* handler for the SWI interrupt */
|
||||
|
||||
#if configENABLE_FPU /* has floating point unit */
|
||||
void vPortEnableVFP(void);
|
||||
/* enables floating point support in the CPU */
|
||||
#endif
|
||||
|
||||
/* Prototypes for interrupt service handlers */
|
||||
#if !McuLib_CONFIG_PEX_SDK_USED /* the SDK expects different interrupt handler names */
|
||||
void SVC_Handler(void); /* SVC interrupt handler */
|
||||
void PendSV_Handler(void); /* PendSV interrupt handler */
|
||||
void SysTick_Handler(void); /* Systick interrupt handler */
|
||||
#else
|
||||
void vPortSVCHandler(void); /* SVC interrupt handler */
|
||||
void vPortPendSVHandler(void); /* PendSV interrupt handler */
|
||||
void vPortTickHandler(void); /* Systick interrupt handler */
|
||||
#endif
|
||||
|
||||
#if (configCPU_FAMILY_IS_ARM_M33(configCPU_FAMILY) || configCPU_FAMILY_IS_ARM_M4_M7(configCPU_FAMILY)) && (configCOMPILER==configCOMPILER_ARM_GCC)
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||
#endif
|
||||
|
||||
#if configENABLE_MPU
|
||||
/* Set the privilege level to user mode if xRunningPrivileged is false. */
|
||||
portFORCE_INLINE static void vPortResetPrivilege( BaseType_t xRunningPrivileged )
|
||||
{
|
||||
if( xRunningPrivileged != pdTRUE )
|
||||
{
|
||||
__asm volatile ( " mrs r0, control \n" \
|
||||
" orr r0, #1 \n" \
|
||||
" msr control, r0 \n" \
|
||||
:::"r0" );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
|
||||
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mov %0, %1 \n" \
|
||||
" msr basepri, %0 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
:"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mrs %0, basepri \n" \
|
||||
" mov %1, %2 \n" \
|
||||
" msr basepri, %1 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
:"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
|
||||
/* This return will not be reached but is necessary to prevent compiler
|
||||
warnings. */
|
||||
return ulOriginalBASEPRI;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, %0 " :: "r" ( ulNewMaskValue ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
#endif
|
||||
|
||||
/* << EST needed for PICO-W lwIP, IPSR would be available on M4 too */
|
||||
#define portCHECK_IF_IN_ISR() ({ \
|
||||
uint32_t ulIPSR; \
|
||||
__asm volatile ("mrs %0, IPSR" : "=r" (ulIPSR)::); \
|
||||
((uint8_t)ulIPSR)>0;})
|
||||
|
||||
#if configUSE_TICKLESS_IDLE_DECISION_HOOK /* << EST */
|
||||
BaseType_t configUSE_TICKLESS_IDLE_DECISION_HOOK_NAME(void); /* return pdTRUE if RTOS can enter tickless idle mode, pdFALSE otherwise */
|
||||
#endif
|
||||
|
||||
void prvTaskExitError(void);
|
||||
/* handler to catch task exit errors */
|
||||
|
||||
#if !configGENERATE_RUN_TIME_STATS_USE_TICKS
|
||||
extern void McuRTOS_AppConfigureTimerForRuntimeStats(void);
|
||||
extern uint32_t McuRTOS_AppGetRuntimeCounterValueFromISR(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
readme.txt
|
||||
----------
|
||||
Tasks backtrace switcher/viewer snippet is from the following FreeRTOS Interactive site:
|
||||
http://interactive.freertos.org/entries/23468301-Tasks-backtrace-switcher-viewer-snippet-for-debugger-gcc-gdb-ARM-Cortex-M3-MPU-port-Eclipse-support-
|
||||
|
||||
It generates the following files:
|
||||
- readme_gdbBacktraceDebug.txt (this file)
|
||||
- .gdbinit-FreeRTOS-helpers (GDB script file)
|
||||
|
||||
Usage:
|
||||
- execute GDB script (either manually or in the launch configuration):
|
||||
source .//Generated_Code//.gdbinit-FreeRTOS-helpers
|
||||
- execute
|
||||
freertos_show_threads
|
||||
to show threads with handlers
|
||||
- use
|
||||
freertos_switch_to_task <handle>
|
||||
to show task stack
|
||||
- use
|
||||
freertos_restore_running_context
|
||||
to restore the context before running
|
||||
|
||||
Credits to:
|
||||
- Artem Pisarneko for his initial contribution
|
||||
- Prasana for the PendSVHandler updates
|
||||
- Geoffrey Wossum for the Cortex-M4 contribution
|
||||
|
||||
Link to article:
|
||||
http://mcuoneclipse.com/2015/10/03/freertos-arm-thread-debugging-with-eclipse-and-gdb/
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.4.3
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT AND BSD-3-Clause
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*/
|
||||
|
||||
#ifndef RP2040_CONFIG_H
|
||||
#define RP2040_CONFIG_H
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#include "hardware/sync.h"
|
||||
|
||||
/* configUSE_DYNAMIC_EXCEPTION_HANDLERS == 1 means set the exception handlers dynamically on cores
|
||||
* that need them in case the user has set up distinct vector table offsets per core
|
||||
*/
|
||||
#ifndef configUSE_DYNAMIC_EXCEPTION_HANDLERS
|
||||
#if defined( PICO_NO_RAM_VECTOR_TABLE ) && ( PICO_NO_RAM_VECTOR_TABLE == 1 )
|
||||
#define configUSE_DYNAMIC_EXCEPTION_HANDLERS 0
|
||||
#else
|
||||
#define configUSE_DYNAMIC_EXCEPTION_HANDLERS 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* configSUPPORT_PICO_SYNC_INTEROP == 1 means that SDK pico_sync
|
||||
* sem/mutex/queue etc. will work correctly when called from FreeRTOS tasks
|
||||
*/
|
||||
#ifndef configSUPPORT_PICO_SYNC_INTEROP
|
||||
#if LIB_PICO_SYNC
|
||||
#define configSUPPORT_PICO_SYNC_INTEROP 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* configSUPPORT_PICO_SYNC_INTEROP == 1 means that SDK pico_time
|
||||
* sleep_ms/sleep_us/sleep_until will work correctly when called from FreeRTOS
|
||||
* tasks, and will actually block at the FreeRTOS level
|
||||
*/
|
||||
#ifndef configSUPPORT_PICO_TIME_INTEROP
|
||||
#if LIB_PICO_TIME
|
||||
#define configSUPPORT_PICO_TIME_INTEROP 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
|
||||
/* configTICK_CORE indicates which core should handle the SysTick
|
||||
* interrupts */
|
||||
#ifndef configTICK_CORE
|
||||
#define configTICK_CORE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* This SMP port requires two spin locks, which are claimed from the SDK.
|
||||
* the spin lock numbers to be used are defined statically and defaulted here
|
||||
* to the values nominally set aside for RTOS by the SDK */
|
||||
#ifndef configSMP_SPINLOCK_0
|
||||
#define configSMP_SPINLOCK_0 PICO_SPINLOCK_ID_OS1
|
||||
#endif
|
||||
|
||||
#ifndef configSMP_SPINLOCK_1
|
||||
#define configSMP_SPINLOCK_1 PICO_SPINLOCK_ID_OS2
|
||||
#endif
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* ifndef RP2040_CONFIG_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.4.3
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT AND BSD-3-Clause
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RP2040_PORTMACRO_H
|
||||
#define RP2040_PORTMACRO_H
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#include "pico.h"
|
||||
#include "hardware/sync.h"
|
||||
#include "rp2040_config.h"
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
void vPortStopTickTimer(void); /* << EST */
|
||||
#if 1 /* << EST */
|
||||
#define portDISABLE_ALL_INTERRUPTS() __asm volatile("cpsid i")
|
||||
#define portENABLE_ALL_INTERRUPTS() __asm volatile("cpsie i")
|
||||
#endif
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef int32_t BaseType_t;
|
||||
typedef uint32_t UBaseType_t;
|
||||
|
||||
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#else
|
||||
#error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
|
||||
/* We have to use PICO_DIVIDER_DISABLE_INTERRUPTS as the source of truth rathern than our config,
|
||||
* as our FreeRTOSConfig.h header cannot be included by ASM code - which is what this affects in the SDK */
|
||||
#define portUSE_DIVIDER_SAVE_RESTORE !PICO_DIVIDER_DISABLE_INTERRUPTS
|
||||
#if portUSE_DIVIDER_SAVE_RESTORE
|
||||
#define portSTACK_LIMIT_PADDING 4
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler utilities. */
|
||||
extern void vPortYield( void );
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portYIELD() vPortYield()
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
|
||||
do \
|
||||
{ \
|
||||
if( xSwitchRequired ) \
|
||||
{ \
|
||||
traceISR_EXIT_TO_SCHEDULER(); \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
traceISR_EXIT(); \
|
||||
} \
|
||||
} while( 0 )
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Exception handlers */
|
||||
#if ( configUSE_DYNAMIC_EXCEPTION_HANDLERS == 0 )
|
||||
/* We only need to override the SDK's weak functions if we want to replace them at compile time */
|
||||
#define vPortSVCHandler isr_svcall
|
||||
#define xPortPendSVHandler isr_pendsv
|
||||
#define xPortSysTickHandler isr_systick
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Multi-core */
|
||||
#define portMAX_CORE_COUNT 2
|
||||
|
||||
/* Check validity of number of cores specified in config */
|
||||
#if ( configNUMBER_OF_CORES < 1 || portMAX_CORE_COUNT < configNUMBER_OF_CORES )
|
||||
#error "Invalid number of cores specified in config!"
|
||||
#endif
|
||||
|
||||
#if ( configTICK_CORE < 0 || configTICK_CORE > configNUMBER_OF_CORES )
|
||||
#error "Invalid tick core specified in config!"
|
||||
#endif
|
||||
/* FreeRTOS core id is always zero based, so always 0 if we're running on only one core */
|
||||
#if configNUMBER_OF_CORES == portMAX_CORE_COUNT
|
||||
#define portGET_CORE_ID() get_core_num()
|
||||
#else
|
||||
#define portGET_CORE_ID() 0
|
||||
#endif
|
||||
|
||||
#define portCHECK_IF_IN_ISR() \
|
||||
( { \
|
||||
uint32_t ulIPSR; \
|
||||
__asm volatile ( "mrs %0, IPSR" : "=r" ( ulIPSR )::); \
|
||||
( ( uint8_t ) ulIPSR ) > 0; } )
|
||||
|
||||
void vYieldCore( int xCoreID );
|
||||
#define portYIELD_CORE( a ) vYieldCore( a )
|
||||
#define portRESTORE_INTERRUPTS( ulState ) __asm volatile ( "msr PRIMASK,%0" ::"r" ( ulState ) : )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical nesting count management. */
|
||||
extern UBaseType_t uxCriticalNestings[ configNUMBER_OF_CORES ];
|
||||
#define portGET_CRITICAL_NESTING_COUNT() ( uxCriticalNestings[ portGET_CORE_ID() ] )
|
||||
#define portSET_CRITICAL_NESTING_COUNT( x ) ( uxCriticalNestings[ portGET_CORE_ID() ] = ( x ) )
|
||||
#define portINCREMENT_CRITICAL_NESTING_COUNT() ( uxCriticalNestings[ portGET_CORE_ID() ]++ )
|
||||
#define portDECREMENT_CRITICAL_NESTING_COUNT() ( uxCriticalNestings[ portGET_CORE_ID() ]-- )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
|
||||
#define portSET_INTERRUPT_MASK() \
|
||||
( { \
|
||||
uint32_t ulState; \
|
||||
__asm volatile ( "mrs %0, PRIMASK" : "=r" ( ulState )::); \
|
||||
__asm volatile ( " cpsid i " ::: "memory" ); \
|
||||
ulState; } )
|
||||
|
||||
#define portCLEAR_INTERRUPT_MASK( ulState ) __asm volatile ( "msr PRIMASK,%0" ::"r" ( ulState ) : )
|
||||
|
||||
extern uint32_t ulSetInterruptMaskFromISR( void ) __attribute__( ( naked ) );
|
||||
extern void vClearInterruptMaskFromISR( uint32_t ulMask ) __attribute__( ( naked ) );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMaskFromISR( x )
|
||||
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
|
||||
extern void vPortEnableInterrupts();
|
||||
#define portENABLE_INTERRUPTS() vPortEnableInterrupts()
|
||||
|
||||
#if ( configNUMBER_OF_CORES == 1 )
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#else
|
||||
extern void vTaskEnterCritical( void );
|
||||
extern void vTaskExitCritical( void );
|
||||
extern UBaseType_t vTaskEnterCriticalFromISR( void );
|
||||
extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
|
||||
#define portENTER_CRITICAL() vTaskEnterCritical()
|
||||
#define portEXIT_CRITICAL() vTaskExitCritical()
|
||||
#define portENTER_CRITICAL_FROM_ISR() vTaskEnterCriticalFromISR()
|
||||
#define portEXIT_CRITICAL_FROM_ISR( x ) vTaskExitCriticalFromISR( x )
|
||||
#endif /* if ( configNUMBER_OF_CORES == 1 ) */
|
||||
|
||||
#define portRTOS_SPINLOCK_COUNT 2
|
||||
|
||||
/* Note this is a single method with uxAcquire parameter since we have
|
||||
* static vars, the method is always called with a compile time constant for
|
||||
* uxAcquire, and the compiler should dothe right thing! */
|
||||
static inline void vPortRecursiveLock( uint32_t ulLockNum,
|
||||
spin_lock_t * pxSpinLock,
|
||||
BaseType_t uxAcquire )
|
||||
{
|
||||
static uint8_t ucOwnedByCore[ portMAX_CORE_COUNT ];
|
||||
static uint8_t ucRecursionCountByLock[ portRTOS_SPINLOCK_COUNT ];
|
||||
|
||||
configASSERT( ulLockNum < portRTOS_SPINLOCK_COUNT );
|
||||
uint32_t ulCoreNum = get_core_num();
|
||||
uint32_t ulLockBit = 1u << ulLockNum;
|
||||
configASSERT( ulLockBit < 256u );
|
||||
|
||||
if( uxAcquire )
|
||||
{
|
||||
if( __builtin_expect( !*pxSpinLock, 0 ) )
|
||||
{
|
||||
if( ucOwnedByCore[ ulCoreNum ] & ulLockBit )
|
||||
{
|
||||
configASSERT( ucRecursionCountByLock[ ulLockNum ] != 255u );
|
||||
ucRecursionCountByLock[ ulLockNum ]++;
|
||||
return;
|
||||
}
|
||||
|
||||
while( __builtin_expect( !*pxSpinLock, 0 ) )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
__mem_fence_acquire();
|
||||
configASSERT( ucRecursionCountByLock[ ulLockNum ] == 0 );
|
||||
ucRecursionCountByLock[ ulLockNum ] = 1;
|
||||
ucOwnedByCore[ ulCoreNum ] |= ulLockBit;
|
||||
}
|
||||
else
|
||||
{
|
||||
configASSERT( ( ucOwnedByCore[ ulCoreNum ] & ulLockBit ) != 0 );
|
||||
configASSERT( ucRecursionCountByLock[ ulLockNum ] != 0 );
|
||||
|
||||
if( !--ucRecursionCountByLock[ ulLockNum ] )
|
||||
{
|
||||
ucOwnedByCore[ ulCoreNum ] &= ~ulLockBit;
|
||||
__mem_fence_release();
|
||||
*pxSpinLock = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if ( configNUMBER_OF_CORES == 1 )
|
||||
#define portGET_ISR_LOCK()
|
||||
#define portRELEASE_ISR_LOCK()
|
||||
#define portGET_TASK_LOCK()
|
||||
#define portRELEASE_TASK_LOCK()
|
||||
#else
|
||||
#define portGET_ISR_LOCK() vPortRecursiveLock( 0, spin_lock_instance( configSMP_SPINLOCK_0 ), pdTRUE )
|
||||
#define portRELEASE_ISR_LOCK() vPortRecursiveLock( 0, spin_lock_instance( configSMP_SPINLOCK_0 ), pdFALSE )
|
||||
#define portGET_TASK_LOCK() vPortRecursiveLock( 1, spin_lock_instance( configSMP_SPINLOCK_1 ), pdTRUE )
|
||||
#define portRELEASE_TASK_LOCK() vPortRecursiveLock( 1, spin_lock_instance( configSMP_SPINLOCK_1 ), pdFALSE )
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Tickless idle/low power functionality. */
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
|
||||
#define portNOP()
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.4.3
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_RP2040_SDK_CONFIG_H
|
||||
#define FREERTOS_RP2040_SDK_CONFIG_H
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include "FreeRTOSConfig.h"
|
||||
#include "rp2040_config.h"
|
||||
#ifndef PICO_USE_MALLOC_MUTEX
|
||||
/* malloc needs to be made thread safe */
|
||||
#define PICO_USE_MALLOC_MUTEX 1
|
||||
#endif /* PICO_USE_MALLOC_MUTEX */
|
||||
#if ( configSUPPORT_PICO_SYNC_INTEROP == 1 )
|
||||
/* increase the amount of time it may reasonably take to wake us up */
|
||||
#ifndef PICO_TIME_SLEEP_OVERHEAD_ADJUST_US
|
||||
#define PICO_TIME_SLEEP_OVERHEAD_ADJUST_US 150
|
||||
#endif
|
||||
|
||||
#define lock_owner_id_t uint32_t
|
||||
extern uint32_t ulPortLockGetCurrentOwnerId( void );
|
||||
#define lock_get_caller_owner_id() ulPortLockGetCurrentOwnerId()
|
||||
#define LOCK_INVALID_OWNER_ID ( ( uint32_t ) -1 )
|
||||
|
||||
struct lock_core;
|
||||
#ifndef lock_internal_spin_unlock_with_wait
|
||||
extern void vPortLockInternalSpinUnlockWithWait( struct lock_core * pxLock,
|
||||
uint32_t ulSave );
|
||||
#define lock_internal_spin_unlock_with_wait( lock, save ) vPortLockInternalSpinUnlockWithWait( lock, save )
|
||||
#endif
|
||||
|
||||
#ifndef lock_internal_spin_unlock_with_notify
|
||||
extern void vPortLockInternalSpinUnlockWithNotify( struct lock_core * pxLock,
|
||||
uint32_t save );
|
||||
#define lock_internal_spin_unlock_with_notify( lock, save ) vPortLockInternalSpinUnlockWithNotify( lock, save );
|
||||
#endif
|
||||
|
||||
#ifndef lock_internal_spin_unlock_with_best_effort_wait_or_timeout
|
||||
extern bool xPortLockInternalSpinUnlockWithBestEffortWaitOrTimeout( struct lock_core * pxLock,
|
||||
uint32_t ulSave,
|
||||
absolute_time_t uxUntil );
|
||||
#define lock_internal_spin_unlock_with_best_effort_wait_or_timeout( lock, save, until ) \
|
||||
xPortLockInternalSpinUnlockWithBestEffortWaitOrTimeout( lock, save, until )
|
||||
#endif
|
||||
#endif /* configSUPPORT_PICO_SYNC_INTEROP */
|
||||
|
||||
#if ( configSUPPORT_PICO_TIME_INTEROP == 1 )
|
||||
extern void xPortSyncInternalYieldUntilBefore( absolute_time_t t );
|
||||
#define sync_internal_yield_until_before( t ) xPortSyncInternalYieldUntilBefore( t )
|
||||
#endif /* configSUPPORT_PICO_TIME_INTEROP */
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* ifndef FREERTOS_RP2040_SDK_CONFIG_H */
|
||||
@@ -0,0 +1,5 @@
|
||||
[{000214A0-0000-0000-C000-000000000046}]
|
||||
Prop3=19,11
|
||||
[InternetShortcut]
|
||||
IDList=
|
||||
URL=https://freertos.org/Using-FreeRTOS-on-RISC-V.html
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.2.0
|
||||
* 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 t
|
||||
|
||||
o 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!
|
||||
*/
|
||||
|
||||
/*
|
||||
* The FreeRTOS kernel's RISC-V port is split between the the code that is
|
||||
* common across all currently supported RISC-V chips (implementations of the
|
||||
* RISC-V ISA), and code that tailors the port to a specific RISC-V chip:
|
||||
*
|
||||
* + FreeRTOS\Source\portable\GCC\RISC-V-RV32\portASM.S contains the code that
|
||||
* is common to all currently supported RISC-V chips. There is only one
|
||||
* portASM.S file because the same file is built for all RISC-V target chips.
|
||||
*
|
||||
* + Header files called freertos_risc_v_chip_specific_extensions.h contain the
|
||||
* code that tailors the FreeRTOS kernel's RISC-V port to a specific RISC-V
|
||||
* chip. There are multiple freertos_risc_v_chip_specific_extensions.h files
|
||||
* as there are multiple RISC-V chip implementations.
|
||||
*
|
||||
* !!!NOTE!!!
|
||||
* TAKE CARE TO INCLUDE THE CORRECT freertos_risc_v_chip_specific_extensions.h
|
||||
* HEADER FILE FOR THE CHIP IN USE. This is done using the assembler's (not the
|
||||
* compiler's!) include path. For example, if the chip in use includes a core
|
||||
* local interrupter (CLINT) and does not include any chip specific register
|
||||
* extensions then add the path below to the assembler's include path:
|
||||
* FreeRTOS\Source\portable\GCC\RISC-V-RV32\chip_specific_extensions\RV32I_CLINT_no_extensions
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This freertos_risc_v_chip_specific_extensions.h is for use with Pulpino Ri5cy
|
||||
* devices, developed and tested using the Vega board RV32M1RM.
|
||||
*/
|
||||
|
||||
#ifndef __FREERTOS_RISC_V_EXTENSIONS_H__
|
||||
#define __FREERTOS_RISC_V_EXTENSIONS_H__
|
||||
|
||||
#define portasmHAS_CLINT 0
|
||||
|
||||
#define portasmHANDLE_INTERRUPT SystemIrqHandler /* << EST */
|
||||
|
||||
/* Constants to define the additional registers found on the Pulpino RI5KY. */
|
||||
#define lpstart0 0x7b0
|
||||
#define lpend0 0x7b1
|
||||
#define lpcount0 0x7b2
|
||||
#define lpstart1 0x7b4
|
||||
#define lpend1 0x7b5
|
||||
#define lpcount1 0x7b6
|
||||
|
||||
/* Six additional registers to save and restore, as per the #defines above. */
|
||||
#define portasmADDITIONAL_CONTEXT_SIZE 6 /* Must be even number on 32-bit cores. */
|
||||
|
||||
/* Save additional registers found on the Pulpino. */
|
||||
.macro portasmSAVE_ADDITIONAL_REGISTERS
|
||||
addi sp, sp, -(portasmADDITIONAL_CONTEXT_SIZE * portWORD_SIZE) /* Make room for the additional registers. */
|
||||
csrr t0, lpstart0 /* Load additional registers into accessable temporary registers. */
|
||||
csrr t1, lpend0
|
||||
csrr t2, lpcount0
|
||||
csrr t3, lpstart1
|
||||
csrr t4, lpend1
|
||||
csrr t5, lpcount1
|
||||
sw t0, 1 * portWORD_SIZE( sp )
|
||||
sw t1, 2 * portWORD_SIZE( sp )
|
||||
sw t2, 3 * portWORD_SIZE( sp )
|
||||
sw t3, 4 * portWORD_SIZE( sp )
|
||||
sw t4, 5 * portWORD_SIZE( sp )
|
||||
sw t5, 6 * portWORD_SIZE( sp )
|
||||
.endm
|
||||
|
||||
/* Restore the additional registers found on the Pulpino. */
|
||||
.macro portasmRESTORE_ADDITIONAL_REGISTERS
|
||||
lw t0, 1 * portWORD_SIZE( sp ) /* Load additional registers into accessable temporary registers. */
|
||||
lw t1, 2 * portWORD_SIZE( sp )
|
||||
lw t2, 3 * portWORD_SIZE( sp )
|
||||
lw t3, 4 * portWORD_SIZE( sp )
|
||||
lw t4, 5 * portWORD_SIZE( sp )
|
||||
lw t5, 6 * portWORD_SIZE( sp )
|
||||
csrw lpstart0, t0
|
||||
csrw lpend0, t1
|
||||
csrw lpcount0, t2
|
||||
csrw lpstart1, t3
|
||||
csrw lpend1, t4
|
||||
csrw lpcount1, t5
|
||||
addi sp, sp, (portasmADDITIONAL_CONTEXT_SIZE * portWORD_SIZE )/* Remove space added for additional registers. */
|
||||
.endm
|
||||
|
||||
#endif /* __FREERTOS_RISC_V_EXTENSIONS_H__ */
|
||||
250
pico-sensor/McuLib/FreeRTOS/Source/portable/GCC/RISC-V/port.c
Normal file
250
pico-sensor/McuLib/FreeRTOS/Source/portable/GCC/RISC-V/port.c
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.2.0
|
||||
* 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!
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the RISC-V RV32 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "portmacro.h"
|
||||
|
||||
#ifndef configCLINT_BASE_ADDRESS
|
||||
#warning configCLINT_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a Core Local Interrupter (CLINT) then set configCLINT_BASE_ADDRESS to the CLINT base address. Otherwise set configCLINT_BASE_ADDRESS to 0.
|
||||
#endif
|
||||
|
||||
/* Let the user override the pre-loading of the initial LR with the address of
|
||||
prvTaskExitError() in case it messes up unwinding of the stack in the
|
||||
debugger. */
|
||||
#ifdef configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#else
|
||||
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||
#endif
|
||||
|
||||
/* The stack used by interrupt service routines. Set configISR_STACK_SIZE_WORDS
|
||||
to use a statically allocated array as the interrupt stack. Alternative leave
|
||||
configISR_STACK_SIZE_WORDS undefined and update the linker script so that a
|
||||
linker variable names __freertos_irq_stack_top has the same value as the top
|
||||
of the stack used by main. Using the linker script method will repurpose the
|
||||
stack that was used by main before the scheduler was started for use as the
|
||||
interrupt stack after the scheduler has started. */
|
||||
#ifdef configISR_STACK_SIZE_WORDS
|
||||
static __attribute__ ((aligned(16))) StackType_t xISRStack[ configISR_STACK_SIZE_WORDS ] = { 0 };
|
||||
const StackType_t xISRStackTop = ( StackType_t ) &( xISRStack[ ( configISR_STACK_SIZE_WORDS & ~portBYTE_ALIGNMENT_MASK ) - 1 ] );
|
||||
#else
|
||||
extern const uint32_t __freertos_irq_stack_top[];
|
||||
const StackType_t xISRStackTop = ( StackType_t ) __freertos_irq_stack_top;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Setup the timer to generate the tick interrupts. The implementation in this
|
||||
* file is weak to allow application writers to change the timer used to
|
||||
* generate the tick interrupt.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void ) __attribute__(( weak ));
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Used to program the machine timer compare register. */
|
||||
uint64_t ullNextTime = 0ULL;
|
||||
const uint64_t *pullNextTime = &ullNextTime;
|
||||
#if 0 /* << EST */
|
||||
const uint32_t ulTimerIncrementsForOneTick = ( uint32_t ) ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ); /* Assumes increment won't go over 32-bits. */
|
||||
#else
|
||||
static uint32_t ulTimerIncrementsForOneTick;
|
||||
#endif
|
||||
volatile uint64_t * const pullMachineTimerCompareRegister = ( volatile uint64_t * const ) ( configCLINT_BASE_ADDRESS + 0x4000 );
|
||||
|
||||
/* Set configCHECK_FOR_STACK_OVERFLOW to 3 to add ISR stack checking to task
|
||||
stack checking. A problem in the ISR stack will trigger an assert, not call the
|
||||
stack overflow hook function (because the stack overflow hook is specific to a
|
||||
task stack, not the ISR stack). */
|
||||
#if( configCHECK_FOR_STACK_OVERFLOW > 2 )
|
||||
#warning This path not tested, or even compiled yet.
|
||||
/* Don't use 0xa5 as the stack fill bytes as that is used by the kernerl for
|
||||
the task stacks, and so will legitimately appear in many positions within
|
||||
the ISR stack. */
|
||||
#define portISR_STACK_FILL_BYTE 0xee
|
||||
|
||||
static const uint8_t ucExpectedStackBytes[] = {
|
||||
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
|
||||
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
|
||||
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
|
||||
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
|
||||
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE }; \
|
||||
|
||||
#define portCHECK_ISR_STACK() configASSERT( ( memcmp( ( void * ) xISRStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) == 0 ) )
|
||||
#else
|
||||
/* Define the function away. */
|
||||
#define portCHECK_ISR_STACK()
|
||||
#endif /* configCHECK_FOR_STACK_OVERFLOW > 2 */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configCLINT_BASE_ADDRESS != 0 )
|
||||
|
||||
void vPortSetupTimerInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;
|
||||
volatile uint32_t * const pulTimeHigh = ( volatile uint32_t * const ) ( configCLINT_BASE_ADDRESS + 0xBFFC );
|
||||
volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configCLINT_BASE_ADDRESS + 0xBFF8 );
|
||||
|
||||
do
|
||||
{
|
||||
ulCurrentTimeHigh = *pulTimeHigh;
|
||||
ulCurrentTimeLow = *pulTimeLow;
|
||||
} while( ulCurrentTimeHigh != *pulTimeHigh );
|
||||
|
||||
ullNextTime = ( uint64_t ) ulCurrentTimeHigh;
|
||||
ullNextTime <<= 32ULL;
|
||||
ullNextTime |= ( uint64_t ) ulCurrentTimeLow;
|
||||
ullNextTime += ( uint64_t ) ulTimerIncrementsForOneTick;
|
||||
*pullMachineTimerCompareRegister = ullNextTime;
|
||||
|
||||
/* Prepare the time to use after the next tick interrupt. */
|
||||
ullNextTime += ( uint64_t ) ulTimerIncrementsForOneTick;
|
||||
}
|
||||
|
||||
#endif /* ( configCLINT_BASE_ADDRESS != 0 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
extern void xPortStartFirstTask( void );
|
||||
#if 1 /* << EST */
|
||||
ulTimerIncrementsForOneTick = ( uint32_t ) ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ); /* Assumes increment won't go over 32-bits. */
|
||||
#endif
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
volatile uint32_t mtvec = 0;
|
||||
|
||||
/* Check the least significant two bits of mtvec are 00 - indicating
|
||||
single vector mode. */
|
||||
__asm volatile( "csrr %0, mtvec" : "=r"( mtvec ) );
|
||||
configASSERT( ( mtvec & 0x03UL ) == 0 );
|
||||
|
||||
/* Check alignment of the interrupt stack - which is the same as the
|
||||
stack that was being used by main() prior to the scheduler being
|
||||
started. */
|
||||
configASSERT( ( xISRStackTop & portBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
}
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
/* If there is a CLINT then it is ok to use the default implementation
|
||||
in this file, otherwise vPortSetupTimerInterrupt() must be implemented to
|
||||
configure whichever clock is to be used to generate the tick interrupt. */
|
||||
vPortSetupTimerInterrupt();
|
||||
|
||||
#if( configCLINT_BASE_ADDRESS != 0 )
|
||||
{
|
||||
/* Enable mtime and external interrupts. 1<<7 for timer interrupt, 1<<11
|
||||
for external interrupt. _RB_ What happens here when mtime is not present as
|
||||
with pulpino? */
|
||||
__asm volatile( "csrs mie, %0" :: "r"(0x880) );
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* Enable external interrupts. */
|
||||
__asm volatile( "csrs mie, %0" :: "r"(0x800) );
|
||||
}
|
||||
#endif /* configCLINT_BASE_ADDRESS */
|
||||
|
||||
xPortStartFirstTask();
|
||||
|
||||
/* Should not get here as after calling xPortStartFirstTask() only tasks
|
||||
should be executing. */
|
||||
return pdFAIL;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented. */
|
||||
for( ;; );
|
||||
}
|
||||
|
||||
/* << EST Begin .... */
|
||||
/*-----------------------------------------------------------*/
|
||||
//static void vPortStartTickTimer(void) {
|
||||
//ENABLE_TICK_COUNTER();
|
||||
//}
|
||||
/*-----------------------------------------------------------*/
|
||||
void vPortStopTickTimer(void) {
|
||||
//DISABLE_TICK_COUNTER();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
#include "fsl_clock.h"
|
||||
|
||||
/* At the time of writing, interrupt nesting is not supported, so do not use
|
||||
the default SystemIrqHandler() implementation as that enables interrupts. A
|
||||
version that does not enable interrupts is provided below. THIS INTERRUPT
|
||||
HANDLER IS SPECIFIC TO THE VEGA BOARD WHICH DOES NOT INCLUDE A CLINT! */
|
||||
void SystemIrqHandler(uint32_t mcause) {
|
||||
uint32_t ulInterruptNumber;
|
||||
typedef void ( * irq_handler_t )( void );
|
||||
extern const irq_handler_t isrTable[];
|
||||
|
||||
ulInterruptNumber = mcause & 0x1FUL;
|
||||
|
||||
/* Clear pending flag in EVENT unit .*/
|
||||
EVENT_UNIT->INTPTPENDCLEAR = ( 1U << ulInterruptNumber );
|
||||
|
||||
/* Read back to make sure write finished. */
|
||||
(void)(EVENT_UNIT->INTPTPENDCLEAR);
|
||||
|
||||
/* Now call the real irq handler for ulInterruptNumber */
|
||||
isrTable[ ulInterruptNumber ]();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
void vPortSetupTimerInterrupt( void ) {
|
||||
//extern void SystemSetupSystick(uint32_t tickRateHz, uint32_t intPriority );
|
||||
|
||||
/* No CLINT so use the LPIT (Low Power Interrupt Timer) to generate the tick interrupt. */
|
||||
CLOCK_SetIpSrc(kCLOCK_Lpit0, kCLOCK_IpSrcFircAsync);
|
||||
SystemSetupSystick(configTICK_RATE_HZ, configKERNEL_INTERRUPT_PRIORITY-1);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
void LPIT0_IRQHandler(void) {
|
||||
//BaseType_t xTaskIncrementTick( void );
|
||||
//void vTaskSwitchContext( void );
|
||||
#warning "requires critical section if interrpt nesting is used."
|
||||
|
||||
/* vPortSetupTimerInterrupt() uses LPIT0 to generate the tick interrupt. */
|
||||
if(xTaskIncrementTick() != 0) {
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
LPIT0->MSR = 1U; /* Clear LPIT0 interrupt flag. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* << EST End */
|
||||
|
||||
|
||||
|
||||
396
pico-sensor/McuLib/FreeRTOS/Source/portable/GCC/RISC-V/portASM.S
Normal file
396
pico-sensor/McuLib/FreeRTOS/Source/portable/GCC/RISC-V/portASM.S
Normal file
@@ -0,0 +1,396 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.2.0
|
||||
* 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!
|
||||
*/
|
||||
|
||||
#if __riscv_xlen == 64
|
||||
#error Not implemented yet - change lw to ld, and sw to sd.
|
||||
#define portWORD_SIZE 8
|
||||
#elif __riscv_xlen == 32
|
||||
#define portWORD_SIZE 4
|
||||
#else
|
||||
#error Assembler did not define __riscv_xlen
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The FreeRTOS kernel's RISC-V port is split between the the code that is
|
||||
* common across all currently supported RISC-V chips (implementations of the
|
||||
* RISC-V ISA), and code which tailors the port to a specific RISC-V chip:
|
||||
*
|
||||
* + The code that is common to all RISC-V chips is implemented in
|
||||
* FreeRTOS\Source\portable\GCC\RISC-V-RV32\portASM.S. There is only one
|
||||
* portASM.S file because the same file is used no matter which RISC-V chip is
|
||||
* in use.
|
||||
*
|
||||
* + The code that tailors the kernel's RISC-V port to a specific RISC-V
|
||||
* chip is implemented in freertos_risc_v_chip_specific_extensions.h. There
|
||||
* is one freertos_risc_v_chip_specific_extensions.h that can be used with any
|
||||
* RISC-V chip that both includes a standard CLINT and does not add to the
|
||||
* base set of RISC-V registers. There are additional
|
||||
* freertos_risc_v_chip_specific_extensions.h files for RISC-V implementations
|
||||
* that do not include a standard CLINT or do add to the base set of RISC-V
|
||||
* registers.
|
||||
*
|
||||
* CARE MUST BE TAKEN TO INCLDUE THE CORRECT
|
||||
* freertos_risc_v_chip_specific_extensions.h HEADER FILE FOR THE CHIP
|
||||
* IN USE. To include the correct freertos_risc_v_chip_specific_extensions.h
|
||||
* header file ensure the path to the correct header file is in the assembler's
|
||||
* include path.
|
||||
*
|
||||
* This freertos_risc_v_chip_specific_extensions.h is for use on RISC-V chips
|
||||
* that include a standard CLINT and do not add to the base set of RISC-V
|
||||
* registers.
|
||||
*
|
||||
*/
|
||||
#include "freertos_risc_v_chip_specific_extensions.h"
|
||||
|
||||
/* Check the freertos_risc_v_chip_specific_extensions.h and/or command line
|
||||
definitions. */
|
||||
#ifndef portasmHAS_CLINT
|
||||
#error freertos_risc_v_chip_specific_extensions.h must define portasmHAS_CLINT to either 1 (CLINT present) or 0 (clint not present).
|
||||
#endif
|
||||
|
||||
#ifndef portasmHANDLE_INTERRUPT
|
||||
#error portasmHANDLE_INTERRUPT must be defined to the function to be called to handle external/peripheral interrupts. portasmHANDLE_INTERRUPT can be defined on the assmbler command line or in the appropriate freertos_risc_v_chip_specific_extensions.h header file.
|
||||
#endif
|
||||
|
||||
/* Only the standard core registers are stored by default. Any additional
|
||||
registers must be saved by the portasmSAVE_ADDITIONAL_REGISTERS and
|
||||
portasmRESTORE_ADDITIONAL_REGISTERS macros - which can be defined in a chip
|
||||
specific version of freertos_risc_v_chip_specific_extensions.h. See the notes
|
||||
at the top of this file. */
|
||||
#define portCONTEXT_SIZE ( 30 * portWORD_SIZE )
|
||||
|
||||
.global xPortStartFirstTask
|
||||
.global freertos_risc_v_trap_handler
|
||||
.global pxPortInitialiseStack
|
||||
.extern pxCurrentTCB
|
||||
.extern ulPortTrapHandler
|
||||
.extern vTaskSwitchContext
|
||||
.extern Timer_IRQHandler
|
||||
.extern pullMachineTimerCompareRegister
|
||||
.extern pullNextTime
|
||||
.extern ulTimerIncrementsForOneTick
|
||||
.extern xISRStackTop
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
.align 8
|
||||
.func
|
||||
freertos_risc_v_trap_handler:
|
||||
addi sp, sp, -portCONTEXT_SIZE
|
||||
sw x1, 1 * portWORD_SIZE( sp )
|
||||
sw x5, 2 * portWORD_SIZE( sp )
|
||||
sw x6, 3 * portWORD_SIZE( sp )
|
||||
sw x7, 4 * portWORD_SIZE( sp )
|
||||
sw x8, 5 * portWORD_SIZE( sp )
|
||||
sw x9, 6 * portWORD_SIZE( sp )
|
||||
sw x10, 7 * portWORD_SIZE( sp )
|
||||
sw x11, 8 * portWORD_SIZE( sp )
|
||||
sw x12, 9 * portWORD_SIZE( sp )
|
||||
sw x13, 10 * portWORD_SIZE( sp )
|
||||
sw x14, 11 * portWORD_SIZE( sp )
|
||||
sw x15, 12 * portWORD_SIZE( sp )
|
||||
sw x16, 13 * portWORD_SIZE( sp )
|
||||
sw x17, 14 * portWORD_SIZE( sp )
|
||||
sw x18, 15 * portWORD_SIZE( sp )
|
||||
sw x19, 16 * portWORD_SIZE( sp )
|
||||
sw x20, 17 * portWORD_SIZE( sp )
|
||||
sw x21, 18 * portWORD_SIZE( sp )
|
||||
sw x22, 19 * portWORD_SIZE( sp )
|
||||
sw x23, 20 * portWORD_SIZE( sp )
|
||||
sw x24, 21 * portWORD_SIZE( sp )
|
||||
sw x25, 22 * portWORD_SIZE( sp )
|
||||
sw x26, 23 * portWORD_SIZE( sp )
|
||||
sw x27, 24 * portWORD_SIZE( sp )
|
||||
sw x28, 25 * portWORD_SIZE( sp )
|
||||
sw x29, 26 * portWORD_SIZE( sp )
|
||||
sw x30, 27 * portWORD_SIZE( sp )
|
||||
sw x31, 28 * portWORD_SIZE( sp )
|
||||
|
||||
csrr t0, mstatus /* Required for MPIE bit. */
|
||||
sw t0, 29 * portWORD_SIZE( sp )
|
||||
|
||||
portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */
|
||||
|
||||
lw t0, pxCurrentTCB /* Load pxCurrentTCB. */
|
||||
sw sp, 0( t0 ) /* Write sp to first TCB member. */
|
||||
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
|
||||
test_if_asynchronous:
|
||||
srli a2, a0, 0x1f /* MSB of mcause is 1 if handing an asynchronous interrupt - shift to LSB to clear other bits. */
|
||||
beq a2, x0, handle_synchronous /* Branch past interrupt handing if not asynchronous. */
|
||||
sw a1, 0( sp ) /* Asynch so save unmodified exception return address. */
|
||||
|
||||
handle_asynchronous:
|
||||
|
||||
#if( portasmHAS_CLINT != 0 )
|
||||
|
||||
test_if_mtimer: /* If there is a CLINT then the mtimer is used to generate the tick interrupt. */
|
||||
lui t0, 0x80000
|
||||
addi t1, t0, 7 /* 0x80000007 == machine timer interrupt. */
|
||||
bne a0, t1, test_if_external_interrupt
|
||||
|
||||
lw t0, pullMachineTimerCompareRegister /* Load address of compare register into t0. */
|
||||
lw t1, pullNextTime /* Load the address of ullNextTime into t1. */
|
||||
lw t2, 0(t1) /* Load the low word of ullNextTime into t2. */
|
||||
lw t3, 4(t1) /* Load the high word of ullNextTime into t3. */
|
||||
sw t2, 0(t0) /* Store low word of ullNextTime into compare register. */
|
||||
sw t3, 4(t0) /* Store high word of ullNextTime into compare register. */
|
||||
lw t0, ulTimerIncrementsForOneTick /* Load the value of ullTimerIncrementForOneTick into t0 (could this be optimized by storing in an array next to pullNextTime?). */
|
||||
add t4, t0, t2 /* Add the low word of ullNextTime to the timer increments for one tick (assumes timer increment for one tick fits in 32-bits. */
|
||||
sltu t5, t4, t2 /* See if the sum of low words overflowed (what about the zero case?). */
|
||||
add t6, t3, t5 /* Add overflow to high word of ullNextTime. */
|
||||
sw t4, 0(t1) /* Store new low word of ullNextTime. */
|
||||
sw t6, 4(t1) /* Store new high word of ullNextTime. */
|
||||
lw sp, xISRStackTop /* Switch to ISR stack before function call. */
|
||||
jal xTaskIncrementTick
|
||||
beqz a0, processed_source /* Don't switch context if incrementing tick didn't unblock a task. */
|
||||
jal vTaskSwitchContext
|
||||
j processed_source
|
||||
|
||||
test_if_external_interrupt: /* If there is a CLINT and the mtimer interrupt is not pending then check to see if an external interrupt is pending. */
|
||||
addi t1, t1, 4 /* 0x80000007 + 4 = 0x8000000b == Machine external interrupt. */
|
||||
bne a0, t1, as_yet_unhandled /* Something as yet unhandled. */
|
||||
|
||||
#endif /* portasmHAS_CLINT */
|
||||
|
||||
lw sp, xISRStackTop /* Switch to ISR stack before function call. */
|
||||
jal portasmHANDLE_INTERRUPT /* Jump to the interrupt handler if there is no CLINT or if there is a CLINT and it has been determined that an external interrupt is pending. */
|
||||
j processed_source
|
||||
|
||||
handle_synchronous:
|
||||
addi a1, a1, 4 /* Synchronous so updated exception return address to the instruction after the instruction that generated the exeption. */
|
||||
sw a1, 0( sp ) /* Save updated exception return address. */
|
||||
|
||||
test_if_environment_call:
|
||||
li t0, 11 /* 11 == environment call. */
|
||||
bne a0, t0, is_exception /* Not an M environment call, so some other exception. */
|
||||
lw sp, xISRStackTop /* Switch to ISR stack before function call. */
|
||||
jal vTaskSwitchContext
|
||||
j processed_source
|
||||
|
||||
is_exception:
|
||||
ebreak
|
||||
j is_exception
|
||||
|
||||
as_yet_unhandled:
|
||||
ebreak
|
||||
j as_yet_unhandled
|
||||
|
||||
processed_source:
|
||||
lw sp, pxCurrentTCB /* Load pxCurrentTCB. */
|
||||
lw sp, 0( sp ) /* Read sp from first TCB member. */
|
||||
|
||||
/* Load mret with the address of the next instruction in the task to run next. */
|
||||
lw t0, 0( sp )
|
||||
csrw mepc, t0
|
||||
|
||||
portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
|
||||
|
||||
/* Load mstatus with the interrupt enable bits used by the task. */
|
||||
lw t0, 29 * portWORD_SIZE( sp )
|
||||
csrw mstatus, t0 /* Required for MPIE bit. */
|
||||
|
||||
lw x1, 1 * portWORD_SIZE( sp )
|
||||
lw x5, 2 * portWORD_SIZE( sp ) /* t0 */
|
||||
lw x6, 3 * portWORD_SIZE( sp ) /* t1 */
|
||||
lw x7, 4 * portWORD_SIZE( sp ) /* t2 */
|
||||
lw x8, 5 * portWORD_SIZE( sp ) /* s0/fp */
|
||||
lw x9, 6 * portWORD_SIZE( sp ) /* s1 */
|
||||
lw x10, 7 * portWORD_SIZE( sp ) /* a0 */
|
||||
lw x11, 8 * portWORD_SIZE( sp ) /* a1 */
|
||||
lw x12, 9 * portWORD_SIZE( sp ) /* a2 */
|
||||
lw x13, 10 * portWORD_SIZE( sp ) /* a3 */
|
||||
lw x14, 11 * portWORD_SIZE( sp ) /* a4 */
|
||||
lw x15, 12 * portWORD_SIZE( sp ) /* a5 */
|
||||
lw x16, 13 * portWORD_SIZE( sp ) /* a6 */
|
||||
lw x17, 14 * portWORD_SIZE( sp ) /* a7 */
|
||||
lw x18, 15 * portWORD_SIZE( sp ) /* s2 */
|
||||
lw x19, 16 * portWORD_SIZE( sp ) /* s3 */
|
||||
lw x20, 17 * portWORD_SIZE( sp ) /* s4 */
|
||||
lw x21, 18 * portWORD_SIZE( sp ) /* s5 */
|
||||
lw x22, 19 * portWORD_SIZE( sp ) /* s6 */
|
||||
lw x23, 20 * portWORD_SIZE( sp ) /* s7 */
|
||||
lw x24, 21 * portWORD_SIZE( sp ) /* s8 */
|
||||
lw x25, 22 * portWORD_SIZE( sp ) /* s9 */
|
||||
lw x26, 23 * portWORD_SIZE( sp ) /* s10 */
|
||||
lw x27, 24 * portWORD_SIZE( sp ) /* s11 */
|
||||
lw x28, 25 * portWORD_SIZE( sp ) /* t3 */
|
||||
lw x29, 26 * portWORD_SIZE( sp ) /* t4 */
|
||||
lw x30, 27 * portWORD_SIZE( sp ) /* t5 */
|
||||
lw x31, 28 * portWORD_SIZE( sp ) /* t6 */
|
||||
addi sp, sp, portCONTEXT_SIZE
|
||||
|
||||
mret
|
||||
.endfunc
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
.align 8
|
||||
.func
|
||||
xPortStartFirstTask:
|
||||
|
||||
#if( portasmHAS_CLINT != 0 )
|
||||
/* If there is a clint then interrupts can branch directly to the FreeRTOS
|
||||
trap handler. Otherwise the interrupt controller will need to be configured
|
||||
outside of this file. */
|
||||
la t0, freertos_risc_v_trap_handler
|
||||
csrw mtvec, t0
|
||||
#endif /* portasmHAS_CLILNT */
|
||||
|
||||
lw sp, pxCurrentTCB /* Load pxCurrentTCB. */
|
||||
lw sp, 0( sp ) /* Read sp from first TCB member. */
|
||||
|
||||
lw x1, 0( sp ) /* Note for starting the scheduler the exception return address is used as the function return address. */
|
||||
|
||||
portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
|
||||
|
||||
lw t0, 29 * portWORD_SIZE( sp ) /* mstatus */
|
||||
csrrw x0, mstatus, t0 /* Interrupts enabled from here! */
|
||||
|
||||
lw x5, 2 * portWORD_SIZE( sp ) /* t0 */
|
||||
lw x6, 3 * portWORD_SIZE( sp ) /* t1 */
|
||||
lw x7, 4 * portWORD_SIZE( sp ) /* t2 */
|
||||
lw x8, 5 * portWORD_SIZE( sp ) /* s0/fp */
|
||||
lw x9, 6 * portWORD_SIZE( sp ) /* s1 */
|
||||
lw x10, 7 * portWORD_SIZE( sp ) /* a0 */
|
||||
lw x11, 8 * portWORD_SIZE( sp ) /* a1 */
|
||||
lw x12, 9 * portWORD_SIZE( sp ) /* a2 */
|
||||
lw x13, 10 * portWORD_SIZE( sp ) /* a3 */
|
||||
lw x14, 11 * portWORD_SIZE( sp ) /* a4 */
|
||||
lw x15, 12 * portWORD_SIZE( sp ) /* a5 */
|
||||
lw x16, 13 * portWORD_SIZE( sp ) /* a6 */
|
||||
lw x17, 14 * portWORD_SIZE( sp ) /* a7 */
|
||||
lw x18, 15 * portWORD_SIZE( sp ) /* s2 */
|
||||
lw x19, 16 * portWORD_SIZE( sp ) /* s3 */
|
||||
lw x20, 17 * portWORD_SIZE( sp ) /* s4 */
|
||||
lw x21, 18 * portWORD_SIZE( sp ) /* s5 */
|
||||
lw x22, 19 * portWORD_SIZE( sp ) /* s6 */
|
||||
lw x23, 20 * portWORD_SIZE( sp ) /* s7 */
|
||||
lw x24, 21 * portWORD_SIZE( sp ) /* s8 */
|
||||
lw x25, 22 * portWORD_SIZE( sp ) /* s9 */
|
||||
lw x26, 23 * portWORD_SIZE( sp ) /* s10 */
|
||||
lw x27, 24 * portWORD_SIZE( sp ) /* s11 */
|
||||
lw x28, 25 * portWORD_SIZE( sp ) /* t3 */
|
||||
lw x29, 26 * portWORD_SIZE( sp ) /* t4 */
|
||||
lw x30, 27 * portWORD_SIZE( sp ) /* t5 */
|
||||
lw x31, 28 * portWORD_SIZE( sp ) /* t6 */
|
||||
addi sp, sp, portCONTEXT_SIZE
|
||||
ret
|
||||
.endfunc
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Unlike other ports pxPortInitialiseStack() is written in assembly code as it
|
||||
* needs access to the portasmADDITIONAL_CONTEXT_SIZE constant. The prototype
|
||||
* for the function is as per the other ports:
|
||||
* StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters );
|
||||
*
|
||||
* As per the standard RISC-V ABI pxTopcOfStack is passed in in a0, pxCode in
|
||||
* a1, and pvParameters in a2. The new top of stack is passed out in a0.
|
||||
*
|
||||
* RISC-V maps registers to ABI names as follows (X1 to X31 integer registers
|
||||
* for the 'I' profile, X1 to X15 for the 'E' profile, currently I assumed).
|
||||
*
|
||||
* Register ABI Name Description Saver
|
||||
* x0 zero Hard-wired zero -
|
||||
* x1 ra Return address Caller
|
||||
* x2 sp Stack pointer Callee
|
||||
* x3 gp Global pointer -
|
||||
* x4 tp Thread pointer -
|
||||
* x5-7 t0-2 Temporaries Caller
|
||||
* x8 s0/fp Saved register/Frame pointer Callee
|
||||
* x9 s1 Saved register Callee
|
||||
* x10-11 a0-1 Function Arguments/return values Caller
|
||||
* x12-17 a2-7 Function arguments Caller
|
||||
* x18-27 s2-11 Saved registers Callee
|
||||
* x28-31 t3-6 Temporaries Caller
|
||||
*
|
||||
* The RISC-V context is saved t FreeRTOS tasks in the following stack frame,
|
||||
* where the global and thread pointers are currently assumed to be constant so
|
||||
* are not saved:
|
||||
*
|
||||
* mstatus
|
||||
* x31
|
||||
* x30
|
||||
* x29
|
||||
* x28
|
||||
* x27
|
||||
* x26
|
||||
* x25
|
||||
* x24
|
||||
* x23
|
||||
* x22
|
||||
* x21
|
||||
* x20
|
||||
* x19
|
||||
* x18
|
||||
* x17
|
||||
* x16
|
||||
* x15
|
||||
* x14
|
||||
* x13
|
||||
* x12
|
||||
* x11
|
||||
* pvParameters
|
||||
* x9
|
||||
* x8
|
||||
* x7
|
||||
* x6
|
||||
* x5
|
||||
* portTASK_RETURN_ADDRESS
|
||||
* [chip specific registers go here]
|
||||
* pxCode
|
||||
*/
|
||||
.align 8
|
||||
.func
|
||||
pxPortInitialiseStack:
|
||||
|
||||
csrr t0, mstatus /* Obtain current mstatus value. */
|
||||
addi t1, x0, 0x188 /* Generate the value 0x1880, which are the MPIE and MPP bits to set in mstatus. */
|
||||
slli t1, t1, 4
|
||||
or t0, t0, t1 /* Set MPIE and MPP bits in mstatus value. */
|
||||
|
||||
addi a0, a0, -portWORD_SIZE
|
||||
sw t0, 0(a0) /* mstatus onto the stack. */
|
||||
addi a0, a0, -(22 * portWORD_SIZE) /* Space for registers x11-x31. */
|
||||
sw a2, 0(a0) /* Task parameters (pvParameters parameter) goes into register X10/a0 on the stack. */
|
||||
addi a0, a0, -(6 * portWORD_SIZE) /* Space for registers x5-x9. */
|
||||
sw x0, 0(a0) /* Return address onto the stack, could be portTASK_RETURN_ADDRESS */
|
||||
addi t0, x0, portasmADDITIONAL_CONTEXT_SIZE /* The number of chip specific additional registers. */
|
||||
chip_specific_stack_frame: /* First add any chip specific registers to the stack frame being created. */
|
||||
beq t0, x0, 1f /* No more chip specific registers to save. */
|
||||
addi a0, a0, -portWORD_SIZE /* Make space for chip specific register. */
|
||||
sw x0, 0(a0) /* Give the chip specific register an initial value of zero. */
|
||||
addi t0, t0, -1 /* Decrement the count of chip specific registers remaining. */
|
||||
j chip_specific_stack_frame /* Until no more chip specific registers. */
|
||||
1:
|
||||
addi a0, a0, -portWORD_SIZE
|
||||
sw a1, 0(a0) /* mret value (pxCode parameter) onto the stack. */
|
||||
ret
|
||||
.endfunc
|
||||
/*-----------------------------------------------------------*/
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.2.0
|
||||
* 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 PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "FreeRTOSConfig.h"
|
||||
#include "projdefs.h" /* for pdFALSE, pdTRUE */
|
||||
|
||||
void vPortStopTickTimer(void); /* << EST */
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#ifdef __riscv64
|
||||
#error This is the RV32 port that has not yet been adapted for 64.
|
||||
#define portBYTE_ALIGNMENT 16
|
||||
#else
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler utilities. */
|
||||
extern void vTaskSwitchContext( void );
|
||||
#define portYIELD() __asm volatile( "ecall" );
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vTaskSwitchContext()
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Critical section management. */
|
||||
#define portCRITICAL_NESTING_IN_TCB 1
|
||||
extern void vTaskEnterCritical( void );
|
||||
extern void vTaskExitCritical( void );
|
||||
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() 0
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile( "csrc mstatus, 8" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile( "csrs mstatus, 8" )
|
||||
#define portENTER_CRITICAL() vTaskEnterCritical()
|
||||
#define portEXIT_CRITICAL() vTaskExitCritical()
|
||||
#define portDISABLE_ALL_INTERRUPTS() portDISABLE_INTERRUPTS() /* << EST */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
|
||||
|
||||
/* Check the configuration. */
|
||||
#if( configMAX_PRIORITIES > 32 )
|
||||
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||
#endif
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - __builtin_clz( uxReadyPriorities ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
not necessary for to use this port. They are defined so the common demo files
|
||||
(which build with all the ports) will build. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portNOP() __asm volatile ( " nop " )
|
||||
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* The FreeRTOS kernel's RISC-V port is split between the the code that is
|
||||
* common across all currently supported RISC-V chips (implementations of the
|
||||
* RISC-V ISA), and code that tailors the port to a specific RISC-V chip:
|
||||
*
|
||||
* + FreeRTOS\Source\portable\GCC\RISC-V-RV32\portASM.S contains the code that
|
||||
* is common to all currently supported RISC-V chips. There is only one
|
||||
* portASM.S file because the same file is built for all RISC-V target chips.
|
||||
*
|
||||
* + Header files called freertos_risc_v_chip_specific_extensions.h contain the
|
||||
* code that tailors the FreeRTOS kernel's RISC-V port to a specific RISC-V
|
||||
* chip. There are multiple freertos_risc_v_chip_specific_extensions.h files
|
||||
* as there are multiple RISC-V chip implementations.
|
||||
*
|
||||
* !!!NOTE!!!
|
||||
* TAKE CARE TO INCLUDE THE CORRECT freertos_risc_v_chip_specific_extensions.h
|
||||
* HEADER FILE FOR THE CHIP IN USE. This is done using the assembler's (not the
|
||||
* compiler's!) include path. For example, if the chip in use includes a core
|
||||
* local interrupter (CLINT) and does not include any chip specific register
|
||||
* extensions then add the path below to the assembler's include path:
|
||||
* FreeRTOS\Source\portable\GCC\RISC-V-RV32\chip_specific_extensions\RV32I_CLINT_no_extensions
|
||||
*
|
||||
*/
|
||||
199
pico-sensor/McuLib/FreeRTOS/Source/portable/MemMang/heap_1.c
Normal file
199
pico-sensor/McuLib/FreeRTOS/Source/portable/MemMang/heap_1.c
Normal file
@@ -0,0 +1,199 @@
|
||||
/* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* << EST */
|
||||
#include "FreeRTOSConfig.h"
|
||||
#if !defined(configUSE_HEAP_SCHEME) || (configUSE_HEAP_SCHEME==1 && configSUPPORT_DYNAMIC_ALLOCATION==1)
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* The simplest possible implementation of pvPortMalloc(). Note that this
|
||||
* implementation does NOT allow allocated memory to be freed again.
|
||||
*
|
||||
* See heap_2.c, heap_3.c and heap_4.c for alternative implementations, and the
|
||||
* memory management pages of https://www.FreeRTOS.org for more information.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||
* all the API functions to use the MPU wrappers. That should only be done when
|
||||
* task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
#include "SEGGER_SYSVIEW_Conf.h"
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
#endif
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
|
||||
#error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
|
||||
#endif
|
||||
|
||||
/* A few bytes might be lost to byte aligning the heap start address. */
|
||||
#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )
|
||||
|
||||
/* Allocate the memory for the heap. */
|
||||
#if ( configAPPLICATION_ALLOCATED_HEAP == 1 )
|
||||
|
||||
/* The application writer has already defined the array used for the RTOS
|
||||
* heap - probably so it can be placed in a special segment or address. */
|
||||
extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
|
||||
#elif configUSE_HEAP_SECTION_NAME && configCOMPILER==configCOMPILER_ARM_IAR /* << EST */
|
||||
#pragma language=extended
|
||||
#pragma location = configHEAP_SECTION_NAME_STRING
|
||||
static uint8_t ucHeap[configTOTAL_HEAP_SIZE] @ configHEAP_SECTION_NAME_STRING;
|
||||
#elif configUSE_HEAP_SECTION_NAME /* << EST */
|
||||
static uint8_t __attribute__((section (configHEAP_SECTION_NAME_STRING))) ucHeap[configTOTAL_HEAP_SIZE];
|
||||
#else
|
||||
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
|
||||
#endif /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
|
||||
/* Index into the ucHeap array. */
|
||||
static size_t xNextFreeByte = ( size_t ) 0;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
static uint8_t *pucAlignedHeap = NULL; /* << EST: make it global, so it can be re-initialized */
|
||||
|
||||
void * pvPortMallocExt( size_t xWantedSize, unsigned int heapTag) /* << EST */
|
||||
{
|
||||
void * pvReturn = NULL;
|
||||
//static uint8_t *pucAlignedHeap = NULL; /* << EST: make it global so it can be re-initialized */
|
||||
|
||||
/* Ensure that blocks are always aligned. */
|
||||
#if ( portBYTE_ALIGNMENT != 1 )
|
||||
{
|
||||
if( xWantedSize & portBYTE_ALIGNMENT_MASK )
|
||||
{
|
||||
/* Byte alignment required. Check for overflow. */
|
||||
if( ( xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ) ) > xWantedSize )
|
||||
{
|
||||
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
xWantedSize = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* if ( portBYTE_ALIGNMENT != 1 ) */
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
if( pucAlignedHeap == NULL )
|
||||
{
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
SEGGER_SYSVIEW_HeapDefine(ucHeap, ucHeap, sizeof(ucHeap), 0);
|
||||
SEGGER_SYSVIEW_NameResource((uint32_t)ucHeap, "heap1");
|
||||
#endif
|
||||
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||
pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) & ucHeap[ portBYTE_ALIGNMENT - 1 ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
|
||||
}
|
||||
|
||||
/* Check there is enough room left for the allocation and. */
|
||||
if( ( xWantedSize > 0 ) && /* valid size */
|
||||
( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) &&
|
||||
( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) ) /* Check for overflow. */
|
||||
{
|
||||
/* Return the next free byte then increment the index past this
|
||||
* block. */
|
||||
pvReturn = pucAlignedHeap + xNextFreeByte;
|
||||
xNextFreeByte += xWantedSize;
|
||||
}
|
||||
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
if (heapTag!=(unsigned)-1) {
|
||||
SEGGER_SYSVIEW_HeapAllocEx(ucHeap, pvReturn, xWantedSize, heapTag);
|
||||
} else {
|
||||
SEGGER_SYSVIEW_HeapAlloc(ucHeap, pvReturn, xWantedSize);
|
||||
}
|
||||
#else
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
#endif
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
#if ( configUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
#if 1/* << EST: Using configuration macro name for hook */
|
||||
extern void configUSE_MALLOC_FAILED_HOOK_NAME( void );
|
||||
configUSE_MALLOC_FAILED_HOOK_NAME();
|
||||
#else /* << EST */
|
||||
vApplicationMallocFailedHook();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void *pvPortMalloc(size_t xWantedSize) { /* << EST */
|
||||
return pvPortMallocExt(xWantedSize, -1);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFree( void * pv )
|
||||
{
|
||||
/* Memory cannot be freed using this scheme. See heap_2.c, heap_3.c and
|
||||
* heap_4.c for alternative implementations, and the memory management pages of
|
||||
* https://www.FreeRTOS.org for more information. */
|
||||
( void ) pv;
|
||||
|
||||
/* Force an assert as it is invalid to call this function. */
|
||||
configASSERT( pv == NULL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortInitialiseBlocks( void )
|
||||
{
|
||||
/* Only required when static memory is not cleared. */
|
||||
xNextFreeByte = ( size_t ) 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetFreeHeapSize( void )
|
||||
{
|
||||
return( configADJUSTED_HEAP_SIZE - xNextFreeByte );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if 1 /* << EST */
|
||||
void vPortInitializeHeap(void) {
|
||||
xNextFreeByte = 0;
|
||||
pucAlignedHeap = NULL;
|
||||
}
|
||||
#endif
|
||||
#endif /* configUSE_HEAP_SCHEME==1 */ /* << EST */
|
||||
|
||||
440
pico-sensor/McuLib/FreeRTOS/Source/portable/MemMang/heap_2.c
Normal file
440
pico-sensor/McuLib/FreeRTOS/Source/portable/MemMang/heap_2.c
Normal file
@@ -0,0 +1,440 @@
|
||||
/* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* << EST */
|
||||
#include "FreeRTOSConfig.h"
|
||||
#if !defined(configUSE_HEAP_SCHEME) || (configUSE_HEAP_SCHEME==2 && configSUPPORT_DYNAMIC_ALLOCATION==1)
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* A sample implementation of pvPortMalloc() and vPortFree() that permits
|
||||
* allocated blocks to be freed, but does not combine adjacent free blocks
|
||||
* into a single larger block (and so will fragment memory). See heap_4.c for
|
||||
* an equivalent that does combine adjacent blocks into single larger blocks.
|
||||
*
|
||||
* See heap_1.c, heap_3.c and heap_4.c for alternative implementations, and the
|
||||
* memory management pages of https://www.FreeRTOS.org for more information.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||
* all the API functions to use the MPU wrappers. That should only be done when
|
||||
* task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
#include "SEGGER_SYSVIEW_Conf.h"
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
#endif
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
|
||||
#error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
|
||||
#endif
|
||||
|
||||
#ifndef configHEAP_CLEAR_MEMORY_ON_FREE
|
||||
#define configHEAP_CLEAR_MEMORY_ON_FREE 0
|
||||
#endif
|
||||
|
||||
/* A few bytes might be lost to byte aligning the heap start address. */
|
||||
#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )
|
||||
|
||||
/* Assumes 8bit bytes! */
|
||||
#define heapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
|
||||
/* Max value that fits in a size_t type. */
|
||||
#define heapSIZE_MAX ( ~( ( size_t ) 0 ) )
|
||||
|
||||
/* Check if multiplying a and b will result in overflow. */
|
||||
#define heapMULTIPLY_WILL_OVERFLOW( a, b ) ( ( ( a ) > 0 ) && ( ( b ) > ( heapSIZE_MAX / ( a ) ) ) )
|
||||
|
||||
/* Check if adding a and b will result in overflow. */
|
||||
#define heapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( heapSIZE_MAX - ( b ) ) )
|
||||
|
||||
/* MSB of the xBlockSize member of an BlockLink_t structure is used to track
|
||||
* the allocation status of a block. When MSB of the xBlockSize member of
|
||||
* an BlockLink_t structure is set then the block belongs to the application.
|
||||
* When the bit is free the block is still part of the free heap space. */
|
||||
#define heapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ) )
|
||||
#define heapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & heapBLOCK_ALLOCATED_BITMASK ) == 0 )
|
||||
#define heapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & heapBLOCK_ALLOCATED_BITMASK ) != 0 )
|
||||
#define heapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= heapBLOCK_ALLOCATED_BITMASK )
|
||||
#define heapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~heapBLOCK_ALLOCATED_BITMASK )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Allocate the memory for the heap. */
|
||||
#if ( configAPPLICATION_ALLOCATED_HEAP == 1 )
|
||||
|
||||
/* The application writer has already defined the array used for the RTOS
|
||||
* heap - probably so it can be placed in a special segment or address. */
|
||||
extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
|
||||
#elif configUSE_HEAP_SECTION_NAME && configCOMPILER==configCOMPILER_ARM_IAR /* << EST */
|
||||
#pragma language=extended
|
||||
#pragma location = configHEAP_SECTION_NAME_STRING
|
||||
static uint8_t ucHeap[configTOTAL_HEAP_SIZE] @ configHEAP_SECTION_NAME_STRING;
|
||||
#elif configUSE_HEAP_SECTION_NAME /* << EST */
|
||||
static uint8_t __attribute__((section (configHEAP_SECTION_NAME_STRING))) ucHeap[configTOTAL_HEAP_SIZE];
|
||||
#else
|
||||
PRIVILEGED_DATA static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
|
||||
#endif /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
|
||||
|
||||
/* Define the linked list structure. This is used to link free blocks in order
|
||||
* of their size. */
|
||||
typedef struct A_BLOCK_LINK
|
||||
{
|
||||
struct A_BLOCK_LINK * pxNextFreeBlock; /*<< The next free block in the list. */
|
||||
size_t xBlockSize; /*<< The size of the free block. */
|
||||
} BlockLink_t;
|
||||
|
||||
|
||||
static const size_t xHeapStructSize = ( ( sizeof( BlockLink_t ) + ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK ) );
|
||||
#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize * 2 ) )
|
||||
|
||||
/* Create a couple of list links to mark the start and end of the list. */
|
||||
PRIVILEGED_DATA static BlockLink_t xStart, xEnd;
|
||||
|
||||
/* Keeps track of the number of free bytes remaining, but says nothing about
|
||||
* fragmentation. */
|
||||
PRIVILEGED_DATA static size_t xFreeBytesRemaining = configADJUSTED_HEAP_SIZE;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialises the heap structures before their first use.
|
||||
*/
|
||||
static void prvHeapInit( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* STATIC FUNCTIONS ARE DEFINED AS MACROS TO MINIMIZE THE FUNCTION CALL DEPTH. */
|
||||
|
||||
/*
|
||||
* Insert a block into the list of free blocks - which is ordered by size of
|
||||
* the block. Small blocks at the start of the list and large blocks at the end
|
||||
* of the list.
|
||||
*/
|
||||
#define prvInsertBlockIntoFreeList( pxBlockToInsert ) \
|
||||
{ \
|
||||
BlockLink_t * pxIterator; \
|
||||
size_t xBlockSize; \
|
||||
\
|
||||
xBlockSize = pxBlockToInsert->xBlockSize; \
|
||||
\
|
||||
/* Iterate through the list until a block is found that has a larger size */ \
|
||||
/* than the block we are inserting. */ \
|
||||
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock->xBlockSize < xBlockSize; pxIterator = pxIterator->pxNextFreeBlock ) \
|
||||
{ \
|
||||
/* There is nothing to do here - just iterate to the correct position. */ \
|
||||
} \
|
||||
\
|
||||
/* Update the list to include the block being inserted in the correct */ \
|
||||
/* position. */ \
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; \
|
||||
pxIterator->pxNextFreeBlock = pxBlockToInsert; \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
static BaseType_t xHeapHasBeenInitialised = pdFALSE; /* << EST: make it global, so it can be re-initialized */
|
||||
|
||||
void * pvPortMallocExt( size_t xWantedSize, unsigned int heapTag) /* << EST */
|
||||
{
|
||||
BlockLink_t * pxBlock;
|
||||
BlockLink_t * pxPreviousBlock;
|
||||
BlockLink_t * pxNewBlockLink;
|
||||
// PRIVILEGED_DATA static BaseType_t xHeapHasBeenInitialised = pdFALSE; /* << EST: make it global so it can be re-initialized */
|
||||
void * pvReturn = NULL;
|
||||
size_t xAdditionalRequiredSize;
|
||||
|
||||
if( xWantedSize > 0 )
|
||||
{
|
||||
/* The wanted size must be increased so it can contain a BlockLink_t
|
||||
* structure in addition to the requested amount of bytes. */
|
||||
if( heapADD_WILL_OVERFLOW( xWantedSize, xHeapStructSize ) == 0 )
|
||||
{
|
||||
xWantedSize += xHeapStructSize;
|
||||
|
||||
/* Ensure that blocks are always aligned to the required number
|
||||
* of bytes. */
|
||||
if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||
{
|
||||
/* Byte alignment required. */
|
||||
xAdditionalRequiredSize = portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK );
|
||||
|
||||
if( heapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 )
|
||||
{
|
||||
xWantedSize += xAdditionalRequiredSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
xWantedSize = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
xWantedSize = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* If this is the first call to malloc then the heap will require
|
||||
* initialisation to setup the list of free blocks. */
|
||||
if( xHeapHasBeenInitialised == pdFALSE )
|
||||
{
|
||||
prvHeapInit();
|
||||
xHeapHasBeenInitialised = pdTRUE;
|
||||
}
|
||||
|
||||
/* Check the block size we are trying to allocate is not so large that the
|
||||
* top bit is set. The top bit of the block size member of the BlockLink_t
|
||||
* structure is used to determine who owns the block - the application or
|
||||
* the kernel, so it must be free. */
|
||||
if( heapBLOCK_SIZE_IS_VALID( xWantedSize ) != 0 )
|
||||
{
|
||||
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
||||
{
|
||||
/* Blocks are stored in byte order - traverse the list from the start
|
||||
* (smallest) block until one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
|
||||
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||
{
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If we found the end marker then a block of adequate size was not found. */
|
||||
if( pxBlock != &xEnd )
|
||||
{
|
||||
/* Return the memory space - jumping over the BlockLink_t structure
|
||||
* at its start. */
|
||||
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
|
||||
|
||||
/* This block is being returned for use so must be taken out of the
|
||||
* list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
|
||||
/* If the block is larger than required it can be split into two. */
|
||||
if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
|
||||
{
|
||||
/* This block is to be split into two. Create a new block
|
||||
* following the number of bytes requested. The void cast is
|
||||
* used to prevent byte alignment warnings from the compiler. */
|
||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||
|
||||
/* Calculate the sizes of two blocks split from the single
|
||||
* block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
|
||||
/* Insert the new block into the list of free blocks.
|
||||
* The list of free blocks is sorted by their size, we have to
|
||||
* iterate to find the right place to insert new block. */
|
||||
prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
|
||||
}
|
||||
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
|
||||
/* The block is being returned - it is allocated and owned
|
||||
* by the application and has no "next" block. */
|
||||
heapALLOCATE_BLOCK( pxBlock );
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
if (heapTag!=(unsigned)-1) {
|
||||
SEGGER_SYSVIEW_HeapAllocEx(ucHeap, pvReturn, xWantedSize, heapTag);
|
||||
} else {
|
||||
SEGGER_SYSVIEW_HeapAlloc(ucHeap, pvReturn, xWantedSize);
|
||||
}
|
||||
#else
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
#endif
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
#if ( configUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
#if 1 /* << EST: Using configuration macro name for hook */
|
||||
extern void configUSE_MALLOC_FAILED_HOOK_NAME( void );
|
||||
configUSE_MALLOC_FAILED_HOOK_NAME();
|
||||
#else
|
||||
vApplicationMallocFailedHook();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void *pvPortMalloc(size_t xWantedSize) { /* << EST */
|
||||
return pvPortMallocExt(xWantedSize, -1);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFree( void * pv )
|
||||
{
|
||||
uint8_t * puc = ( uint8_t * ) pv;
|
||||
BlockLink_t * pxLink;
|
||||
|
||||
if( pv != NULL )
|
||||
{
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
* before it. */
|
||||
puc -= xHeapStructSize;
|
||||
|
||||
/* This unexpected casting is to keep some compilers from issuing
|
||||
* byte alignment warnings. */
|
||||
pxLink = ( void * ) puc;
|
||||
|
||||
configASSERT( heapBLOCK_IS_ALLOCATED( pxLink ) != 0 );
|
||||
configASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||
|
||||
if( heapBLOCK_IS_ALLOCATED( pxLink ) != 0 )
|
||||
{
|
||||
if( pxLink->pxNextFreeBlock == NULL )
|
||||
{
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
* allocated. */
|
||||
heapFREE_BLOCK( pxLink );
|
||||
#if ( configHEAP_CLEAR_MEMORY_ON_FREE == 1 )
|
||||
{
|
||||
( void ) memset( puc + xHeapStructSize, 0, pxLink->xBlockSize - xHeapStructSize );
|
||||
}
|
||||
#endif
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
SEGGER_SYSVIEW_HeapFree(ucHeap, pv);
|
||||
#else
|
||||
traceFREE( pv, pxLink->xBlockSize );
|
||||
#endif
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetFreeHeapSize( void )
|
||||
{
|
||||
return xFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortInitialiseBlocks( void )
|
||||
{
|
||||
/* This just exists to keep the linker quiet. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void * pvPortCalloc( size_t xNum,
|
||||
size_t xSize )
|
||||
{
|
||||
void * pv = NULL;
|
||||
|
||||
if( heapMULTIPLY_WILL_OVERFLOW( xNum, xSize ) == 0 )
|
||||
{
|
||||
pv = pvPortMalloc( xNum * xSize );
|
||||
|
||||
if( pv != NULL )
|
||||
{
|
||||
( void ) memset( pv, 0, xNum * xSize );
|
||||
}
|
||||
}
|
||||
|
||||
return pv;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvHeapInit( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
BlockLink_t * pxFirstFreeBlock;
|
||||
uint8_t * pucAlignedHeap;
|
||||
|
||||
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||
pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) & ucHeap[ portBYTE_ALIGNMENT - 1 ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
|
||||
|
||||
/* xStart is used to hold a pointer to the first item in the list of free
|
||||
* blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
|
||||
xStart.xBlockSize = ( size_t ) 0;
|
||||
|
||||
/* xEnd is used to mark the end of the list of free blocks. */
|
||||
xEnd.xBlockSize = configADJUSTED_HEAP_SIZE;
|
||||
xEnd.pxNextFreeBlock = NULL;
|
||||
|
||||
/* To start with there is a single free block that is sized to take up the
|
||||
* entire heap space. */
|
||||
pxFirstFreeBlock = ( BlockLink_t * ) pucAlignedHeap;
|
||||
pxFirstFreeBlock->xBlockSize = configADJUSTED_HEAP_SIZE;
|
||||
pxFirstFreeBlock->pxNextFreeBlock = &xEnd;
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
SEGGER_SYSVIEW_HeapDefine(ucHeap, ucHeap, sizeof(ucHeap), sizeof(BlockLink_t));
|
||||
SEGGER_SYSVIEW_NameResource((uint32_t)ucHeap, "heap2");
|
||||
#endif
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
#if 1 /* << EST */
|
||||
void vPortInitializeHeap(void) {
|
||||
xStart.pxNextFreeBlock = NULL;
|
||||
xStart.xBlockSize = 0;
|
||||
xEnd.pxNextFreeBlock = NULL;
|
||||
xEnd.xBlockSize = 0;
|
||||
xFreeBytesRemaining = configADJUSTED_HEAP_SIZE;
|
||||
xHeapHasBeenInitialised = pdFALSE;
|
||||
}
|
||||
#endif
|
||||
#endif /* configUSE_HEAP_SCHEME==2 */ /* << EST */
|
||||
|
||||
|
||||
147
pico-sensor/McuLib/FreeRTOS/Source/portable/MemMang/heap_3.c
Normal file
147
pico-sensor/McuLib/FreeRTOS/Source/portable/MemMang/heap_3.c
Normal file
@@ -0,0 +1,147 @@
|
||||
/* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* << EST */
|
||||
#include "FreeRTOSConfig.h"
|
||||
#if !defined(configUSE_HEAP_SCHEME) || (configUSE_HEAP_SCHEME==3 && configSUPPORT_DYNAMIC_ALLOCATION==1)
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Implementation of pvPortMalloc() and vPortFree() that relies on the
|
||||
* compilers own malloc() and free() implementations.
|
||||
*
|
||||
* This file can only be used if the linker is configured to to generate
|
||||
* a heap memory area.
|
||||
*
|
||||
* See heap_1.c, heap_2.c and heap_4.c for alternative implementations, and the
|
||||
* memory management pages of https://www.FreeRTOS.org for more information.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||
* all the API functions to use the MPU wrappers. That should only be done when
|
||||
* task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#if 0 && configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST: currently not fully supported for heap3 */
|
||||
#include "SEGGER_SYSVIEW_Conf.h"
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
#endif
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
|
||||
#error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
|
||||
#endif
|
||||
|
||||
#if 0 && configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
static bool firstMalloc = true;
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void * pvPortMallocExt( size_t xWantedSize, unsigned int heapTag) /* << EST */
|
||||
{
|
||||
void * pvReturn;
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
#if 0 && configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
if (firstMalloc) {
|
||||
firstMalloc = false;
|
||||
SEGGER_SYSVIEW_HeapDefine(ucHeap, ucHeap, sizeof(ucHeap), sizeof(BlockLink_t));
|
||||
SEGGER_SYSVIEW_NameResource((uint32_t)ucHeap, "heap3");
|
||||
}
|
||||
#endif
|
||||
pvReturn = malloc( xWantedSize );
|
||||
#if 0 && configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
if (heapTag!=(unsigned)-1) {
|
||||
SEGGER_SYSVIEW_HeapAllocEx(ucHeap, pvReturn, xWantedSize, heapTag);
|
||||
} else {
|
||||
SEGGER_SYSVIEW_HeapAlloc(ucHeap, pvReturn, xWantedSize);
|
||||
}
|
||||
#else
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
#endif
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
#if ( configUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
#if 1 /* << EST: Using configuration macro name for hook */
|
||||
extern void configUSE_MALLOC_FAILED_HOOK_NAME( void );
|
||||
configUSE_MALLOC_FAILED_HOOK_NAME();
|
||||
#else
|
||||
vApplicationMallocFailedHook();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void *pvPortMalloc(size_t xWantedSize) { /* << EST */
|
||||
return pvPortMallocExt(xWantedSize, -1);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFree( void * pv )
|
||||
{
|
||||
if( pv != NULL )
|
||||
{
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
free( pv );
|
||||
#if 0 && configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
SEGGER_SYSVIEW_HeapFree(ucHeap, pv);
|
||||
#else
|
||||
traceFREE( pv, 0 );
|
||||
#endif
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
#if 1 /* << EST */
|
||||
void vPortInitializeHeap(void) {
|
||||
#if 0 && configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
firstMalloc = true;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* configUSE_HEAP_SCHEME==3 */ /* << EST */
|
||||
|
||||
|
||||
707
pico-sensor/McuLib/FreeRTOS/Source/portable/MemMang/heap_4.c
Normal file
707
pico-sensor/McuLib/FreeRTOS/Source/portable/MemMang/heap_4.c
Normal file
@@ -0,0 +1,707 @@
|
||||
/* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* << EST */
|
||||
#include "FreeRTOSConfig.h"
|
||||
#if !defined(configUSE_HEAP_SCHEME) || (configUSE_HEAP_SCHEME==4 && configSUPPORT_DYNAMIC_ALLOCATION==1)
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* A sample implementation of pvPortMalloc() and vPortFree() that combines
|
||||
* (coalescences) adjacent memory blocks as they are freed, and in so doing
|
||||
* limits memory fragmentation.
|
||||
*
|
||||
* See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the
|
||||
* memory management pages of https://www.FreeRTOS.org for more information.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||
* all the API functions to use the MPU wrappers. That should only be done when
|
||||
* task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
#include "SEGGER_SYSVIEW_Conf.h"
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
#endif
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
|
||||
#error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
|
||||
#endif
|
||||
|
||||
#ifndef configHEAP_CLEAR_MEMORY_ON_FREE
|
||||
#define configHEAP_CLEAR_MEMORY_ON_FREE 0
|
||||
#endif
|
||||
|
||||
/* Block sizes must not get too small. */
|
||||
#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
|
||||
|
||||
/* Assumes 8bit bytes! */
|
||||
#define heapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
|
||||
/* Max value that fits in a size_t type. */
|
||||
#define heapSIZE_MAX ( ~( ( size_t ) 0 ) )
|
||||
|
||||
/* Check if multiplying a and b will result in overflow. */
|
||||
#define heapMULTIPLY_WILL_OVERFLOW( a, b ) ( ( ( a ) > 0 ) && ( ( b ) > ( heapSIZE_MAX / ( a ) ) ) )
|
||||
|
||||
/* Check if adding a and b will result in overflow. */
|
||||
#define heapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( heapSIZE_MAX - ( b ) ) )
|
||||
|
||||
/* Check if the subtraction operation ( a - b ) will result in underflow. */
|
||||
#define heapSUBTRACT_WILL_UNDERFLOW( a, b ) ( ( a ) < ( b ) )
|
||||
|
||||
/* MSB of the xBlockSize member of an BlockLink_t structure is used to track
|
||||
* the allocation status of a block. When MSB of the xBlockSize member of
|
||||
* an BlockLink_t structure is set then the block belongs to the application.
|
||||
* When the bit is free the block is still part of the free heap space. */
|
||||
#define heapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ) )
|
||||
#define heapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & heapBLOCK_ALLOCATED_BITMASK ) == 0 )
|
||||
#define heapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & heapBLOCK_ALLOCATED_BITMASK ) != 0 )
|
||||
#define heapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= heapBLOCK_ALLOCATED_BITMASK )
|
||||
#define heapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~heapBLOCK_ALLOCATED_BITMASK )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Allocate the memory for the heap. */
|
||||
#if ( configAPPLICATION_ALLOCATED_HEAP == 1 )
|
||||
|
||||
/* The application writer has already defined the array used for the RTOS
|
||||
* heap - probably so it can be placed in a special segment or address. */
|
||||
extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
|
||||
#elif configUSE_HEAP_SECTION_NAME && configCOMPILER==configCOMPILER_ARM_IAR /* << EST */
|
||||
#pragma language=extended
|
||||
#pragma location = configHEAP_SECTION_NAME_STRING
|
||||
static unsigned char ucHeap[configTOTAL_HEAP_SIZE] @ configHEAP_SECTION_NAME_STRING;
|
||||
#elif configUSE_HEAP_SECTION_NAME /* << EST */
|
||||
static unsigned char __attribute__((section (configHEAP_SECTION_NAME_STRING))) ucHeap[configTOTAL_HEAP_SIZE];
|
||||
#else
|
||||
PRIVILEGED_DATA static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
|
||||
#endif /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
|
||||
/* Define the linked list structure. This is used to link free blocks in order
|
||||
* of their memory address. */
|
||||
typedef struct A_BLOCK_LINK
|
||||
{
|
||||
struct A_BLOCK_LINK * pxNextFreeBlock; /**< The next free block in the list. */
|
||||
size_t xBlockSize; /**< The size of the free block. */
|
||||
} BlockLink_t;
|
||||
|
||||
/* Setting configENABLE_HEAP_PROTECTOR to 1 enables heap block pointers
|
||||
* protection using an application supplied canary value to catch heap
|
||||
* corruption should a heap buffer overflow occur.
|
||||
*/
|
||||
#if ( configENABLE_HEAP_PROTECTOR == 1 )
|
||||
|
||||
/**
|
||||
* @brief Application provided function to get a random value to be used as canary.
|
||||
*
|
||||
* @param pxHeapCanary [out] Output parameter to return the canary value.
|
||||
*/
|
||||
extern void vApplicationGetRandomHeapCanary( portPOINTER_SIZE_TYPE * pxHeapCanary );
|
||||
|
||||
/* Canary value for protecting internal heap pointers. */
|
||||
PRIVILEGED_DATA static portPOINTER_SIZE_TYPE xHeapCanary;
|
||||
|
||||
/* Macro to load/store BlockLink_t pointers to memory. By XORing the
|
||||
* pointers with a random canary value, heap overflows will result
|
||||
* in randomly unpredictable pointer values which will be caught by
|
||||
* heapVALIDATE_BLOCK_POINTER assert. */
|
||||
#define heapPROTECT_BLOCK_POINTER( pxBlock ) ( ( BlockLink_t * ) ( ( ( portPOINTER_SIZE_TYPE ) ( pxBlock ) ) ^ xHeapCanary ) )
|
||||
#else
|
||||
|
||||
#define heapPROTECT_BLOCK_POINTER( pxBlock ) ( pxBlock )
|
||||
|
||||
#endif /* configENABLE_HEAP_PROTECTOR */
|
||||
|
||||
/* Assert that a heap block pointer is within the heap bounds. */
|
||||
#define heapVALIDATE_BLOCK_POINTER( pxBlock ) \
|
||||
configASSERT( ( ( uint8_t * ) ( pxBlock ) >= &( ucHeap[ 0 ] ) ) && \
|
||||
( ( uint8_t * ) ( pxBlock ) <= &( ucHeap[ configTOTAL_HEAP_SIZE - 1 ] ) ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Inserts a block of memory that is being freed into the correct position in
|
||||
* the list of free memory blocks. The block being freed will be merged with
|
||||
* the block in front it and/or the block behind it if the memory blocks are
|
||||
* adjacent to each other.
|
||||
*/
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Called automatically to setup the required heap structures the first time
|
||||
* pvPortMalloc() is called.
|
||||
*/
|
||||
static void prvHeapInit( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The size of the structure placed at the beginning of each allocated memory
|
||||
* block must by correctly byte aligned. */
|
||||
#if 0 /* << EST */
|
||||
static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
|
||||
#else /* << EST do not optimize this variable, needed for NXP TAD plugin */
|
||||
static const volatile size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
|
||||
#endif
|
||||
|
||||
/* Create a couple of list links to mark the start and end of the list. */
|
||||
PRIVILEGED_DATA static BlockLink_t xStart;
|
||||
PRIVILEGED_DATA static BlockLink_t * pxEnd = NULL;
|
||||
|
||||
/* Keeps track of the number of calls to allocate and free memory as well as the
|
||||
* number of free bytes remaining, but says nothing about fragmentation. */
|
||||
PRIVILEGED_DATA static size_t xFreeBytesRemaining = 0U;
|
||||
PRIVILEGED_DATA static size_t xMinimumEverFreeBytesRemaining = 0U;
|
||||
PRIVILEGED_DATA static size_t xNumberOfSuccessfulAllocations = 0;
|
||||
PRIVILEGED_DATA static size_t xNumberOfSuccessfulFrees = 0;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
void *pvPortMallocExt(size_t xWantedSize, unsigned int heapTag) /* << EST */
|
||||
{
|
||||
BlockLink_t * pxBlock;
|
||||
BlockLink_t * pxPreviousBlock;
|
||||
BlockLink_t * pxNewBlockLink;
|
||||
void * pvReturn = NULL;
|
||||
size_t xAdditionalRequiredSize;
|
||||
|
||||
if( xWantedSize > 0 )
|
||||
{
|
||||
/* The wanted size must be increased so it can contain a BlockLink_t
|
||||
* structure in addition to the requested amount of bytes. */
|
||||
if( heapADD_WILL_OVERFLOW( xWantedSize, xHeapStructSize ) == 0 )
|
||||
{
|
||||
xWantedSize += xHeapStructSize;
|
||||
|
||||
/* Ensure that blocks are always aligned to the required number
|
||||
* of bytes. */
|
||||
if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||
{
|
||||
/* Byte alignment required. */
|
||||
xAdditionalRequiredSize = portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK );
|
||||
|
||||
if( heapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 )
|
||||
{
|
||||
xWantedSize += xAdditionalRequiredSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
xWantedSize = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
xWantedSize = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* If this is the first call to malloc then the heap will require
|
||||
* initialisation to setup the list of free blocks. */
|
||||
if( pxEnd == NULL )
|
||||
{
|
||||
prvHeapInit();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Check the block size we are trying to allocate is not so large that the
|
||||
* top bit is set. The top bit of the block size member of the BlockLink_t
|
||||
* structure is used to determine who owns the block - the application or
|
||||
* the kernel, so it must be free. */
|
||||
if( heapBLOCK_SIZE_IS_VALID( xWantedSize ) != 0 )
|
||||
{
|
||||
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
||||
{
|
||||
/* Traverse the list from the start (lowest address) block until
|
||||
* one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = heapPROTECT_BLOCK_POINTER( xStart.pxNextFreeBlock );
|
||||
heapVALIDATE_BLOCK_POINTER( pxBlock );
|
||||
|
||||
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != heapPROTECT_BLOCK_POINTER( NULL ) ) )
|
||||
{
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = heapPROTECT_BLOCK_POINTER( pxBlock->pxNextFreeBlock );
|
||||
heapVALIDATE_BLOCK_POINTER( pxBlock );
|
||||
}
|
||||
|
||||
/* If the end marker was reached then a block of adequate size
|
||||
* was not found. */
|
||||
if( pxBlock != pxEnd )
|
||||
{
|
||||
/* Return the memory space pointed to - jumping over the
|
||||
* BlockLink_t structure at its start. */
|
||||
pvReturn = ( void * ) ( ( ( uint8_t * ) heapPROTECT_BLOCK_POINTER( pxPreviousBlock->pxNextFreeBlock ) ) + xHeapStructSize );
|
||||
heapVALIDATE_BLOCK_POINTER( pvReturn );
|
||||
|
||||
/* This block is being returned for use so must be taken out
|
||||
* of the list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
|
||||
/* If the block is larger than required it can be split into
|
||||
* two. */
|
||||
configASSERT( heapSUBTRACT_WILL_UNDERFLOW( pxBlock->xBlockSize, xWantedSize ) == 0 );
|
||||
|
||||
if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
|
||||
{
|
||||
/* This block is to be split into two. Create a new
|
||||
* block following the number of bytes requested. The void
|
||||
* cast is used to prevent byte alignment warnings from the
|
||||
* compiler. */
|
||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||
configASSERT( ( ( ( size_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
|
||||
/* Calculate the sizes of two blocks split from the
|
||||
* single block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
|
||||
/* Insert the new block into the list of free blocks. */
|
||||
pxNewBlockLink->pxNextFreeBlock = pxPreviousBlock->pxNextFreeBlock;
|
||||
pxPreviousBlock->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxNewBlockLink );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
|
||||
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
||||
{
|
||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* The block is being returned - it is allocated and owned
|
||||
* by the application and has no "next" block. */
|
||||
heapALLOCATE_BLOCK( pxBlock );
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
xNumberOfSuccessfulAllocations++;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
if (heapTag!=(unsigned)-1) {
|
||||
SEGGER_SYSVIEW_HeapAllocEx(&xStart, pvReturn, xWantedSize, heapTag);
|
||||
} else {
|
||||
SEGGER_SYSVIEW_HeapAlloc(&xStart, pvReturn, xWantedSize);
|
||||
}
|
||||
#else
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
#endif
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
#if ( configUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
#if 1/* << EST: Using configuration macro name for hook */
|
||||
extern void configUSE_MALLOC_FAILED_HOOK_NAME( void );
|
||||
configUSE_MALLOC_FAILED_HOOK_NAME();
|
||||
#else /* << EST */
|
||||
vApplicationMallocFailedHook();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif /* if ( configUSE_MALLOC_FAILED_HOOK == 1 ) */
|
||||
|
||||
configASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) portBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void *pvPortMalloc(size_t xWantedSize) { /* << EST */
|
||||
return pvPortMallocExt(xWantedSize, -1);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFree( void * pv )
|
||||
{
|
||||
uint8_t * puc = ( uint8_t * ) pv;
|
||||
BlockLink_t * pxLink;
|
||||
|
||||
if( pv != NULL )
|
||||
{
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
* before it. */
|
||||
puc -= xHeapStructSize;
|
||||
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = ( void * ) puc;
|
||||
|
||||
heapVALIDATE_BLOCK_POINTER( pxLink );
|
||||
configASSERT( heapBLOCK_IS_ALLOCATED( pxLink ) != 0 );
|
||||
configASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||
|
||||
if( heapBLOCK_IS_ALLOCATED( pxLink ) != 0 )
|
||||
{
|
||||
if( pxLink->pxNextFreeBlock == NULL )
|
||||
{
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
* allocated. */
|
||||
heapFREE_BLOCK( pxLink );
|
||||
#if ( configHEAP_CLEAR_MEMORY_ON_FREE == 1 )
|
||||
{
|
||||
/* Check for underflow as this can occur if xBlockSize is
|
||||
* overwritten in a heap block. */
|
||||
if( heapSUBTRACT_WILL_UNDERFLOW( pxLink->xBlockSize, xHeapStructSize ) == 0 )
|
||||
{
|
||||
( void ) memset( puc + xHeapStructSize, 0, pxLink->xBlockSize - xHeapStructSize );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
SEGGER_SYSVIEW_HeapFree(&xStart, pv);
|
||||
#else
|
||||
traceFREE( pv, pxLink->xBlockSize );
|
||||
#endif
|
||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||
xNumberOfSuccessfulFrees++;
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetFreeHeapSize( void )
|
||||
{
|
||||
return xFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void )
|
||||
{
|
||||
return xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortInitialiseBlocks( void )
|
||||
{
|
||||
/* This just exists to keep the linker quiet. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void * pvPortCalloc( size_t xNum,
|
||||
size_t xSize )
|
||||
{
|
||||
void * pv = NULL;
|
||||
|
||||
if( heapMULTIPLY_WILL_OVERFLOW( xNum, xSize ) == 0 )
|
||||
{
|
||||
pv = pvPortMalloc( xNum * xSize );
|
||||
|
||||
if( pv != NULL )
|
||||
{
|
||||
( void ) memset( pv, 0, xNum * xSize );
|
||||
}
|
||||
}
|
||||
|
||||
return pv;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvHeapInit( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
BlockLink_t * pxFirstFreeBlock;
|
||||
portPOINTER_SIZE_TYPE uxStartAddress, uxEndAddress;
|
||||
size_t xTotalHeapSize = configTOTAL_HEAP_SIZE;
|
||||
|
||||
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||
uxStartAddress = ( portPOINTER_SIZE_TYPE ) ucHeap;
|
||||
|
||||
if( ( uxStartAddress & portBYTE_ALIGNMENT_MASK ) != 0 )
|
||||
{
|
||||
uxStartAddress += ( portBYTE_ALIGNMENT - 1 );
|
||||
uxStartAddress &= ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK );
|
||||
xTotalHeapSize -= ( size_t ) ( uxStartAddress - ( portPOINTER_SIZE_TYPE ) ucHeap );
|
||||
}
|
||||
|
||||
#if ( configENABLE_HEAP_PROTECTOR == 1 )
|
||||
{
|
||||
vApplicationGetRandomHeapCanary( &( xHeapCanary ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* xStart is used to hold a pointer to the first item in the list of free
|
||||
* blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = ( void * ) heapPROTECT_BLOCK_POINTER( uxStartAddress );
|
||||
xStart.xBlockSize = ( size_t ) 0;
|
||||
|
||||
/* pxEnd is used to mark the end of the list of free blocks and is inserted
|
||||
* at the end of the heap space. */
|
||||
uxEndAddress = uxStartAddress + ( portPOINTER_SIZE_TYPE ) xTotalHeapSize;
|
||||
uxEndAddress -= ( portPOINTER_SIZE_TYPE ) xHeapStructSize;
|
||||
uxEndAddress &= ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK );
|
||||
pxEnd = ( BlockLink_t * ) uxEndAddress;
|
||||
pxEnd->xBlockSize = 0;
|
||||
pxEnd->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( NULL );
|
||||
|
||||
/* To start with there is a single free block that is sized to take up the
|
||||
* entire heap space, minus the space taken by pxEnd. */
|
||||
pxFirstFreeBlock = ( BlockLink_t * ) uxStartAddress;
|
||||
pxFirstFreeBlock->xBlockSize = ( size_t ) ( uxEndAddress - ( portPOINTER_SIZE_TYPE ) pxFirstFreeBlock );
|
||||
pxFirstFreeBlock->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxEnd );
|
||||
|
||||
/* Only one block exists - and it covers the entire usable heap space. */
|
||||
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
SEGGER_SYSVIEW_HeapDefine(ucHeap, ucHeap, sizeof(ucHeap), sizeof(BlockLink_t));
|
||||
SEGGER_SYSVIEW_NameResource((uint32_t)ucHeap, "heap4");
|
||||
#endif
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
BlockLink_t * pxIterator;
|
||||
uint8_t * puc;
|
||||
|
||||
/* Iterate through the list until a block is found that has a higher address
|
||||
* than the block being inserted. */
|
||||
for( pxIterator = &xStart; heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock ) < pxBlockToInsert; pxIterator = heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock ) )
|
||||
{
|
||||
/* Nothing to do here, just iterate to the right position. */
|
||||
}
|
||||
|
||||
if( pxIterator != &xStart )
|
||||
{
|
||||
heapVALIDATE_BLOCK_POINTER( pxIterator );
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted after
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxIterator;
|
||||
|
||||
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
|
||||
{
|
||||
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||
pxBlockToInsert = pxIterator;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted before
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxBlockToInsert;
|
||||
|
||||
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock ) )
|
||||
{
|
||||
if( heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock ) != pxEnd )
|
||||
{
|
||||
/* Form one big block from the two blocks. */
|
||||
pxBlockToInsert->xBlockSize += heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock )->xBlockSize;
|
||||
pxBlockToInsert->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock )->pxNextFreeBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxEnd );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the block being inserted plugged a gab, so was merged with the block
|
||||
* before and the block after, then it's pxNextFreeBlock pointer will have
|
||||
* already been set, and should not be set here as that would make it point
|
||||
* to itself. */
|
||||
if( pxIterator != pxBlockToInsert )
|
||||
{
|
||||
pxIterator->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxBlockToInsert );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortGetHeapStats( HeapStats_t * pxHeapStats )
|
||||
{
|
||||
BlockLink_t * pxBlock;
|
||||
size_t xBlocks = 0, xMaxSize = 0, xMinSize = portMAX_DELAY; /* portMAX_DELAY used as a portable way of getting the maximum value. */
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
pxBlock = heapPROTECT_BLOCK_POINTER( xStart.pxNextFreeBlock );
|
||||
|
||||
/* pxBlock will be NULL if the heap has not been initialised. The heap
|
||||
* is initialised automatically when the first allocation is made. */
|
||||
if( pxBlock != NULL )
|
||||
{
|
||||
while( pxBlock != pxEnd )
|
||||
{
|
||||
/* Increment the number of blocks and record the largest block seen
|
||||
* so far. */
|
||||
xBlocks++;
|
||||
|
||||
if( pxBlock->xBlockSize > xMaxSize )
|
||||
{
|
||||
xMaxSize = pxBlock->xBlockSize;
|
||||
}
|
||||
|
||||
if( pxBlock->xBlockSize < xMinSize )
|
||||
{
|
||||
xMinSize = pxBlock->xBlockSize;
|
||||
}
|
||||
|
||||
/* Move to the next block in the chain until the last block is
|
||||
* reached. */
|
||||
pxBlock = heapPROTECT_BLOCK_POINTER( pxBlock->pxNextFreeBlock );
|
||||
}
|
||||
}
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
pxHeapStats->xSizeOfLargestFreeBlockInBytes = xMaxSize;
|
||||
pxHeapStats->xSizeOfSmallestFreeBlockInBytes = xMinSize;
|
||||
pxHeapStats->xNumberOfFreeBlocks = xBlocks;
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
pxHeapStats->xAvailableHeapSpaceInBytes = xFreeBytesRemaining;
|
||||
pxHeapStats->xNumberOfSuccessfulAllocations = xNumberOfSuccessfulAllocations;
|
||||
pxHeapStats->xNumberOfSuccessfulFrees = xNumberOfSuccessfulFrees;
|
||||
pxHeapStats->xMinimumEverFreeBytesRemaining = xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
#if 1 /* << EST */
|
||||
void vPortInitializeHeap(void) {
|
||||
pxEnd = NULL; /* force initialization of heap next time a block gets allocated */
|
||||
xStart.pxNextFreeBlock = NULL;
|
||||
xStart.xBlockSize = 0;
|
||||
xFreeBytesRemaining = 0;
|
||||
xMinimumEverFreeBytesRemaining = 0;
|
||||
}
|
||||
|
||||
#include <string.h> /* for memcpy() */
|
||||
#if 0
|
||||
void *pvPortRealloc(void *ptr, size_t new_size) {
|
||||
void *newBlock;
|
||||
uint8_t *puc;
|
||||
BlockLink_t *pxLink;
|
||||
size_t old_size;
|
||||
|
||||
if (ptr==NULL) { /* if it is NULL, return a new block */
|
||||
return pvPortMalloc(new_size);
|
||||
}
|
||||
if (new_size==0) { /* if new size is zero, free up memory and return NULL */
|
||||
vPortFree(ptr);
|
||||
return NULL;
|
||||
}
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
* before it. */
|
||||
puc = (uint8_t*)ptr;
|
||||
puc -= xHeapStructSize;
|
||||
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = (void *)puc;
|
||||
configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
||||
|
||||
old_size = (pxLink->xBlockSize & ~xBlockAllocatedBit)-xHeapStructSize;
|
||||
if (new_size==old_size) { /* same size: don't need to do anything */
|
||||
return ptr;
|
||||
}
|
||||
newBlock = pvPortMalloc(new_size); /* allocate new block */
|
||||
if (newBlock==NULL) {
|
||||
return NULL; /* if there is not enough memory, the old block is not freed and NULL is returned */
|
||||
}
|
||||
if (old_size>new_size) { /* shrink memory block? */
|
||||
old_size = new_size; /* make sure we only copy up to the new size */
|
||||
}
|
||||
memcpy(newBlock, ptr, old_size); /* copy old content to new block */
|
||||
vPortFree(ptr); /* free old block */
|
||||
return newBlock;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* configUSE_HEAP_SCHEME==4 */ /* << EST */
|
||||
|
||||
755
pico-sensor/McuLib/FreeRTOS/Source/portable/MemMang/heap_5.c
Normal file
755
pico-sensor/McuLib/FreeRTOS/Source/portable/MemMang/heap_5.c
Normal file
@@ -0,0 +1,755 @@
|
||||
/* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* << EST */
|
||||
#include "FreeRTOSConfig.h"
|
||||
#if !defined(configUSE_HEAP_SCHEME) || (configUSE_HEAP_SCHEME==5 && configSUPPORT_DYNAMIC_ALLOCATION==1)
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* A sample implementation of pvPortMalloc() that allows the heap to be defined
|
||||
* across multiple non-contiguous blocks and combines (coalescences) adjacent
|
||||
* memory blocks as they are freed.
|
||||
*
|
||||
* See heap_1.c, heap_2.c, heap_3.c and heap_4.c for alternative
|
||||
* implementations, and the memory management pages of https://www.FreeRTOS.org
|
||||
* for more information.
|
||||
*
|
||||
* Usage notes:
|
||||
*
|
||||
* vPortDefineHeapRegions() ***must*** be called before pvPortMalloc().
|
||||
* pvPortMalloc() will be called if any task objects (tasks, queues, event
|
||||
* groups, etc.) are created, therefore vPortDefineHeapRegions() ***must*** be
|
||||
* called before any other objects are defined.
|
||||
*
|
||||
* vPortDefineHeapRegions() takes a single parameter. The parameter is an array
|
||||
* of HeapRegion_t structures. HeapRegion_t is defined in portable.h as
|
||||
*
|
||||
* typedef struct HeapRegion
|
||||
* {
|
||||
* uint8_t *pucStartAddress; << Start address of a block of memory that will be part of the heap.
|
||||
* size_t xSizeInBytes; << Size of the block of memory.
|
||||
* } HeapRegion_t;
|
||||
*
|
||||
* The array is terminated using a NULL zero sized region definition, and the
|
||||
* memory regions defined in the array ***must*** appear in address order from
|
||||
* low address to high address. So the following is a valid example of how
|
||||
* to use the function.
|
||||
*
|
||||
* HeapRegion_t xHeapRegions[] =
|
||||
* {
|
||||
* { ( uint8_t * ) 0x80000000UL, 0x10000 }, << Defines a block of 0x10000 bytes starting at address 0x80000000
|
||||
* { ( uint8_t * ) 0x90000000UL, 0xa0000 }, << Defines a block of 0xa0000 bytes starting at address of 0x90000000
|
||||
* { NULL, 0 } << Terminates the array.
|
||||
* };
|
||||
*
|
||||
* vPortDefineHeapRegions( xHeapRegions ); << Pass the array into vPortDefineHeapRegions().
|
||||
*
|
||||
* Note 0x80000000 is the lower address so appears in the array first.
|
||||
*
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||
* all the API functions to use the MPU wrappers. That should only be done when
|
||||
* task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
#include "SEGGER_SYSVIEW_Conf.h"
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
#endif
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
|
||||
#error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
|
||||
#endif
|
||||
|
||||
#ifndef configHEAP_CLEAR_MEMORY_ON_FREE
|
||||
#define configHEAP_CLEAR_MEMORY_ON_FREE 0
|
||||
#endif
|
||||
|
||||
/* Block sizes must not get too small. */
|
||||
#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
|
||||
|
||||
/* Assumes 8bit bytes! */
|
||||
#define heapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
|
||||
/* Max value that fits in a size_t type. */
|
||||
#define heapSIZE_MAX ( ~( ( size_t ) 0 ) )
|
||||
|
||||
/* Check if multiplying a and b will result in overflow. */
|
||||
#define heapMULTIPLY_WILL_OVERFLOW( a, b ) ( ( ( a ) > 0 ) && ( ( b ) > ( heapSIZE_MAX / ( a ) ) ) )
|
||||
|
||||
/* Check if adding a and b will result in overflow. */
|
||||
#define heapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( heapSIZE_MAX - ( b ) ) )
|
||||
|
||||
/* Check if the subtraction operation ( a - b ) will result in underflow. */
|
||||
#define heapSUBTRACT_WILL_UNDERFLOW( a, b ) ( ( a ) < ( b ) )
|
||||
|
||||
/* MSB of the xBlockSize member of an BlockLink_t structure is used to track
|
||||
* the allocation status of a block. When MSB of the xBlockSize member of
|
||||
* an BlockLink_t structure is set then the block belongs to the application.
|
||||
* When the bit is free the block is still part of the free heap space. */
|
||||
#define heapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ) )
|
||||
#define heapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & heapBLOCK_ALLOCATED_BITMASK ) == 0 )
|
||||
#define heapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & heapBLOCK_ALLOCATED_BITMASK ) != 0 )
|
||||
#define heapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= heapBLOCK_ALLOCATED_BITMASK )
|
||||
#define heapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~heapBLOCK_ALLOCATED_BITMASK )
|
||||
|
||||
/* Setting configENABLE_HEAP_PROTECTOR to 1 enables heap block pointers
|
||||
* protection using an application supplied canary value to catch heap
|
||||
* corruption should a heap buffer overflow occur.
|
||||
*/
|
||||
#if ( configENABLE_HEAP_PROTECTOR == 1 )
|
||||
|
||||
/* Macro to load/store BlockLink_t pointers to memory. By XORing the
|
||||
* pointers with a random canary value, heap overflows will result
|
||||
* in randomly unpredictable pointer values which will be caught by
|
||||
* heapVALIDATE_BLOCK_POINTER assert. */
|
||||
#define heapPROTECT_BLOCK_POINTER( pxBlock ) ( ( BlockLink_t * ) ( ( ( portPOINTER_SIZE_TYPE ) ( pxBlock ) ) ^ xHeapCanary ) )
|
||||
|
||||
/* Assert that a heap block pointer is within the heap bounds. */
|
||||
#define heapVALIDATE_BLOCK_POINTER( pxBlock ) \
|
||||
configASSERT( ( pucHeapHighAddress != NULL ) && \
|
||||
( pucHeapLowAddress != NULL ) && \
|
||||
( ( uint8_t * ) ( pxBlock ) >= pucHeapLowAddress ) && \
|
||||
( ( uint8_t * ) ( pxBlock ) < pucHeapHighAddress ) )
|
||||
|
||||
#else /* if ( configENABLE_HEAP_PROTECTOR == 1 ) */
|
||||
|
||||
#define heapPROTECT_BLOCK_POINTER( pxBlock ) ( pxBlock )
|
||||
|
||||
#define heapVALIDATE_BLOCK_POINTER( pxBlock )
|
||||
|
||||
#endif /* configENABLE_HEAP_PROTECTOR */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Define the linked list structure. This is used to link free blocks in order
|
||||
* of their memory address. */
|
||||
typedef struct A_BLOCK_LINK
|
||||
{
|
||||
struct A_BLOCK_LINK * pxNextFreeBlock; /**< The next free block in the list. */
|
||||
size_t xBlockSize; /**< The size of the free block. */
|
||||
} BlockLink_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Inserts a block of memory that is being freed into the correct position in
|
||||
* the list of free memory blocks. The block being freed will be merged with
|
||||
* the block in front it and/or the block behind it if the memory blocks are
|
||||
* adjacent to each other.
|
||||
*/
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) PRIVILEGED_FUNCTION;
|
||||
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#if ( configENABLE_HEAP_PROTECTOR == 1 )
|
||||
|
||||
/**
|
||||
* @brief Application provided function to get a random value to be used as canary.
|
||||
*
|
||||
* @param pxHeapCanary [out] Output parameter to return the canary value.
|
||||
*/
|
||||
extern void vApplicationGetRandomHeapCanary( portPOINTER_SIZE_TYPE * pxHeapCanary );
|
||||
#endif /* configENABLE_HEAP_PROTECTOR */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The size of the structure placed at the beginning of each allocated memory
|
||||
* block must by correctly byte aligned. */
|
||||
static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
|
||||
|
||||
/* Create a couple of list links to mark the start and end of the list. */
|
||||
PRIVILEGED_DATA static BlockLink_t xStart;
|
||||
PRIVILEGED_DATA static BlockLink_t * pxEnd = NULL;
|
||||
|
||||
/* Keeps track of the number of calls to allocate and free memory as well as the
|
||||
* number of free bytes remaining, but says nothing about fragmentation. */
|
||||
PRIVILEGED_DATA static size_t xFreeBytesRemaining = 0U;
|
||||
PRIVILEGED_DATA static size_t xMinimumEverFreeBytesRemaining = 0U;
|
||||
PRIVILEGED_DATA static size_t xNumberOfSuccessfulAllocations = 0;
|
||||
PRIVILEGED_DATA static size_t xNumberOfSuccessfulFrees = 0;
|
||||
|
||||
#if ( configENABLE_HEAP_PROTECTOR == 1 )
|
||||
|
||||
/* Canary value for protecting internal heap pointers. */
|
||||
PRIVILEGED_DATA static portPOINTER_SIZE_TYPE xHeapCanary;
|
||||
|
||||
/* Highest and lowest heap addresses used for heap block bounds checking. */
|
||||
PRIVILEGED_DATA static uint8_t * pucHeapHighAddress = NULL;
|
||||
PRIVILEGED_DATA static uint8_t * pucHeapLowAddress = NULL;
|
||||
|
||||
#endif /* configENABLE_HEAP_PROTECTOR */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void * pvPortMallocExt( size_t xWantedSize, unsigned int heapTag) /* << EST */
|
||||
{
|
||||
BlockLink_t * pxBlock;
|
||||
BlockLink_t * pxPreviousBlock;
|
||||
BlockLink_t * pxNewBlockLink;
|
||||
void * pvReturn = NULL;
|
||||
size_t xAdditionalRequiredSize;
|
||||
|
||||
/* The heap must be initialised before the first call to
|
||||
* pvPortMalloc(). */
|
||||
configASSERT( pxEnd );
|
||||
|
||||
if( xWantedSize > 0 )
|
||||
{
|
||||
/* The wanted size must be increased so it can contain a BlockLink_t
|
||||
* structure in addition to the requested amount of bytes. */
|
||||
if( heapADD_WILL_OVERFLOW( xWantedSize, xHeapStructSize ) == 0 )
|
||||
{
|
||||
xWantedSize += xHeapStructSize;
|
||||
|
||||
/* Ensure that blocks are always aligned to the required number
|
||||
* of bytes. */
|
||||
if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||
{
|
||||
/* Byte alignment required. */
|
||||
xAdditionalRequiredSize = portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK );
|
||||
|
||||
if( heapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 )
|
||||
{
|
||||
xWantedSize += xAdditionalRequiredSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
xWantedSize = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
xWantedSize = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Check the block size we are trying to allocate is not so large that the
|
||||
* top bit is set. The top bit of the block size member of the BlockLink_t
|
||||
* structure is used to determine who owns the block - the application or
|
||||
* the kernel, so it must be free. */
|
||||
if( heapBLOCK_SIZE_IS_VALID( xWantedSize ) != 0 )
|
||||
{
|
||||
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
||||
{
|
||||
/* Traverse the list from the start (lowest address) block until
|
||||
* one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = heapPROTECT_BLOCK_POINTER( xStart.pxNextFreeBlock );
|
||||
heapVALIDATE_BLOCK_POINTER( pxBlock );
|
||||
|
||||
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != heapPROTECT_BLOCK_POINTER( NULL ) ) )
|
||||
{
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = heapPROTECT_BLOCK_POINTER( pxBlock->pxNextFreeBlock );
|
||||
heapVALIDATE_BLOCK_POINTER( pxBlock );
|
||||
}
|
||||
|
||||
/* If the end marker was reached then a block of adequate size
|
||||
* was not found. */
|
||||
if( pxBlock != pxEnd )
|
||||
{
|
||||
/* Return the memory space pointed to - jumping over the
|
||||
* BlockLink_t structure at its start. */
|
||||
pvReturn = ( void * ) ( ( ( uint8_t * ) heapPROTECT_BLOCK_POINTER( pxPreviousBlock->pxNextFreeBlock ) ) + xHeapStructSize );
|
||||
heapVALIDATE_BLOCK_POINTER( pvReturn );
|
||||
|
||||
/* This block is being returned for use so must be taken out
|
||||
* of the list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
|
||||
/* If the block is larger than required it can be split into
|
||||
* two. */
|
||||
configASSERT( heapSUBTRACT_WILL_UNDERFLOW( pxBlock->xBlockSize, xWantedSize ) == 0 );
|
||||
|
||||
if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
|
||||
{
|
||||
/* This block is to be split into two. Create a new
|
||||
* block following the number of bytes requested. The void
|
||||
* cast is used to prevent byte alignment warnings from the
|
||||
* compiler. */
|
||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||
configASSERT( ( ( ( size_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
|
||||
/* Calculate the sizes of two blocks split from the
|
||||
* single block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
|
||||
/* Insert the new block into the list of free blocks. */
|
||||
pxNewBlockLink->pxNextFreeBlock = pxPreviousBlock->pxNextFreeBlock;
|
||||
pxPreviousBlock->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxNewBlockLink );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
|
||||
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
||||
{
|
||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* The block is being returned - it is allocated and owned
|
||||
* by the application and has no "next" block. */
|
||||
heapALLOCATE_BLOCK( pxBlock );
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
xNumberOfSuccessfulAllocations++;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
if (heapTag!=(unsigned)-1) {
|
||||
SEGGER_SYSVIEW_HeapAllocEx(&xStart, pvReturn, xWantedSize, heapTag);
|
||||
} else {
|
||||
SEGGER_SYSVIEW_HeapAlloc(&xStart, pvReturn, xWantedSize);
|
||||
}
|
||||
#else
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
#endif
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
#if ( configUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
#if 1 /* << EST: Using configuration macro name for hook */
|
||||
extern void configUSE_MALLOC_FAILED_HOOK_NAME( void );
|
||||
configUSE_MALLOC_FAILED_HOOK_NAME();
|
||||
#else /* << EST */
|
||||
vApplicationMallocFailedHook();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif /* if ( configUSE_MALLOC_FAILED_HOOK == 1 ) */
|
||||
|
||||
configASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) portBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void *pvPortMalloc(size_t xWantedSize) { /* << EST */
|
||||
return pvPortMallocExt(xWantedSize, -1);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFree( void * pv )
|
||||
{
|
||||
uint8_t * puc = ( uint8_t * ) pv;
|
||||
BlockLink_t * pxLink;
|
||||
|
||||
if( pv != NULL )
|
||||
{
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
* before it. */
|
||||
puc -= xHeapStructSize;
|
||||
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = ( void * ) puc;
|
||||
|
||||
heapVALIDATE_BLOCK_POINTER( pxLink );
|
||||
configASSERT( heapBLOCK_IS_ALLOCATED( pxLink ) != 0 );
|
||||
configASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||
|
||||
if( heapBLOCK_IS_ALLOCATED( pxLink ) != 0 )
|
||||
{
|
||||
if( pxLink->pxNextFreeBlock == NULL )
|
||||
{
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
* allocated. */
|
||||
heapFREE_BLOCK( pxLink );
|
||||
#if ( configHEAP_CLEAR_MEMORY_ON_FREE == 1 )
|
||||
{
|
||||
/* Check for underflow as this can occur if xBlockSize is
|
||||
* overwritten in a heap block. */
|
||||
if( heapSUBTRACT_WILL_UNDERFLOW( pxLink->xBlockSize, xHeapStructSize ) == 0 )
|
||||
{
|
||||
( void ) memset( puc + xHeapStructSize, 0, pxLink->xBlockSize - xHeapStructSize );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
SEGGER_SYSVIEW_HeapFree(&xStart, pv);
|
||||
#else
|
||||
traceFREE( pv, pxLink->xBlockSize );
|
||||
#endif
|
||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||
xNumberOfSuccessfulFrees++;
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetFreeHeapSize( void )
|
||||
{
|
||||
return xFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void )
|
||||
{
|
||||
return xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void * pvPortCalloc( size_t xNum,
|
||||
size_t xSize )
|
||||
{
|
||||
void * pv = NULL;
|
||||
|
||||
if( heapMULTIPLY_WILL_OVERFLOW( xNum, xSize ) == 0 )
|
||||
{
|
||||
pv = pvPortMalloc( xNum * xSize);
|
||||
|
||||
if( pv != NULL )
|
||||
{
|
||||
( void ) memset( pv, 0, xNum * xSize );
|
||||
}
|
||||
}
|
||||
|
||||
return pv;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
BlockLink_t * pxIterator;
|
||||
uint8_t * puc;
|
||||
|
||||
/* Iterate through the list until a block is found that has a higher address
|
||||
* than the block being inserted. */
|
||||
for( pxIterator = &xStart; heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock ) < pxBlockToInsert; pxIterator = heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock ) )
|
||||
{
|
||||
/* Nothing to do here, just iterate to the right position. */
|
||||
}
|
||||
|
||||
if( pxIterator != &xStart )
|
||||
{
|
||||
heapVALIDATE_BLOCK_POINTER( pxIterator );
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted after
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxIterator;
|
||||
|
||||
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
|
||||
{
|
||||
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||
pxBlockToInsert = pxIterator;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted before
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxBlockToInsert;
|
||||
|
||||
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock ) )
|
||||
{
|
||||
if( heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock ) != pxEnd )
|
||||
{
|
||||
/* Form one big block from the two blocks. */
|
||||
pxBlockToInsert->xBlockSize += heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock )->xBlockSize;
|
||||
pxBlockToInsert->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock )->pxNextFreeBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxEnd );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the block being inserted plugged a gap, so was merged with the block
|
||||
* before and the block after, then it's pxNextFreeBlock pointer will have
|
||||
* already been set, and should not be set here as that would make it point
|
||||
* to itself. */
|
||||
if( pxIterator != pxBlockToInsert )
|
||||
{
|
||||
pxIterator->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxBlockToInsert );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
BlockLink_t * pxFirstFreeBlockInRegion = NULL;
|
||||
BlockLink_t * pxPreviousFreeBlock;
|
||||
portPOINTER_SIZE_TYPE xAlignedHeap;
|
||||
size_t xTotalRegionSize, xTotalHeapSize = 0;
|
||||
BaseType_t xDefinedRegions = 0;
|
||||
portPOINTER_SIZE_TYPE xAddress;
|
||||
const HeapRegion_t * pxHeapRegion;
|
||||
|
||||
/* Can only call once! */
|
||||
configASSERT( pxEnd == NULL );
|
||||
|
||||
#if ( configENABLE_HEAP_PROTECTOR == 1 )
|
||||
{
|
||||
vApplicationGetRandomHeapCanary( &( xHeapCanary ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] );
|
||||
|
||||
while( pxHeapRegion->xSizeInBytes > 0 )
|
||||
{
|
||||
xTotalRegionSize = pxHeapRegion->xSizeInBytes;
|
||||
|
||||
/* Ensure the heap region starts on a correctly aligned boundary. */
|
||||
xAddress = ( portPOINTER_SIZE_TYPE ) pxHeapRegion->pucStartAddress;
|
||||
|
||||
if( ( xAddress & portBYTE_ALIGNMENT_MASK ) != 0 )
|
||||
{
|
||||
xAddress += ( portBYTE_ALIGNMENT - 1 );
|
||||
xAddress &= ~( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK;
|
||||
|
||||
/* Adjust the size for the bytes lost to alignment. */
|
||||
xTotalRegionSize -= ( size_t ) ( xAddress - ( portPOINTER_SIZE_TYPE ) pxHeapRegion->pucStartAddress );
|
||||
}
|
||||
|
||||
xAlignedHeap = xAddress;
|
||||
|
||||
/* Set xStart if it has not already been set. */
|
||||
if( xDefinedRegions == 0 )
|
||||
{
|
||||
/* xStart is used to hold a pointer to the first item in the list of
|
||||
* free blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = ( BlockLink_t * ) heapPROTECT_BLOCK_POINTER( xAlignedHeap );
|
||||
xStart.xBlockSize = ( size_t ) 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Should only get here if one region has already been added to the
|
||||
* heap. */
|
||||
configASSERT( pxEnd != heapPROTECT_BLOCK_POINTER( NULL ) );
|
||||
|
||||
/* Check blocks are passed in with increasing start addresses. */
|
||||
configASSERT( ( size_t ) xAddress > ( size_t ) pxEnd );
|
||||
}
|
||||
|
||||
#if ( configENABLE_HEAP_PROTECTOR == 1 )
|
||||
{
|
||||
if( ( pucHeapLowAddress == NULL ) ||
|
||||
( ( uint8_t * ) xAlignedHeap < pucHeapLowAddress ) )
|
||||
{
|
||||
pucHeapLowAddress = ( uint8_t * ) xAlignedHeap;
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_HEAP_PROTECTOR */
|
||||
|
||||
/* Remember the location of the end marker in the previous region, if
|
||||
* any. */
|
||||
pxPreviousFreeBlock = pxEnd;
|
||||
|
||||
/* pxEnd is used to mark the end of the list of free blocks and is
|
||||
* inserted at the end of the region space. */
|
||||
xAddress = xAlignedHeap + ( portPOINTER_SIZE_TYPE ) xTotalRegionSize;
|
||||
xAddress -= ( portPOINTER_SIZE_TYPE ) xHeapStructSize;
|
||||
xAddress &= ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK );
|
||||
pxEnd = ( BlockLink_t * ) xAddress;
|
||||
pxEnd->xBlockSize = 0;
|
||||
pxEnd->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( NULL );
|
||||
|
||||
/* To start with there is a single free block in this region that is
|
||||
* sized to take up the entire heap region minus the space taken by the
|
||||
* free block structure. */
|
||||
pxFirstFreeBlockInRegion = ( BlockLink_t * ) xAlignedHeap;
|
||||
pxFirstFreeBlockInRegion->xBlockSize = ( size_t ) ( xAddress - ( portPOINTER_SIZE_TYPE ) pxFirstFreeBlockInRegion );
|
||||
pxFirstFreeBlockInRegion->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxEnd );
|
||||
|
||||
/* If this is not the first region that makes up the entire heap space
|
||||
* then link the previous region to this region. */
|
||||
if( pxPreviousFreeBlock != NULL )
|
||||
{
|
||||
pxPreviousFreeBlock->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxFirstFreeBlockInRegion );
|
||||
}
|
||||
|
||||
xTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize;
|
||||
|
||||
#if ( configENABLE_HEAP_PROTECTOR == 1 )
|
||||
{
|
||||
if( ( pucHeapHighAddress == NULL ) ||
|
||||
( ( ( ( uint8_t * ) pxFirstFreeBlockInRegion ) + pxFirstFreeBlockInRegion->xBlockSize ) > pucHeapHighAddress ) )
|
||||
{
|
||||
pucHeapHighAddress = ( ( uint8_t * ) pxFirstFreeBlockInRegion ) + pxFirstFreeBlockInRegion->xBlockSize;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Move onto the next HeapRegion_t structure. */
|
||||
xDefinedRegions++;
|
||||
pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] );
|
||||
}
|
||||
|
||||
xMinimumEverFreeBytesRemaining = xTotalHeapSize;
|
||||
xFreeBytesRemaining = xTotalHeapSize;
|
||||
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
SEGGER_SYSVIEW_HeapDefine(&xStart, xStart.pxNextFreeBlock, xTotalHeapSize, sizeof(BlockLink_t));
|
||||
SEGGER_SYSVIEW_NameResource((uint32_t)&xStart, "heap5");
|
||||
#endif
|
||||
/* Check something was actually defined before it is accessed. */
|
||||
configASSERT( xTotalHeapSize );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortGetHeapStats( HeapStats_t * pxHeapStats )
|
||||
{
|
||||
BlockLink_t * pxBlock;
|
||||
size_t xBlocks = 0, xMaxSize = 0, xMinSize = portMAX_DELAY; /* portMAX_DELAY used as a portable way of getting the maximum value. */
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
pxBlock = heapPROTECT_BLOCK_POINTER( xStart.pxNextFreeBlock );
|
||||
|
||||
/* pxBlock will be NULL if the heap has not been initialised. The heap
|
||||
* is initialised automatically when the first allocation is made. */
|
||||
if( pxBlock != NULL )
|
||||
{
|
||||
while( pxBlock != pxEnd )
|
||||
{
|
||||
/* Increment the number of blocks and record the largest block seen
|
||||
* so far. */
|
||||
xBlocks++;
|
||||
|
||||
if( pxBlock->xBlockSize > xMaxSize )
|
||||
{
|
||||
xMaxSize = pxBlock->xBlockSize;
|
||||
}
|
||||
|
||||
/* Heap five will have a zero sized block at the end of each
|
||||
* each region - the block is only used to link to the next
|
||||
* heap region so it not a real block. */
|
||||
if( pxBlock->xBlockSize != 0 )
|
||||
{
|
||||
if( pxBlock->xBlockSize < xMinSize )
|
||||
{
|
||||
xMinSize = pxBlock->xBlockSize;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move to the next block in the chain until the last block is
|
||||
* reached. */
|
||||
pxBlock = heapPROTECT_BLOCK_POINTER( pxBlock->pxNextFreeBlock );
|
||||
}
|
||||
}
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
pxHeapStats->xSizeOfLargestFreeBlockInBytes = xMaxSize;
|
||||
pxHeapStats->xSizeOfSmallestFreeBlockInBytes = xMinSize;
|
||||
pxHeapStats->xNumberOfFreeBlocks = xBlocks;
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
pxHeapStats->xAvailableHeapSpaceInBytes = xFreeBytesRemaining;
|
||||
pxHeapStats->xNumberOfSuccessfulAllocations = xNumberOfSuccessfulAllocations;
|
||||
pxHeapStats->xNumberOfSuccessfulFrees = xNumberOfSuccessfulFrees;
|
||||
pxHeapStats->xMinimumEverFreeBytesRemaining = xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
#if 1 /* << EST */
|
||||
void vPortInitializeHeap(void) {
|
||||
xStart.pxNextFreeBlock = NULL;
|
||||
xStart.xBlockSize = 0;
|
||||
pxEnd = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#endif /* configUSE_HEAP_SCHEME==5 */ /* << EST */
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
/* Copyright (C) Dave Nadler 2017, All Rights Reserved. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
#if !defined(configUSE_HEAP_SCHEME) || (configUSE_HEAP_SCHEME==6)
|
||||
/**
|
||||
* \file heap_useNewlib.c
|
||||
* \brief Wrappers required to use newlib malloc-family within FreeRTOS.
|
||||
*
|
||||
* \par Overview
|
||||
* Route FreeRTOS memory management functions to newlib's malloc family.
|
||||
* Thus newlib and FreeRTOS share memory-management routines and memory pool,
|
||||
* and all newlib's internal memory-management requirements are supported.
|
||||
*
|
||||
* \author Dave Nadler
|
||||
* \date 1-July-2017
|
||||
*
|
||||
* \see https://sourceware.org/newlib/libc.html#Reentrancy
|
||||
* \see https://sourceware.org/newlib/libc.html#malloc
|
||||
* \see https://sourceware.org/newlib/libc.html#index-_005f_005fenv_005flock
|
||||
* \see https://sourceware.org/newlib/libc.html#index-_005f_005fmalloc_005flock
|
||||
* \see https://sourceforge.net/p/freertos/feature-requests/72/
|
||||
* \see http://www.billgatliff.com/newlib.html
|
||||
* \see http://wiki.osdev.org/Porting_Newlib
|
||||
* \see http://www.embecosm.com/appnotes/ean9/ean9-howto-newlib-1.0.html
|
||||
*
|
||||
*
|
||||
* \copyright
|
||||
* (c) Dave Nadler 2017, All Rights Reserved.
|
||||
* Web: http://www.nadler.com
|
||||
* email: drn@nadler.com
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Use or redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions, ALL ORIGINAL COMMENTS, 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.
|
||||
*
|
||||
* 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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 <stdlib.h> // maps to newlib...
|
||||
#include <malloc.h> // mallinfo...
|
||||
#include <errno.h> // ENOMEM
|
||||
|
||||
#include "FreeRTOS.h" // defines public interface we're implementing here
|
||||
#if !defined(configUSE_NEWLIB_REENTRANT) || (configUSE_NEWLIB_REENTRANT!=1)
|
||||
#warning "#define configUSE_NEWLIB_REENTRANT 1 // Required for thread-safety of newlib sprintf, strtok, etc..."
|
||||
// If you're *really* sure you don't need FreeRTOS's newlib reentrancy support, remove this warning...
|
||||
#endif
|
||||
#include "task.h"
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
#include "SEGGER_SYSVIEW_Conf.h"
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
#endif
|
||||
|
||||
// ================================================================================================
|
||||
// External routines required by newlib's malloc (sbrk/_sbrk, __malloc_lock/unlock)
|
||||
// ================================================================================================
|
||||
|
||||
#if 0 // suggested minimal implementation from https://sourceware.org/newlib/libc.html#Syscalls:
|
||||
// sbrk: Increase program data space. As malloc and related functions depend on this,
|
||||
// it is useful to have a working implementation. The following suffices for a standalone system;
|
||||
// it exploits the symbol _end automatically defined by the GNU linker.
|
||||
caddr_t sbrk(int incr) {
|
||||
extern char _end; /* Defined by the linker */
|
||||
static char *heap_end;
|
||||
char *prev_heap_end;
|
||||
if (heap_end == 0) {
|
||||
heap_end = &_end;
|
||||
}
|
||||
prev_heap_end = heap_end;
|
||||
if (heap_end + incr > stack_ptr) {
|
||||
write (1, "Heap and stack collision\n", 25);
|
||||
abort ();
|
||||
}
|
||||
heap_end += incr;
|
||||
return (caddr_t) prev_heap_end;
|
||||
}
|
||||
#endif
|
||||
#if 0 // Freescale implementation
|
||||
caddr_t _sbrk(int incr)
|
||||
{
|
||||
extern char end __asm("end");
|
||||
extern char heap_limit __asm("__HeapLimit");
|
||||
static char *heap_end;
|
||||
char *prev_heap_end;
|
||||
if (heap_end == NULL)
|
||||
heap_end = &end;
|
||||
prev_heap_end = heap_end;
|
||||
if (heap_end + incr > &heap_limit)
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return (caddr_t)-1;
|
||||
}
|
||||
heap_end += incr;
|
||||
return (caddr_t)prev_heap_end;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
static int totalBytesProvidedBySBRK = 0;
|
||||
#endif
|
||||
extern char configLINKER_HEAP_BASE_SYMBOL, configLINKER_HEAP_LIMIT_SYMBOL, configLINKER_HEAP_SIZE_SYMBOL; // make sure to define these symbols in linker command file
|
||||
static int heapBytesRemaining = (int)&configLINKER_HEAP_SIZE_SYMBOL; // that's (&__HeapLimit)-(&__HeapBase)
|
||||
|
||||
//! sbrk/_sbrk version supporting reentrant newlib (depends upon above symbols defined by linker control file).
|
||||
char * sbrk(int incr) {
|
||||
static char *currentHeapEnd = &configLINKER_HEAP_BASE_SYMBOL;
|
||||
vTaskSuspendAll(); // Note: safe to use before FreeRTOS scheduler started
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
if (currentHeapEnd == &configLINKER_HEAP_BASE_SYMBOL && incr!=0) {
|
||||
/* first call */
|
||||
SEGGER_SYSVIEW_HeapDefine(&configLINKER_HEAP_BASE_SYMBOL, &configLINKER_HEAP_BASE_SYMBOL, (int)&configLINKER_HEAP_SIZE_SYMBOL, 0);
|
||||
SEGGER_SYSVIEW_NameResource(&configLINKER_HEAP_BASE_SYMBOL, "heapNewLib");
|
||||
}
|
||||
#endif
|
||||
char *previousHeapEnd = currentHeapEnd;
|
||||
if (currentHeapEnd + incr > &configLINKER_HEAP_LIMIT_SYMBOL) {
|
||||
#if( configUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
extern void configUSE_MALLOC_FAILED_HOOK_NAME( void );
|
||||
configUSE_MALLOC_FAILED_HOOK_NAME();
|
||||
}
|
||||
#elif 0
|
||||
// If you want to alert debugger or halt...
|
||||
while(1) { __asm("bkpt #0"); }; // Stop in GUI as if at a breakpoint (if debugging, otherwise loop forever)
|
||||
#else
|
||||
// If you prefer to believe your application will gracefully trap out-of-memory...
|
||||
_impure_ptr->_errno = ENOMEM; // newlib's thread-specific errno
|
||||
xTaskResumeAll();
|
||||
#endif
|
||||
return (char *)-1; // the malloc-family routine that called sbrk will return 0
|
||||
}
|
||||
currentHeapEnd += incr;
|
||||
heapBytesRemaining -= incr;
|
||||
#ifndef NDEBUG
|
||||
totalBytesProvidedBySBRK += incr;
|
||||
#endif
|
||||
xTaskResumeAll();
|
||||
return (char *) previousHeapEnd;
|
||||
}
|
||||
//! Synonym for sbrk.
|
||||
char * _sbrk(int incr) { return sbrk(incr); };
|
||||
|
||||
void __malloc_lock(struct _reent *p) { vTaskSuspendAll(); };
|
||||
void __malloc_unlock(struct _reent *p) { (void)xTaskResumeAll(); };
|
||||
|
||||
// newlib also requires implementing locks for the application's environment memory space,
|
||||
// accessed by newlib's setenv() and getenv() functions.
|
||||
// As these are trivial functions, momentarily suspend task switching (rather than semaphore).
|
||||
// ToDo: Move __env_lock/unlock to a separate newlib helper file.
|
||||
void __env_lock() { vTaskSuspendAll(); };
|
||||
void __env_unlock() { (void)xTaskResumeAll(); };
|
||||
|
||||
/// /brief Wrap malloc/malloc_r to help debug who requests memory and why.
|
||||
/// Add to the linker command line: -Xlinker --wrap=malloc -Xlinker --wrap=_malloc_r
|
||||
// Note: These functions are normally unused and stripped by linker.
|
||||
void *__wrap_malloc(size_t nbytes) {
|
||||
extern void * __real_malloc(size_t nbytes);
|
||||
void *p = __real_malloc(nbytes); // Solely for debug breakpoint...
|
||||
return p;
|
||||
};
|
||||
void *__wrap__malloc_r(void *reent, size_t nbytes) {
|
||||
extern void * __real__malloc_r(size_t nbytes);
|
||||
void *p = __real__malloc_r(nbytes); // Solely for debug breakpoint...
|
||||
return p;
|
||||
};
|
||||
|
||||
|
||||
// ================================================================================================
|
||||
// Implement FreeRTOS's memory API using newlib-provided malloc family.
|
||||
// ================================================================================================
|
||||
|
||||
void *pvPortMallocExt( size_t xSize, unsigned int heapTag) PRIVILEGED_FUNCTION { /* << EST */
|
||||
void *p = malloc(xSize);
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
if (heapTag!=(unsigned)-1) {
|
||||
SEGGER_SYSVIEW_HeapAllocEx(&configLINKER_HEAP_BASE_SYMBOL, p, xSize, heapTag);
|
||||
} else {
|
||||
SEGGER_SYSVIEW_HeapAlloc(&configLINKER_HEAP_BASE_SYMBOL, p, xSize);
|
||||
}
|
||||
#else
|
||||
traceMALLOC(p, xSize );
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void *pvPortMalloc(size_t xWantedSize) { /* << EST */
|
||||
return pvPortMallocExt(xWantedSize, -1);
|
||||
}
|
||||
|
||||
void vPortFree( void *pv ) PRIVILEGED_FUNCTION {
|
||||
free(pv);
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
SEGGER_SYSVIEW_HeapFree(&configLINKER_HEAP_BASE_SYMBOL, pv);
|
||||
#else
|
||||
traceFREE(pv, 0);
|
||||
#endif
|
||||
};
|
||||
|
||||
size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION {
|
||||
struct mallinfo mi = mallinfo();
|
||||
return mi.fordblks + heapBytesRemaining;
|
||||
}
|
||||
|
||||
// GetMinimumEverFree is not available in newlib's malloc implementation.
|
||||
// So, no implementation provided: size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
//! No implementation needed, but stub provided in case application already calls vPortInitialiseBlocks
|
||||
void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION {};
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
#if 1 /* << EST */
|
||||
void vPortInitializeHeap(void) {
|
||||
#if configUSE_SEGGER_SYSTEM_VIEWER_HOOKS && configUSE_SEGGER_SYSTEM_VIEWER_HEAP_EVENTS /* << EST */
|
||||
SEGGER_SYSVIEW_HeapDefine(&configLINKER_HEAP_BASE_SYMBOL, &configLINKER_HEAP_BASE_SYMBOL, sizeof(ucHeap), sizeof(BlockLink_t));
|
||||
SEGGER_SYSVIEW_NameResource(&configLINKER_HEAP_BASE_SYMBOL, "heapNewLib");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !defined(configUSE_HEAP_SCHEME) || (configUSE_HEAP_SCHEME==6) */
|
||||
@@ -0,0 +1,7 @@
|
||||
heap_useNewlib.txt
|
||||
------------------
|
||||
|
||||
For details, see
|
||||
- http://www.nadler.com/embedded/newlibAndFreeRTOS.html
|
||||
- http://mcuoneclipse.com/2017/07/02/using-freertos-with-newlib-and-newlib-nano
|
||||
|
||||
3359
pico-sensor/McuLib/FreeRTOS/Source/queue.c
Normal file
3359
pico-sensor/McuLib/FreeRTOS/Source/queue.c
Normal file
File diff suppressed because it is too large
Load Diff
1572
pico-sensor/McuLib/FreeRTOS/Source/stream_buffer.c
Normal file
1572
pico-sensor/McuLib/FreeRTOS/Source/stream_buffer.c
Normal file
File diff suppressed because it is too large
Load Diff
8859
pico-sensor/McuLib/FreeRTOS/Source/tasks.c
Normal file
8859
pico-sensor/McuLib/FreeRTOS/Source/tasks.c
Normal file
File diff suppressed because it is too large
Load Diff
1329
pico-sensor/McuLib/FreeRTOS/Source/timers.c
Normal file
1329
pico-sensor/McuLib/FreeRTOS/Source/timers.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user