Style: uncrusitfy

This commit is contained in:
Alfred Gedeon 2020-07-01 22:27:40 -07:00 committed by alfred gedeon
parent a5dbc2b1de
commit 718178c68a
406 changed files with 108795 additions and 106323 deletions

View file

@ -29,32 +29,32 @@
#include "croutine.h" #include "croutine.h"
/* Remove the whole file is co-routines are not being used. */ /* Remove the whole file is co-routines are not being used. */
#if( configUSE_CO_ROUTINES != 0 ) #if ( configUSE_CO_ROUTINES != 0 )
/* /*
* Some kernel aware debuggers require data to be viewed to be global, rather * Some kernel aware debuggers require data to be viewed to be global, rather
* than file scope. * than file scope.
*/ */
#ifdef portREMOVE_STATIC_QUALIFIER #ifdef portREMOVE_STATIC_QUALIFIER
#define static #define static
#endif #endif
/* Lists for ready and blocked co-routines. --------------------*/ /* Lists for ready and blocked co-routines. --------------------*/
static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */ static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */
static List_t xDelayedCoRoutineList1; /*< Delayed 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 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 * 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 * 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. */ 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. --------------------------------*/ /* Other file private variables. --------------------------------*/
CRCB_t * pxCurrentCoRoutine = NULL; CRCB_t * pxCurrentCoRoutine = NULL;
static UBaseType_t uxTopCoRoutineReadyPriority = 0; static UBaseType_t uxTopCoRoutineReadyPriority = 0;
static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0; static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0;
/* The initial state of the co-routine when it is created. */ /* The initial state of the co-routine when it is created. */
#define corINITIAL_STATE ( 0 ) #define corINITIAL_STATE ( 0 )
/* /*
* Place the co-routine represented by pxCRCB into the appropriate ready queue * Place the co-routine represented by pxCRCB into the appropriate ready queue
@ -63,20 +63,20 @@ static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0;
* This macro accesses the co-routine ready lists and therefore must not be * This macro accesses the co-routine ready lists and therefore must not be
* used from within an ISR. * used from within an ISR.
*/ */
#define prvAddCoRoutineToReadyQueue( pxCRCB ) \ #define prvAddCoRoutineToReadyQueue( pxCRCB ) \
{ \ { \
if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \ if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \
{ \ { \
uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \ uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \
} \ } \
vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \ vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \
} }
/* /*
* Utility to ready all the lists used by the scheduler. This is called * Utility to ready all the lists used by the scheduler. This is called
* automatically upon the creation of the first co-routine. * automatically upon the creation of the first co-routine.
*/ */
static void prvInitialiseCoRoutineLists( void ); static void prvInitialiseCoRoutineLists( void );
/* /*
* Co-routines that are readied by an interrupt cannot be placed directly into * Co-routines that are readied by an interrupt cannot be placed directly into
@ -84,7 +84,7 @@ static void prvInitialiseCoRoutineLists( void );
* in the pending ready list in order that they can later be moved to the ready * in the pending ready list in order that they can later be moved to the ready
* list by the co-routine scheduler. * list by the co-routine scheduler.
*/ */
static void prvCheckPendingReadyList( void ); static void prvCheckPendingReadyList( void );
/* /*
* Macro that looks at the list of co-routines that are currently delayed to * Macro that looks at the list of co-routines that are currently delayed to
@ -94,21 +94,24 @@ static void prvCheckPendingReadyList( void );
* meaning once one co-routine has been found whose timer has not expired * meaning once one co-routine has been found whose timer has not expired
* we need not look any further down the list. * we need not look any further down the list.
*/ */
static void prvCheckDelayedList( void ); static void prvCheckDelayedList( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex ) BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode,
{ UBaseType_t uxPriority,
BaseType_t xReturn; UBaseType_t uxIndex )
CRCB_t *pxCoRoutine; {
BaseType_t xReturn;
CRCB_t * pxCoRoutine;
/* Allocate the memory that will store the co-routine control block. */ /* Allocate the memory that will store the co-routine control block. */
pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) ); pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) );
if( pxCoRoutine ) if( pxCoRoutine )
{ {
/* If pxCurrentCoRoutine is NULL then this is the first co-routine to /* If pxCurrentCoRoutine is NULL then this is the first co-routine to
be created and the co-routine data structures need initialising. */ * be created and the co-routine data structures need initialising. */
if( pxCurrentCoRoutine == NULL ) if( pxCurrentCoRoutine == NULL )
{ {
pxCurrentCoRoutine = pxCoRoutine; pxCurrentCoRoutine = pxCoRoutine;
@ -132,8 +135,8 @@ CRCB_t *pxCoRoutine;
vListInitialiseItem( &( pxCoRoutine->xEventListItem ) ); vListInitialiseItem( &( pxCoRoutine->xEventListItem ) );
/* Set the co-routine control block as a link back from the ListItem_t. /* 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 * This is so we can get back to the containing CRCB from a generic item
in a list. */ * in a list. */
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine ); listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine );
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine ); listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine );
@ -141,7 +144,7 @@ CRCB_t *pxCoRoutine;
listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) ); 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 /* Now the co-routine has been initialised it can be added to the ready
list at the correct priority. */ * list at the correct priority. */
prvAddCoRoutineToReadyQueue( pxCoRoutine ); prvAddCoRoutineToReadyQueue( pxCoRoutine );
xReturn = pdPASS; xReturn = pdPASS;
@ -152,20 +155,21 @@ CRCB_t *pxCoRoutine;
} }
return xReturn; return xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList ) void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay,
{ List_t * pxEventList )
TickType_t xTimeToWake; {
TickType_t xTimeToWake;
/* Calculate the time to wake - this may overflow but this is /* Calculate the time to wake - this may overflow but this is
not a problem. */ * not a problem. */
xTimeToWake = xCoRoutineTickCount + xTicksToDelay; xTimeToWake = xCoRoutineTickCount + xTicksToDelay;
/* We must remove ourselves from the ready list before adding /* We must remove ourselves from the ready list before adding
ourselves to the blocked list as the same list item is used for * ourselves to the blocked list as the same list item is used for
both lists. */ * both lists. */
( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); ( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
/* The list item will be inserted in wake time order. */ /* The list item will be inserted in wake time order. */
@ -174,38 +178,38 @@ TickType_t xTimeToWake;
if( xTimeToWake < xCoRoutineTickCount ) if( xTimeToWake < xCoRoutineTickCount )
{ {
/* Wake time has overflowed. Place this item in the /* Wake time has overflowed. Place this item in the
overflow list. */ * overflow list. */
vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
} }
else else
{ {
/* The wake time has not overflowed, so we can use the /* The wake time has not overflowed, so we can use the
current block list. */ * current block list. */
vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
} }
if( pxEventList ) if( pxEventList )
{ {
/* Also add the co-routine to an event list. If this is done then the /* Also add the co-routine to an event list. If this is done then the
function must be called with interrupts disabled. */ * function must be called with interrupts disabled. */
vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) ); vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvCheckPendingReadyList( void ) static void prvCheckPendingReadyList( void )
{ {
/* Are there any co-routines waiting to get moved to the ready list? These /* 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 * are co-routines that have been readied by an ISR. The ISR cannot access
the ready lists itself. */ * the ready lists itself. */
while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE ) while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE )
{ {
CRCB_t *pxUnblockedCRCB; CRCB_t * pxUnblockedCRCB;
/* The pending ready list can be accessed by an ISR. */ /* The pending ready list can be accessed by an ISR. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
{ {
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) ); pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyCoRoutineList ) );
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
} }
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
@ -213,14 +217,15 @@ static void prvCheckPendingReadyList( void )
( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) ); ( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) );
prvAddCoRoutineToReadyQueue( pxUnblockedCRCB ); prvAddCoRoutineToReadyQueue( pxUnblockedCRCB );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvCheckDelayedList( void ) static void prvCheckDelayedList( void )
{ {
CRCB_t *pxCRCB; CRCB_t * pxCRCB;
xPassedTicks = xTaskGetTickCount() - xLastTickCount; xPassedTicks = xTaskGetTickCount() - xLastTickCount;
while( xPassedTicks ) while( xPassedTicks )
{ {
xCoRoutineTickCount++; xCoRoutineTickCount++;
@ -232,7 +237,7 @@ CRCB_t *pxCRCB;
List_t * pxTemp; List_t * pxTemp;
/* Tick count has overflowed so we need to swap the delay lists. If there are /* 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! */ * any items in pxDelayedCoRoutineList here then there is an error! */
pxTemp = pxDelayedCoRoutineList; pxTemp = pxDelayedCoRoutineList;
pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList; pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList;
pxOverflowDelayedCoRoutineList = pxTemp; pxOverflowDelayedCoRoutineList = pxTemp;
@ -252,10 +257,10 @@ CRCB_t *pxCRCB;
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
{ {
/* The event could have occurred just before this critical /* The event could have occurred just before this critical
section. If this is the case then the generic list item will * section. If this is the case then the generic list item will
have been moved to the pending ready list and the following * have been moved to the pending ready list and the following
line is still valid. Also the pvContainer parameter will have * line is still valid. Also the pvContainer parameter will have
been set to NULL so the following lines are also valid. */ * been set to NULL so the following lines are also valid. */
( void ) uxListRemove( &( pxCRCB->xGenericListItem ) ); ( void ) uxListRemove( &( pxCRCB->xGenericListItem ) );
/* Is the co-routine waiting on an event also? */ /* Is the co-routine waiting on an event also? */
@ -271,14 +276,14 @@ CRCB_t *pxCRCB;
} }
xLastTickCount = xCoRoutineTickCount; xLastTickCount = xCoRoutineTickCount;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vCoRoutineSchedule( void ) void vCoRoutineSchedule( void )
{ {
/* Only run a co-routine after prvInitialiseCoRoutineLists() has been /* Only run a co-routine after prvInitialiseCoRoutineLists() has been
called. prvInitialiseCoRoutineLists() is called automatically when a * called. prvInitialiseCoRoutineLists() is called automatically when a
co-routine is created. */ * co-routine is created. */
if( pxDelayedCoRoutineList != NULL ) if( pxDelayedCoRoutineList != NULL )
{ {
/* See if any co-routines readied by events need moving to the ready lists. */ /* See if any co-routines readied by events need moving to the ready lists. */
@ -295,24 +300,23 @@ void vCoRoutineSchedule( void )
/* No more co-routines to check. */ /* No more co-routines to check. */
return; return;
} }
--uxTopCoRoutineReadyPriority; --uxTopCoRoutineReadyPriority;
} }
/* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines /* 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. */ * of the same priority get an equal share of the processor time. */
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ); listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) );
/* Call the co-routine. */ /* Call the co-routine. */
( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex ); ( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex );
} }
}
return;
}
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvInitialiseCoRoutineLists( void ) static void prvInitialiseCoRoutineLists( void )
{ {
UBaseType_t uxPriority; UBaseType_t uxPriority;
for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ ) for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ )
{ {
@ -324,20 +328,20 @@ UBaseType_t uxPriority;
vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList ); vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList );
/* Start with pxDelayedCoRoutineList using list1 and the /* Start with pxDelayedCoRoutineList using list1 and the
pxOverflowDelayedCoRoutineList using list2. */ * pxOverflowDelayedCoRoutineList using list2. */
pxDelayedCoRoutineList = &xDelayedCoRoutineList1; pxDelayedCoRoutineList = &xDelayedCoRoutineList1;
pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2; pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList ) BaseType_t xCoRoutineRemoveFromEventList( const List_t * pxEventList )
{ {
CRCB_t *pxUnblockedCRCB; CRCB_t * pxUnblockedCRCB;
BaseType_t xReturn; BaseType_t xReturn;
/* This function is called from within an interrupt. It can only access /* This function is called from within an interrupt. It can only access
event lists and the pending ready list. This function assumes that a * event lists and the pending ready list. This function assumes that a
check has already been made to ensure pxEventList is not empty. */ * check has already been made to ensure pxEventList is not empty. */
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) ); vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );
@ -352,7 +356,6 @@ BaseType_t xReturn;
} }
return xReturn; return xReturn;
} }
#endif /* configUSE_CO_ROUTINES == 0 */ #endif /* configUSE_CO_ROUTINES == 0 */

View file

@ -28,8 +28,8 @@
#include <stdlib.h> #include <stdlib.h>
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining /* 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 * all the API functions to use the MPU wrappers. That should only be done when
task.h is included from an application file. */ * task.h is included from an application file. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* FreeRTOS includes. */ /* FreeRTOS includes. */
@ -39,14 +39,14 @@ task.h is included from an application file. */
#include "event_groups.h" #include "event_groups.h"
/* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified /* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified
because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
for the header files above, but not in this file, in order to generate the * for the header files above, but not in this file, in order to generate the
correct privileged Vs unprivileged linkage and placement. */ * correct privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021 See comment above. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021 See comment above. */
/* The following bit fields convey control information in a task's event list /* The following bit fields convey control information in a task's event list
item value. It is important they don't clash with the * item value. It is important they don't clash with the
taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */ * taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
#if configUSE_16_BIT_TICKS == 1 #if configUSE_16_BIT_TICKS == 1
#define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
#define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U #define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U
@ -64,11 +64,11 @@ typedef struct EventGroupDef_t
EventBits_t uxEventBits; EventBits_t uxEventBits;
List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */ List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */
#if( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxEventGroupNumber; UBaseType_t uxEventGroupNumber;
#endif #endif
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */ uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
#endif #endif
} EventGroup_t; } EventGroup_t;
@ -83,24 +83,26 @@ typedef struct EventGroupDef_t
* wait condition is met if any of the bits set in uxBitsToWait for are also set * wait condition is met if any of the bits set in uxBitsToWait for are also set
* in uxCurrentEventBits. * in uxCurrentEventBits.
*/ */
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION; static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configSUPPORT_STATIC_ALLOCATION == 1 ) #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ) EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer )
{ {
EventGroup_t *pxEventBits; EventGroup_t * pxEventBits;
/* A StaticEventGroup_t object must be provided. */ /* A StaticEventGroup_t object must be provided. */
configASSERT( pxEventGroupBuffer ); configASSERT( pxEventGroupBuffer );
#if( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
/* Sanity check that the size of the structure used to declare a /* Sanity check that the size of the structure used to declare a
variable of type StaticEventGroup_t equals the size of the real * variable of type StaticEventGroup_t equals the size of the real
event group structure. */ * event group structure. */
volatile size_t xSize = sizeof( StaticEventGroup_t ); volatile size_t xSize = sizeof( StaticEventGroup_t );
configASSERT( xSize == sizeof( EventGroup_t ) ); configASSERT( xSize == sizeof( EventGroup_t ) );
} /*lint !e529 xSize is referenced if configASSERT() is defined. */ } /*lint !e529 xSize is referenced if configASSERT() is defined. */
@ -114,11 +116,11 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
pxEventBits->uxEventBits = 0; pxEventBits->uxEventBits = 0;
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
{ {
/* Both static and dynamic allocation can be used, so note that /* Both static and dynamic allocation can be used, so note that
this event group was created statically in case the event group * this event group was created statically in case the event group
is later deleted. */ * is later deleted. */
pxEventBits->ucStaticallyAllocated = pdTRUE; pxEventBits->ucStaticallyAllocated = pdTRUE;
} }
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
@ -128,8 +130,8 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
else else
{ {
/* xEventGroupCreateStatic should only ever be called with /* xEventGroupCreateStatic should only ever be called with
pxEventGroupBuffer pointing to a pre-allocated (compile time * pxEventGroupBuffer pointing to a pre-allocated (compile time
allocated) StaticEventGroup_t variable. */ * allocated) StaticEventGroup_t variable. */
traceEVENT_GROUP_CREATE_FAILED(); traceEVENT_GROUP_CREATE_FAILED();
} }
@ -139,25 +141,25 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
#endif /* configSUPPORT_STATIC_ALLOCATION */ #endif /* configSUPPORT_STATIC_ALLOCATION */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
EventGroupHandle_t xEventGroupCreate( void ) EventGroupHandle_t xEventGroupCreate( void )
{ {
EventGroup_t *pxEventBits; EventGroup_t * pxEventBits;
/* Allocate the event group. Justification for MISRA deviation as /* Allocate the event group. Justification for MISRA deviation as
follows: pvPortMalloc() always ensures returned memory blocks are * follows: pvPortMalloc() always ensures returned memory blocks are
aligned per the requirements of the MCU stack. In this case * aligned per the requirements of the MCU stack. In this case
pvPortMalloc() must return a pointer that is guaranteed to meet the * pvPortMalloc() must return a pointer that is guaranteed to meet the
alignment requirements of the EventGroup_t structure - which (if you * alignment requirements of the EventGroup_t structure - which (if you
follow it through) is the alignment requirements of the TickType_t type * follow it through) is the alignment requirements of the TickType_t type
(EventBits_t being of TickType_t itself). Therefore, whenever the * (EventBits_t being of TickType_t itself). Therefore, whenever the
stack alignment requirements are greater than or equal to the * stack alignment requirements are greater than or equal to the
TickType_t alignment requirements the cast is safe. In other cases, * TickType_t alignment requirements the cast is safe. In other cases,
where the natural word size of the architecture is less than * where the natural word size of the architecture is less than
sizeof( TickType_t ), the TickType_t variables will be accessed in two * sizeof( TickType_t ), the TickType_t variables will be accessed in two
or more reads operations, and the alignment requirements is only that * or more reads operations, and the alignment requirements is only that
of each individual read. */ * of each individual read. */
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */ pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */
if( pxEventBits != NULL ) if( pxEventBits != NULL )
@ -165,11 +167,11 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
pxEventBits->uxEventBits = 0; pxEventBits->uxEventBits = 0;
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
#if( configSUPPORT_STATIC_ALLOCATION == 1 ) #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
{ {
/* Both static and dynamic allocation can be used, so note this /* Both static and dynamic allocation can be used, so note this
event group was allocated statically in case the event group is * event group was allocated statically in case the event group is
later deleted. */ * later deleted. */
pxEventBits->ucStaticallyAllocated = pdFALSE; pxEventBits->ucStaticallyAllocated = pdFALSE;
} }
#endif /* configSUPPORT_STATIC_ALLOCATION */ #endif /* configSUPPORT_STATIC_ALLOCATION */
@ -187,12 +189,15 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
const EventBits_t uxBitsToWaitFor,
TickType_t xTicksToWait )
{ {
EventBits_t uxOriginalBitValue, uxReturn; EventBits_t uxOriginalBitValue, uxReturn;
EventGroup_t *pxEventBits = xEventGroup; EventGroup_t * pxEventBits = xEventGroup;
BaseType_t xAlreadyYielded; BaseType_t xAlreadyYielded;
BaseType_t xTimeoutOccurred = pdFALSE; BaseType_t xTimeoutOccurred = pdFALSE;
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
configASSERT( uxBitsToWaitFor != 0 ); configASSERT( uxBitsToWaitFor != 0 );
@ -214,7 +219,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
uxReturn = ( uxOriginalBitValue | uxBitsToSet ); uxReturn = ( uxOriginalBitValue | uxBitsToSet );
/* Rendezvous always clear the bits. They will have been cleared /* Rendezvous always clear the bits. They will have been cleared
already unless this is the only task in the rendezvous. */ * already unless this is the only task in the rendezvous. */
pxEventBits->uxEventBits &= ~uxBitsToWaitFor; pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
xTicksToWait = 0; xTicksToWait = 0;
@ -226,20 +231,20 @@ BaseType_t xTimeoutOccurred = pdFALSE;
traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ); traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
/* Store the bits that the calling task is waiting for in the /* 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 * task's event list item so the kernel knows when a match is
found. Then enter the blocked state. */ * found. Then enter the blocked state. */
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait ); vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
/* This assignment is obsolete as uxReturn will get set after /* This assignment is obsolete as uxReturn will get set after
the task unblocks, but some compilers mistakenly generate a * the task unblocks, but some compilers mistakenly generate a
warning about uxReturn being returned without being set if the * warning about uxReturn being returned without being set if the
assignment is omitted. */ * assignment is omitted. */
uxReturn = 0; uxReturn = 0;
} }
else else
{ {
/* The rendezvous bits were not set, but no block time was /* The rendezvous bits were not set, but no block time was
specified - just return the current event bit value. */ * specified - just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits; uxReturn = pxEventBits->uxEventBits;
xTimeoutOccurred = pdTRUE; xTimeoutOccurred = pdTRUE;
} }
@ -259,9 +264,9 @@ BaseType_t xTimeoutOccurred = pdFALSE;
} }
/* The task blocked to wait for its required bits to be set - at this /* 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 * 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 * 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. */ * event list item, and they should now be retrieved then cleared. */
uxReturn = uxTaskResetEventItemValue(); uxReturn = uxTaskResetEventItemValue();
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
@ -272,9 +277,9 @@ BaseType_t xTimeoutOccurred = pdFALSE;
uxReturn = pxEventBits->uxEventBits; uxReturn = pxEventBits->uxEventBits;
/* Although the task got here because it timed out before the /* Although the task got here because it timed out before the
bits it was waiting for were set, it is possible that since it * 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 * unblocked another task has set the bits. If this is the case
then it needs to clear the bits before exiting. */ * then it needs to clear the bits before exiting. */
if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor ) if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
{ {
pxEventBits->uxEventBits &= ~uxBitsToWaitFor; pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
@ -294,7 +299,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
} }
/* Control bits might be set as the task had blocked should not be /* Control bits might be set as the task had blocked should not be
returned. */ * returned. */
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
} }
@ -307,15 +312,19 @@ BaseType_t xTimeoutOccurred = pdFALSE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) 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; EventGroup_t * pxEventBits = xEventGroup;
EventBits_t uxReturn, uxControlBits = 0; EventBits_t uxReturn, uxControlBits = 0;
BaseType_t xWaitConditionMet, xAlreadyYielded; BaseType_t xWaitConditionMet, xAlreadyYielded;
BaseType_t xTimeoutOccurred = pdFALSE; BaseType_t xTimeoutOccurred = pdFALSE;
/* Check the user is not attempting to wait on the bits used by the kernel /* 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. */ * itself, and that at least one bit is being requested. */
configASSERT( xEventGroup ); configASSERT( xEventGroup );
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
configASSERT( uxBitsToWaitFor != 0 ); configASSERT( uxBitsToWaitFor != 0 );
@ -335,7 +344,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
if( xWaitConditionMet != pdFALSE ) if( xWaitConditionMet != pdFALSE )
{ {
/* The wait condition has already been met so there is no need to /* The wait condition has already been met so there is no need to
block. */ * block. */
uxReturn = uxCurrentEventBits; uxReturn = uxCurrentEventBits;
xTicksToWait = ( TickType_t ) 0; xTicksToWait = ( TickType_t ) 0;
@ -352,16 +361,16 @@ BaseType_t xTimeoutOccurred = pdFALSE;
else if( xTicksToWait == ( TickType_t ) 0 ) else if( xTicksToWait == ( TickType_t ) 0 )
{ {
/* The wait condition has not been met, but no block time was /* The wait condition has not been met, but no block time was
specified, so just return the current value. */ * specified, so just return the current value. */
uxReturn = uxCurrentEventBits; uxReturn = uxCurrentEventBits;
xTimeoutOccurred = pdTRUE; xTimeoutOccurred = pdTRUE;
} }
else else
{ {
/* The task is going to block to wait for its required bits to be /* The task is going to block to wait for its required bits to be
set. uxControlBits are used to remember the specified behaviour of * set. uxControlBits are used to remember the specified behaviour of
this call to xEventGroupWaitBits() - for use when the event bits * this call to xEventGroupWaitBits() - for use when the event bits
unblock the task. */ * unblock the task. */
if( xClearOnExit != pdFALSE ) if( xClearOnExit != pdFALSE )
{ {
uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT; uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
@ -381,13 +390,13 @@ BaseType_t xTimeoutOccurred = pdFALSE;
} }
/* Store the bits that the calling task is waiting for in the /* 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 * task's event list item so the kernel knows when a match is
found. Then enter the blocked state. */ * found. Then enter the blocked state. */
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait ); vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
/* This is obsolete as it will get set after the task unblocks, but /* This is obsolete as it will get set after the task unblocks, but
some compilers mistakenly generate a warning about the variable * some compilers mistakenly generate a warning about the variable
being returned without being set if it is not done. */ * being returned without being set if it is not done. */
uxReturn = 0; uxReturn = 0;
traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ); traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
@ -407,9 +416,9 @@ BaseType_t xTimeoutOccurred = pdFALSE;
} }
/* The task blocked to wait for its required bits to be set - at this /* 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 * 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 * 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. */ * event list item, and they should now be retrieved then cleared. */
uxReturn = uxTaskResetEventItemValue(); uxReturn = uxTaskResetEventItemValue();
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
@ -420,7 +429,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
uxReturn = pxEventBits->uxEventBits; uxReturn = pxEventBits->uxEventBits;
/* It is possible that the event bits were updated between this /* It is possible that the event bits were updated between this
task leaving the Blocked state and running again. */ * task leaving the Blocked state and running again. */
if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE ) if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
{ {
if( xClearOnExit != pdFALSE ) if( xClearOnExit != pdFALSE )
@ -436,6 +445,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
{ {
mtCOVERAGE_TEST_MARKER(); mtCOVERAGE_TEST_MARKER();
} }
xTimeoutOccurred = pdTRUE; xTimeoutOccurred = pdTRUE;
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
@ -448,6 +458,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
/* The task blocked so control bits may have been set. */ /* The task blocked so control bits may have been set. */
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
} }
traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ); traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
/* Prevent compiler warnings when trace macros are not used. */ /* Prevent compiler warnings when trace macros are not used. */
@ -457,13 +468,14 @@ BaseType_t xTimeoutOccurred = pdFALSE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear )
{ {
EventGroup_t *pxEventBits = xEventGroup; EventGroup_t * pxEventBits = xEventGroup;
EventBits_t uxReturn; EventBits_t uxReturn;
/* Check the user is not attempting to clear the bits used by the kernel /* Check the user is not attempting to clear the bits used by the kernel
itself. */ * itself. */
configASSERT( xEventGroup ); configASSERT( xEventGroup );
configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
@ -472,7 +484,7 @@ EventBits_t uxReturn;
traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ); traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
/* The value returned is the event group value prior to the bits being /* The value returned is the event group value prior to the bits being
cleared. */ * cleared. */
uxReturn = pxEventBits->uxEventBits; uxReturn = pxEventBits->uxEventBits;
/* Clear the bits. */ /* Clear the bits. */
@ -486,7 +498,8 @@ EventBits_t uxReturn;
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear )
{ {
BaseType_t xReturn; BaseType_t xReturn;
@ -496,14 +509,14 @@ EventBits_t uxReturn;
return xReturn; return xReturn;
} }
#endif #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
{ {
UBaseType_t uxSavedInterruptStatus; UBaseType_t uxSavedInterruptStatus;
EventGroup_t const * const pxEventBits = xEventGroup; EventGroup_t const * const pxEventBits = xEventGroup;
EventBits_t uxReturn; EventBits_t uxReturn;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{ {
@ -515,17 +528,18 @@ EventBits_t uxReturn;
} /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */ } /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet )
{ {
ListItem_t *pxListItem, *pxNext; ListItem_t * pxListItem, * pxNext;
ListItem_t const *pxListEnd; ListItem_t const * pxListEnd;
List_t const * pxList; List_t const * pxList;
EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits; EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
EventGroup_t *pxEventBits = xEventGroup; EventGroup_t * pxEventBits = xEventGroup;
BaseType_t xMatchFound = pdFALSE; BaseType_t xMatchFound = pdFALSE;
/* Check the user is not attempting to set the bits used by the kernel /* Check the user is not attempting to set the bits used by the kernel
itself. */ * itself. */
configASSERT( xEventGroup ); configASSERT( xEventGroup );
configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
@ -586,21 +600,21 @@ BaseType_t xMatchFound = pdFALSE;
} }
/* Store the actual event flag value in the task's event list /* Store the actual event flag value in the task's event list
item before removing the task from the event list. The * item before removing the task from the event list. The
eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows * eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
that is was unblocked due to its required bits matching, rather * that is was unblocked due to its required bits matching, rather
than because it timed out. */ * than because it timed out. */
vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET ); vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
} }
/* Move onto the next list item. Note pxListItem->pxNext is not /* 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 * used here as the list item may have been removed from the event list
and inserted into the ready/pending reading list. */ * and inserted into the ready/pending reading list. */
pxListItem = pxNext; pxListItem = pxNext;
} }
/* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
bit was set in the control word. */ * bit was set in the control word. */
pxEventBits->uxEventBits &= ~uxBitsToClear; pxEventBits->uxEventBits &= ~uxBitsToClear;
} }
( void ) xTaskResumeAll(); ( void ) xTaskResumeAll();
@ -611,8 +625,8 @@ BaseType_t xMatchFound = pdFALSE;
void vEventGroupDelete( EventGroupHandle_t xEventGroup ) void vEventGroupDelete( EventGroupHandle_t xEventGroup )
{ {
EventGroup_t *pxEventBits = xEventGroup; EventGroup_t * pxEventBits = xEventGroup;
const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits ); const List_t * pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
vTaskSuspendAll(); vTaskSuspendAll();
{ {
@ -621,21 +635,21 @@ const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 ) while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
{ {
/* Unblock the task, returning 0 as the event list is being deleted /* Unblock the task, returning 0 as the event list is being deleted
and cannot therefore have any bits set. */ * and cannot therefore have any bits set. */
configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) ); configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET ); vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
} }
#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
{ {
/* The event group can only have been allocated dynamically - free /* The event group can only have been allocated dynamically - free
it again. */ * it again. */
vPortFree( pxEventBits ); vPortFree( pxEventBits );
} }
#elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
{ {
/* The event group could have been allocated statically or /* The event group could have been allocated statically or
dynamically, so check before attempting to free the memory. */ * dynamically, so check before attempting to free the memory. */
if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
{ {
vPortFree( pxEventBits ); vPortFree( pxEventBits );
@ -652,29 +666,33 @@ const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* For internal use only - execute a 'set bits' command that was pended from /* For internal use only - execute a 'set bits' command that was pended from
an interrupt. */ * an interrupt. */
void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) void vEventGroupSetBitsCallback( void * pvEventGroup,
const uint32_t ulBitsToSet )
{ {
( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */ ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* For internal use only - execute a 'clear bits' command that was pended from /* For internal use only - execute a 'clear bits' command that was pended from
an interrupt. */ * an interrupt. */
void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) void vEventGroupClearBitsCallback( void * pvEventGroup,
const uint32_t ulBitsToClear )
{ {
( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */ ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xWaitForAllBits )
{ {
BaseType_t xWaitConditionMet = pdFALSE; BaseType_t xWaitConditionMet = pdFALSE;
if( xWaitForAllBits == pdFALSE ) if( xWaitForAllBits == pdFALSE )
{ {
/* Task only has to wait for one bit within uxBitsToWaitFor to be /* Task only has to wait for one bit within uxBitsToWaitFor to be
set. Is one already set? */ * set. Is one already set? */
if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 ) if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
{ {
xWaitConditionMet = pdTRUE; xWaitConditionMet = pdTRUE;
@ -687,7 +705,7 @@ BaseType_t xWaitConditionMet = pdFALSE;
else else
{ {
/* Task has to wait for all the bits in uxBitsToWaitFor to be set. /* Task has to wait for all the bits in uxBitsToWaitFor to be set.
Are they set already? */ * Are they set already? */
if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor ) if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
{ {
xWaitConditionMet = pdTRUE; xWaitConditionMet = pdTRUE;
@ -704,7 +722,9 @@ BaseType_t xWaitConditionMet = pdFALSE;
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) #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 xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
BaseType_t * pxHigherPriorityTaskWoken )
{ {
BaseType_t xReturn; BaseType_t xReturn;
@ -714,15 +734,15 @@ BaseType_t xWaitConditionMet = pdFALSE;
return xReturn; return xReturn;
} }
#endif #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if (configUSE_TRACE_FACILITY == 1) #if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) UBaseType_t uxEventGroupGetNumber( void * xEventGroup )
{ {
UBaseType_t xReturn; UBaseType_t xReturn;
EventGroup_t const *pxEventBits = ( EventGroup_t * ) xEventGroup; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */ EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */
if( xEventGroup == NULL ) if( xEventGroup == NULL )
{ {
@ -741,12 +761,11 @@ BaseType_t xWaitConditionMet = pdFALSE;
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
void vEventGroupSetNumber( void * xEventGroup, UBaseType_t uxEventGroupNumber ) void vEventGroupSetNumber( void * xEventGroup,
UBaseType_t uxEventGroupNumber )
{ {
( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */ ( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */
} }
#endif /* configUSE_TRACE_FACILITY */ #endif /* configUSE_TRACE_FACILITY */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

File diff suppressed because it is too large Load diff

View file

@ -47,9 +47,9 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) ) #if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) )
/* Only the current stack state is to be checked. */ /* Only the current stack state is to be checked. */
#define taskCHECK_FOR_STACK_OVERFLOW() \ #define taskCHECK_FOR_STACK_OVERFLOW() \
{ \ { \
/* Is the currently saved stack pointer within the stack limit? */ \ /* Is the currently saved stack pointer within the stack limit? */ \
@ -62,9 +62,9 @@
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) ) #if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) )
/* Only the current stack state is to be checked. */ /* Only the current stack state is to be checked. */
#define taskCHECK_FOR_STACK_OVERFLOW() \ #define taskCHECK_FOR_STACK_OVERFLOW() \
{ \ { \
\ \
@ -78,7 +78,7 @@
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) #if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) )
#define taskCHECK_FOR_STACK_OVERFLOW() \ #define taskCHECK_FOR_STACK_OVERFLOW() \
{ \ { \
@ -97,11 +97,11 @@
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) #if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) )
#define taskCHECK_FOR_STACK_OVERFLOW() \ #define taskCHECK_FOR_STACK_OVERFLOW() \
{ \ { \
int8_t *pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \ int8_t * pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \
static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 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, \
@ -129,4 +129,3 @@
#endif /* STACK_MACROS_H */ #endif /* STACK_MACROS_H */

View file

@ -34,18 +34,18 @@
*/ */
#ifndef ATOMIC_H #ifndef ATOMIC_H
#define ATOMIC_H #define ATOMIC_H
#ifndef INC_FREERTOS_H #ifndef INC_FREERTOS_H
#error "include FreeRTOS.h must appear in source files before include atomic.h" #error "include FreeRTOS.h must appear in source files before include atomic.h"
#endif #endif
/* Standard includes. */ /* Standard includes. */
#include <stdint.h> #include <stdint.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* /*
* Port specific definitions -- entering/exiting critical section. * Port specific definitions -- entering/exiting critical section.
@ -55,22 +55,22 @@ extern "C" {
* ATOMIC_ENTER_CRITICAL(). * ATOMIC_ENTER_CRITICAL().
* *
*/ */
#if defined( portSET_INTERRUPT_MASK_FROM_ISR ) #if defined( portSET_INTERRUPT_MASK_FROM_ISR )
/* Nested interrupt scheme is supported in this port. */ /* Nested interrupt scheme is supported in this port. */
#define ATOMIC_ENTER_CRITICAL() \ #define ATOMIC_ENTER_CRITICAL() \
UBaseType_t uxCriticalSectionType = portSET_INTERRUPT_MASK_FROM_ISR() UBaseType_t uxCriticalSectionType = portSET_INTERRUPT_MASK_FROM_ISR()
#define ATOMIC_EXIT_CRITICAL() \ #define ATOMIC_EXIT_CRITICAL() \
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxCriticalSectionType ) portCLEAR_INTERRUPT_MASK_FROM_ISR( uxCriticalSectionType )
#else #else
/* Nested interrupt scheme is NOT supported in this port. */ /* Nested interrupt scheme is NOT supported in this port. */
#define ATOMIC_ENTER_CRITICAL() portENTER_CRITICAL() #define ATOMIC_ENTER_CRITICAL() portENTER_CRITICAL()
#define ATOMIC_EXIT_CRITICAL() portEXIT_CRITICAL() #define ATOMIC_EXIT_CRITICAL() portEXIT_CRITICAL()
#endif /* portSET_INTERRUPT_MASK_FROM_ISR() */ #endif /* portSET_INTERRUPT_MASK_FROM_ISR() */
/* /*
* Port specific definition -- "always inline". * Port specific definition -- "always inline".
@ -79,12 +79,12 @@ extern "C" {
* for atomic. Thus, if portFORCE_INLINE is not provided by portmacro.h, * for atomic. Thus, if portFORCE_INLINE is not provided by portmacro.h,
* instead of resulting error, simply define it away. * instead of resulting error, simply define it away.
*/ */
#ifndef portFORCE_INLINE #ifndef portFORCE_INLINE
#define portFORCE_INLINE #define portFORCE_INLINE
#endif #endif
#define ATOMIC_COMPARE_AND_SWAP_SUCCESS 0x1U /**< Compare and swap succeeded, swapped. */ #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. */ #define ATOMIC_COMPARE_AND_SWAP_FAILURE 0x0U /**< Compare and swap failed, did not swap. */
/*----------------------------- Swap && CAS ------------------------------*/ /*----------------------------- Swap && CAS ------------------------------*/
@ -103,11 +103,11 @@ extern "C" {
* @note This function only swaps *pulDestination with ulExchange, if previous * @note This function only swaps *pulDestination with ulExchange, if previous
* *pulDestination value equals ulComparand. * *pulDestination value equals ulComparand.
*/ */
static portFORCE_INLINE uint32_t Atomic_CompareAndSwap_u32( uint32_t volatile * pulDestination, static portFORCE_INLINE uint32_t Atomic_CompareAndSwap_u32( uint32_t volatile * pulDestination,
uint32_t ulExchange, uint32_t ulExchange,
uint32_t ulComparand ) uint32_t ulComparand )
{ {
uint32_t ulReturnValue; uint32_t ulReturnValue;
ATOMIC_ENTER_CRITICAL(); ATOMIC_ENTER_CRITICAL();
{ {
@ -124,7 +124,7 @@ uint32_t ulReturnValue;
ATOMIC_EXIT_CRITICAL(); ATOMIC_EXIT_CRITICAL();
return ulReturnValue; return ulReturnValue;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -139,10 +139,10 @@ uint32_t ulReturnValue;
* *
* @return The initial value of *ppvDestination. * @return The initial value of *ppvDestination.
*/ */
static portFORCE_INLINE void * Atomic_SwapPointers_p32( void * volatile * ppvDestination, static portFORCE_INLINE void * Atomic_SwapPointers_p32( void * volatile * ppvDestination,
void * pvExchange ) void * pvExchange )
{ {
void * pReturnValue; void * pReturnValue;
ATOMIC_ENTER_CRITICAL(); ATOMIC_ENTER_CRITICAL();
{ {
@ -152,7 +152,7 @@ void * pReturnValue;
ATOMIC_EXIT_CRITICAL(); ATOMIC_EXIT_CRITICAL();
return pReturnValue; return pReturnValue;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -171,11 +171,11 @@ void * pReturnValue;
* @note This function only swaps *ppvDestination with pvExchange, if previous * @note This function only swaps *ppvDestination with pvExchange, if previous
* *ppvDestination value equals pvComparand. * *ppvDestination value equals pvComparand.
*/ */
static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32( void * volatile * ppvDestination, static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32( void * volatile * ppvDestination,
void * pvExchange, void * pvExchange,
void * pvComparand ) void * pvComparand )
{ {
uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE; uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
ATOMIC_ENTER_CRITICAL(); ATOMIC_ENTER_CRITICAL();
{ {
@ -188,7 +188,7 @@ uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
ATOMIC_EXIT_CRITICAL(); ATOMIC_EXIT_CRITICAL();
return ulReturnValue; return ulReturnValue;
} }
/*----------------------------- Arithmetic ------------------------------*/ /*----------------------------- Arithmetic ------------------------------*/
@ -204,9 +204,9 @@ uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
* *
* @return previous *pulAddend value. * @return previous *pulAddend value.
*/ */
static portFORCE_INLINE uint32_t Atomic_Add_u32( uint32_t volatile * pulAddend, static portFORCE_INLINE uint32_t Atomic_Add_u32( uint32_t volatile * pulAddend,
uint32_t ulCount ) uint32_t ulCount )
{ {
uint32_t ulCurrent; uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL(); ATOMIC_ENTER_CRITICAL();
@ -217,7 +217,7 @@ static portFORCE_INLINE uint32_t Atomic_Add_u32( uint32_t volatile * pulAddend,
ATOMIC_EXIT_CRITICAL(); ATOMIC_EXIT_CRITICAL();
return ulCurrent; return ulCurrent;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -232,9 +232,9 @@ static portFORCE_INLINE uint32_t Atomic_Add_u32( uint32_t volatile * pulAddend,
* *
* @return previous *pulAddend value. * @return previous *pulAddend value.
*/ */
static portFORCE_INLINE uint32_t Atomic_Subtract_u32( uint32_t volatile * pulAddend, static portFORCE_INLINE uint32_t Atomic_Subtract_u32( uint32_t volatile * pulAddend,
uint32_t ulCount ) uint32_t ulCount )
{ {
uint32_t ulCurrent; uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL(); ATOMIC_ENTER_CRITICAL();
@ -245,7 +245,7 @@ static portFORCE_INLINE uint32_t Atomic_Subtract_u32( uint32_t volatile * pulAdd
ATOMIC_EXIT_CRITICAL(); ATOMIC_EXIT_CRITICAL();
return ulCurrent; return ulCurrent;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -258,9 +258,9 @@ static portFORCE_INLINE uint32_t Atomic_Subtract_u32( uint32_t volatile * pulAdd
* *
* @return *pulAddend value before increment. * @return *pulAddend value before increment.
*/ */
static portFORCE_INLINE uint32_t Atomic_Increment_u32( uint32_t volatile * pulAddend ) static portFORCE_INLINE uint32_t Atomic_Increment_u32( uint32_t volatile * pulAddend )
{ {
uint32_t ulCurrent; uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL(); ATOMIC_ENTER_CRITICAL();
{ {
@ -270,7 +270,7 @@ uint32_t ulCurrent;
ATOMIC_EXIT_CRITICAL(); ATOMIC_EXIT_CRITICAL();
return ulCurrent; return ulCurrent;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -283,9 +283,9 @@ uint32_t ulCurrent;
* *
* @return *pulAddend value before decrement. * @return *pulAddend value before decrement.
*/ */
static portFORCE_INLINE uint32_t Atomic_Decrement_u32( uint32_t volatile * pulAddend ) static portFORCE_INLINE uint32_t Atomic_Decrement_u32( uint32_t volatile * pulAddend )
{ {
uint32_t ulCurrent; uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL(); ATOMIC_ENTER_CRITICAL();
{ {
@ -295,7 +295,7 @@ uint32_t ulCurrent;
ATOMIC_EXIT_CRITICAL(); ATOMIC_EXIT_CRITICAL();
return ulCurrent; return ulCurrent;
} }
/*----------------------------- Bitwise Logical ------------------------------*/ /*----------------------------- Bitwise Logical ------------------------------*/
@ -310,10 +310,10 @@ uint32_t ulCurrent;
* *
* @return The original value of *pulDestination. * @return The original value of *pulDestination.
*/ */
static portFORCE_INLINE uint32_t Atomic_OR_u32( uint32_t volatile * pulDestination, static portFORCE_INLINE uint32_t Atomic_OR_u32( uint32_t volatile * pulDestination,
uint32_t ulValue ) uint32_t ulValue )
{ {
uint32_t ulCurrent; uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL(); ATOMIC_ENTER_CRITICAL();
{ {
@ -323,7 +323,7 @@ uint32_t ulCurrent;
ATOMIC_EXIT_CRITICAL(); ATOMIC_EXIT_CRITICAL();
return ulCurrent; return ulCurrent;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -337,10 +337,10 @@ uint32_t ulCurrent;
* *
* @return The original value of *pulDestination. * @return The original value of *pulDestination.
*/ */
static portFORCE_INLINE uint32_t Atomic_AND_u32( uint32_t volatile * pulDestination, static portFORCE_INLINE uint32_t Atomic_AND_u32( uint32_t volatile * pulDestination,
uint32_t ulValue ) uint32_t ulValue )
{ {
uint32_t ulCurrent; uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL(); ATOMIC_ENTER_CRITICAL();
{ {
@ -350,7 +350,7 @@ uint32_t ulCurrent;
ATOMIC_EXIT_CRITICAL(); ATOMIC_EXIT_CRITICAL();
return ulCurrent; return ulCurrent;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -364,10 +364,10 @@ uint32_t ulCurrent;
* *
* @return The original value of *pulDestination. * @return The original value of *pulDestination.
*/ */
static portFORCE_INLINE uint32_t Atomic_NAND_u32( uint32_t volatile * pulDestination, static portFORCE_INLINE uint32_t Atomic_NAND_u32( uint32_t volatile * pulDestination,
uint32_t ulValue ) uint32_t ulValue )
{ {
uint32_t ulCurrent; uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL(); ATOMIC_ENTER_CRITICAL();
{ {
@ -377,7 +377,7 @@ uint32_t ulCurrent;
ATOMIC_EXIT_CRITICAL(); ATOMIC_EXIT_CRITICAL();
return ulCurrent; return ulCurrent;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -391,10 +391,10 @@ uint32_t ulCurrent;
* *
* @return The original value of *pulDestination. * @return The original value of *pulDestination.
*/ */
static portFORCE_INLINE uint32_t Atomic_XOR_u32( uint32_t volatile * pulDestination, static portFORCE_INLINE uint32_t Atomic_XOR_u32( uint32_t volatile * pulDestination,
uint32_t ulValue ) uint32_t ulValue )
{ {
uint32_t ulCurrent; uint32_t ulCurrent;
ATOMIC_ENTER_CRITICAL(); ATOMIC_ENTER_CRITICAL();
{ {
@ -404,10 +404,10 @@ uint32_t ulCurrent;
ATOMIC_EXIT_CRITICAL(); ATOMIC_EXIT_CRITICAL();
return ulCurrent; return ulCurrent;
} }
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* ATOMIC_H */ #endif /* ATOMIC_H */

View file

@ -25,44 +25,45 @@
*/ */
#ifndef CO_ROUTINE_H #ifndef CO_ROUTINE_H
#define CO_ROUTINE_H #define CO_ROUTINE_H
#ifndef INC_FREERTOS_H #ifndef INC_FREERTOS_H
#error "include FreeRTOS.h must appear in source files before include croutine.h" #error "include FreeRTOS.h must appear in source files before include croutine.h"
#endif #endif
#include "list.h" #include "list.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Used to hide the implementation of the co-routine control block. The /* 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 * control block structure however has to be included in the header due to
the macro implementation of the co-routine functionality. */ * the macro implementation of the co-routine functionality. */
typedef void * CoRoutineHandle_t; typedef void * CoRoutineHandle_t;
/* Defines the prototype to which co-routine functions must conform. */ /* Defines the prototype to which co-routine functions must conform. */
typedef void (*crCOROUTINE_CODE)( CoRoutineHandle_t, UBaseType_t ); typedef void (* crCOROUTINE_CODE)( CoRoutineHandle_t,
UBaseType_t );
typedef struct corCoRoutineControlBlock typedef struct corCoRoutineControlBlock
{ {
crCOROUTINE_CODE pxCoRoutineFunction; crCOROUTINE_CODE pxCoRoutineFunction;
ListItem_t xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */ 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. */ 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 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. */ 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. */ 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. */ } CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */
/** /**
* croutine. h * croutine. h
*<pre> *<pre>
BaseType_t xCoRoutineCreate( * BaseType_t xCoRoutineCreate(
crCOROUTINE_CODE pxCoRoutineCode, * crCOROUTINE_CODE pxCoRoutineCode,
UBaseType_t uxPriority, * UBaseType_t uxPriority,
UBaseType_t uxIndex * UBaseType_t uxIndex
);</pre> * );</pre>
* *
* Create a new co-routine and add it to the list of co-routines that are * Create a new co-routine and add it to the list of co-routines that are
* ready to run. * ready to run.
@ -82,58 +83,60 @@ typedef struct corCoRoutineControlBlock
* list, otherwise an error code defined with ProjDefs.h. * list, otherwise an error code defined with ProjDefs.h.
* *
* Example usage: * Example usage:
<pre> * <pre>
// Co-routine to be created. * // Co-routine to be created.
void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) * 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. * // 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. * // This may not be necessary for const variables.
static const char cLedToFlash[ 2 ] = { 5, 6 }; * static const char cLedToFlash[ 2 ] = { 5, 6 };
static const TickType_t uxFlashRates[ 2 ] = { 200, 400 }; * static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };
*
// Must start every co-routine with a call to crSTART(); * // Must start every co-routine with a call to crSTART();
crSTART( xHandle ); * crSTART( xHandle );
*
for( ;; ) * for( ;; )
{ * {
// This co-routine just delays for a fixed period, then toggles * // This co-routine just delays for a fixed period, then toggles
// an LED. Two co-routines are created using this function, so * // an LED. Two co-routines are created using this function, so
// the uxIndex parameter is used to tell the co-routine which * // the uxIndex parameter is used to tell the co-routine which
// LED to flash and how int32_t to delay. This assumes xQueue has * // LED to flash and how int32_t to delay. This assumes xQueue has
// already been created. * // already been created.
vParTestToggleLED( cLedToFlash[ uxIndex ] ); * vParTestToggleLED( cLedToFlash[ uxIndex ] );
crDELAY( xHandle, uxFlashRates[ uxIndex ] ); * crDELAY( xHandle, uxFlashRates[ uxIndex ] );
} * }
*
// Must end every co-routine with a call to crEND(); * // Must end every co-routine with a call to crEND();
crEND(); * crEND();
} * }
*
// Function that creates two co-routines. * // Function that creates two co-routines.
void vOtherFunction( void ) * void vOtherFunction( void )
{ * {
uint8_t ucParameterToPass; * uint8_t ucParameterToPass;
TaskHandle_t xHandle; * TaskHandle_t xHandle;
*
// Create two co-routines at priority 0. The first is given index 0 * // 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 * // so (from the code above) toggles LED 5 every 200 ticks. The second
// is given index 1 so toggles LED 6 every 400 ticks. * // is given index 1 so toggles LED 6 every 400 ticks.
for( uxIndex = 0; uxIndex < 2; uxIndex++ ) * for( uxIndex = 0; uxIndex < 2; uxIndex++ )
{ * {
xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex ); * xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
} * }
} * }
</pre> * </pre>
* \defgroup xCoRoutineCreate xCoRoutineCreate * \defgroup xCoRoutineCreate xCoRoutineCreate
* \ingroup Tasks * \ingroup Tasks
*/ */
BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex ); BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode,
UBaseType_t uxPriority,
UBaseType_t uxIndex );
/** /**
* croutine. h * croutine. h
*<pre> *<pre>
void vCoRoutineSchedule( void );</pre> * void vCoRoutineSchedule( void );</pre>
* *
* Run a co-routine. * Run a co-routine.
* *
@ -147,103 +150,109 @@ BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPri
* hook). * hook).
* *
* Example usage: * Example usage:
<pre> * <pre>
// This idle task hook will schedule a co-routine each time it is called. * // 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. * // The rest of the idle task will execute between co-routine calls.
void vApplicationIdleHook( void ) * void vApplicationIdleHook( void )
{ * {
vCoRoutineSchedule(); * vCoRoutineSchedule();
} * }
*
// Alternatively, if you do not require any other part of the idle task to * // Alternatively, if you do not require any other part of the idle task to
// execute, the idle task hook can call vCoRoutineSchedule() within an * // execute, the idle task hook can call vCoRoutineSchedule() within an
// infinite loop. * // infinite loop.
void vApplicationIdleHook( void ) * void vApplicationIdleHook( void )
{ * {
for( ;; ) * for( ;; )
{ * {
vCoRoutineSchedule(); * vCoRoutineSchedule();
} * }
} * }
</pre> * </pre>
* \defgroup vCoRoutineSchedule vCoRoutineSchedule * \defgroup vCoRoutineSchedule vCoRoutineSchedule
* \ingroup Tasks * \ingroup Tasks
*/ */
void vCoRoutineSchedule( void ); void vCoRoutineSchedule( void );
/** /**
* croutine. h * croutine. h
* <pre> * <pre>
crSTART( CoRoutineHandle_t xHandle );</pre> * crSTART( CoRoutineHandle_t xHandle );</pre>
* *
* This macro MUST always be called at the start of a co-routine function. * This macro MUST always be called at the start of a co-routine function.
* *
* Example usage: * Example usage:
<pre> * <pre>
// Co-routine to be created. * // Co-routine to be created.
void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) * 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. * // Variables in co-routines must be declared static if they must maintain value across a blocking call.
static int32_t ulAVariable; * static int32_t ulAVariable;
*
// Must start every co-routine with a call to crSTART(); * // Must start every co-routine with a call to crSTART();
crSTART( xHandle ); * crSTART( xHandle );
*
for( ;; ) * for( ;; )
{ * {
// Co-routine functionality goes here. * // Co-routine functionality goes here.
} * }
*
// Must end every co-routine with a call to crEND(); * // Must end every co-routine with a call to crEND();
crEND(); * crEND();
}</pre> * }</pre>
* \defgroup crSTART crSTART * \defgroup crSTART crSTART
* \ingroup Tasks * \ingroup Tasks
*/ */
#define crSTART( pxCRCB ) switch( ( ( CRCB_t * )( pxCRCB ) )->uxState ) { case 0: #define crSTART( pxCRCB ) \
switch( ( ( CRCB_t * ) ( pxCRCB ) )->uxState ) { \
case 0:
/** /**
* croutine. h * croutine. h
* <pre> * <pre>
crEND();</pre> * crEND();</pre>
* *
* This macro MUST always be called at the end of a co-routine function. * This macro MUST always be called at the end of a co-routine function.
* *
* Example usage: * Example usage:
<pre> * <pre>
// Co-routine to be created. * // Co-routine to be created.
void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) * 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. * // Variables in co-routines must be declared static if they must maintain value across a blocking call.
static int32_t ulAVariable; * static int32_t ulAVariable;
*
// Must start every co-routine with a call to crSTART(); * // Must start every co-routine with a call to crSTART();
crSTART( xHandle ); * crSTART( xHandle );
*
for( ;; ) * for( ;; )
{ * {
// Co-routine functionality goes here. * // Co-routine functionality goes here.
} * }
*
// Must end every co-routine with a call to crEND(); * // Must end every co-routine with a call to crEND();
crEND(); * crEND();
}</pre> * }</pre>
* \defgroup crSTART crSTART * \defgroup crSTART crSTART
* \ingroup Tasks * \ingroup Tasks
*/ */
#define crEND() } #define crEND() }
/* /*
* These macros are intended for internal use by the co-routine implementation * These macros are intended for internal use by the co-routine implementation
* only. The macros should not be used directly by application writers. * 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_STATE0( xHandle ) \
#define crSET_STATE1( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1): ( ( 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 * croutine. h
*<pre> *<pre>
crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );</pre> * crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );</pre>
* *
* Delay a co-routine for a fixed period of time. * Delay a co-routine for a fixed period of time.
* *
@ -260,33 +269,33 @@ void vCoRoutineSchedule( void );
* can be used to convert ticks to milliseconds. * can be used to convert ticks to milliseconds.
* *
* Example usage: * Example usage:
<pre> * <pre>
// Co-routine to be created. * // Co-routine to be created.
void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) * 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. * // 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. * // This may not be necessary for const variables.
// We are to delay for 200ms. * // We are to delay for 200ms.
static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS; * static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;
*
// Must start every co-routine with a call to crSTART(); * // Must start every co-routine with a call to crSTART();
crSTART( xHandle ); * crSTART( xHandle );
*
for( ;; ) * for( ;; )
{ * {
// Delay for 200ms. * // Delay for 200ms.
crDELAY( xHandle, xDelayTime ); * crDELAY( xHandle, xDelayTime );
*
// Do something here. * // Do something here.
} * }
*
// Must end every co-routine with a call to crEND(); * // Must end every co-routine with a call to crEND();
crEND(); * crEND();
}</pre> * }</pre>
* \defgroup crDELAY crDELAY * \defgroup crDELAY crDELAY
* \ingroup Tasks * \ingroup Tasks
*/ */
#define crDELAY( xHandle, xTicksToDelay ) \ #define crDELAY( xHandle, xTicksToDelay ) \
if( ( xTicksToDelay ) > 0 ) \ if( ( xTicksToDelay ) > 0 ) \
{ \ { \
vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \ vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \
@ -295,13 +304,13 @@ void vCoRoutineSchedule( void );
/** /**
* <pre> * <pre>
crQUEUE_SEND( * crQUEUE_SEND(
CoRoutineHandle_t xHandle, * CoRoutineHandle_t xHandle,
QueueHandle_t pxQueue, * QueueHandle_t pxQueue,
void *pvItemToQueue, * void *pvItemToQueue,
TickType_t xTicksToWait, * TickType_t xTicksToWait,
BaseType_t *pxResult * BaseType_t *pxResult
)</pre> * )</pre>
* *
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
@ -341,44 +350,44 @@ void vCoRoutineSchedule( void );
* error defined within ProjDefs.h. * error defined within ProjDefs.h.
* *
* Example usage: * Example usage:
<pre> * <pre>
// Co-routine function that blocks for a fixed period then posts a number onto * // Co-routine function that blocks for a fixed period then posts a number onto
// a queue. * // a queue.
static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) * 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. * // 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 xNumberToPost = 0;
static BaseType_t xResult; * static BaseType_t xResult;
*
// Co-routines must begin with a call to crSTART(). * // Co-routines must begin with a call to crSTART().
crSTART( xHandle ); * crSTART( xHandle );
*
for( ;; ) * for( ;; )
{ * {
// This assumes the queue has already been created. * // This assumes the queue has already been created.
crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult ); * crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
*
if( xResult != pdPASS ) * if( xResult != pdPASS )
{ * {
// The message was not posted! * // The message was not posted!
} * }
*
// Increment the number to be posted onto the queue. * // Increment the number to be posted onto the queue.
xNumberToPost++; * xNumberToPost++;
*
// Delay for 100 ticks. * // Delay for 100 ticks.
crDELAY( xHandle, 100 ); * crDELAY( xHandle, 100 );
} * }
*
// Co-routines must end with a call to crEND(). * // Co-routines must end with a call to crEND().
crEND(); * crEND();
}</pre> * }</pre>
* \defgroup crQUEUE_SEND crQUEUE_SEND * \defgroup crQUEUE_SEND crQUEUE_SEND
* \ingroup Tasks * \ingroup Tasks
*/ */
#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \ #define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \
{ \ { \
*( pxResult ) = xQueueCRSend( ( pxQueue) , ( pvItemToQueue) , ( xTicksToWait ) ); \ *( pxResult ) = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), ( xTicksToWait ) ); \
if( *( pxResult ) == errQUEUE_BLOCKED ) \ if( *( pxResult ) == errQUEUE_BLOCKED ) \
{ \ { \
crSET_STATE0( ( xHandle ) ); \ crSET_STATE0( ( xHandle ) ); \
@ -389,18 +398,18 @@ void vCoRoutineSchedule( void );
crSET_STATE1( ( xHandle ) ); \ crSET_STATE1( ( xHandle ) ); \
*pxResult = pdPASS; \ *pxResult = pdPASS; \
} \ } \
} }
/** /**
* croutine. h * croutine. h
* <pre> * <pre>
crQUEUE_RECEIVE( * crQUEUE_RECEIVE(
CoRoutineHandle_t xHandle, * CoRoutineHandle_t xHandle,
QueueHandle_t pxQueue, * QueueHandle_t pxQueue,
void *pvBuffer, * void *pvBuffer,
TickType_t xTicksToWait, * TickType_t xTicksToWait,
BaseType_t *pxResult * BaseType_t *pxResult
)</pre> * )</pre>
* *
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
@ -439,58 +448,58 @@ void vCoRoutineSchedule( void );
* an error code as defined within ProjDefs.h. * an error code as defined within ProjDefs.h.
* *
* Example usage: * Example usage:
<pre> * <pre>
// A co-routine receives the number of an LED to flash from a queue. It * // A co-routine receives the number of an LED to flash from a queue. It
// blocks on the queue until the number is received. * // blocks on the queue until the number is received.
static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) * 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. * // Variables in co-routines must be declared static if they must maintain value across a blocking call.
static BaseType_t xResult; * static BaseType_t xResult;
static UBaseType_t uxLEDToFlash; * static UBaseType_t uxLEDToFlash;
*
// All co-routines must start with a call to crSTART(). * // All co-routines must start with a call to crSTART().
crSTART( xHandle ); * crSTART( xHandle );
*
for( ;; ) * for( ;; )
{ * {
// Wait for data to become available on the queue. * // Wait for data to become available on the queue.
crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult ); * crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
*
if( xResult == pdPASS ) * if( xResult == pdPASS )
{ * {
// We received the LED to flash - flash it! * // We received the LED to flash - flash it!
vParTestToggleLED( uxLEDToFlash ); * vParTestToggleLED( uxLEDToFlash );
} * }
} * }
*
crEND(); * crEND();
}</pre> * }</pre>
* \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE * \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE
* \ingroup Tasks * \ingroup Tasks
*/ */
#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \ #define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \
{ \ { \
*( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), ( xTicksToWait ) ); \ *( pxResult ) = xQueueCRReceive( ( pxQueue ), ( pvBuffer ), ( xTicksToWait ) ); \
if( *( pxResult ) == errQUEUE_BLOCKED ) \ if( *( pxResult ) == errQUEUE_BLOCKED ) \
{ \ { \
crSET_STATE0( ( xHandle ) ); \ crSET_STATE0( ( xHandle ) ); \
*( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), 0 ); \ *( pxResult ) = xQueueCRReceive( ( pxQueue ), ( pvBuffer ), 0 ); \
} \ } \
if( *( pxResult ) == errQUEUE_YIELD ) \ if( *( pxResult ) == errQUEUE_YIELD ) \
{ \ { \
crSET_STATE1( ( xHandle ) ); \ crSET_STATE1( ( xHandle ) ); \
*( pxResult ) = pdPASS; \ *( pxResult ) = pdPASS; \
} \ } \
} }
/** /**
* croutine. h * croutine. h
* <pre> * <pre>
crQUEUE_SEND_FROM_ISR( * crQUEUE_SEND_FROM_ISR(
QueueHandle_t pxQueue, * QueueHandle_t pxQueue,
void *pvItemToQueue, * void *pvItemToQueue,
BaseType_t xCoRoutinePreviouslyWoken * BaseType_t xCoRoutinePreviouslyWoken
)</pre> * )</pre>
* *
* The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
* co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
@ -525,69 +534,69 @@ void vCoRoutineSchedule( void );
* the ISR. * the ISR.
* *
* Example usage: * Example usage:
<pre> * <pre>
// A co-routine that blocks on a queue waiting for characters to be received. * // A co-routine that blocks on a queue waiting for characters to be received.
static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) * static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
{ * {
char cRxedChar; * char cRxedChar;
BaseType_t xResult; * BaseType_t xResult;
*
// All co-routines must start with a call to crSTART(). * // All co-routines must start with a call to crSTART().
crSTART( xHandle ); * crSTART( xHandle );
*
for( ;; ) * for( ;; )
{ * {
// Wait for data to become available on the queue. This assumes the * // Wait for data to become available on the queue. This assumes the
// queue xCommsRxQueue has already been created! * // queue xCommsRxQueue has already been created!
crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult ); * crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
*
// Was a character received? * // Was a character received?
if( xResult == pdPASS ) * if( xResult == pdPASS )
{ * {
// Process the character here. * // Process the character here.
} * }
} * }
*
// All co-routines must end with a call to crEND(). * // All co-routines must end with a call to crEND().
crEND(); * crEND();
} * }
*
// An ISR that uses a queue to send characters received on a serial port to * // An ISR that uses a queue to send characters received on a serial port to
// a co-routine. * // a co-routine.
void vUART_ISR( void ) * void vUART_ISR( void )
{ * {
char cRxedChar; * char cRxedChar;
BaseType_t xCRWokenByPost = pdFALSE; * BaseType_t xCRWokenByPost = pdFALSE;
*
// We loop around reading characters until there are none left in the UART. * // We loop around reading characters until there are none left in the UART.
while( UART_RX_REG_NOT_EMPTY() ) * while( UART_RX_REG_NOT_EMPTY() )
{ * {
// Obtain the character from the UART. * // Obtain the character from the UART.
cRxedChar = UART_RX_REG; * cRxedChar = UART_RX_REG;
*
// Post the character onto a queue. xCRWokenByPost will be pdFALSE * // Post the character onto a queue. xCRWokenByPost will be pdFALSE
// the first time around the loop. If the post causes a co-routine * // the first time around the loop. If the post causes a co-routine
// to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE. * // 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 * // 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 * // blocked on the queue only one is woken by this ISR no matter how
// many characters are posted to the queue. * // many characters are posted to the queue.
xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost ); * xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
} * }
}</pre> * }</pre>
* \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR * \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR
* \ingroup Tasks * \ingroup Tasks
*/ */
#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) ) #define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) )
/** /**
* croutine. h * croutine. h
* <pre> * <pre>
crQUEUE_SEND_FROM_ISR( * crQUEUE_SEND_FROM_ISR(
QueueHandle_t pxQueue, * QueueHandle_t pxQueue,
void *pvBuffer, * void *pvBuffer,
BaseType_t * pxCoRoutineWoken * BaseType_t * pxCoRoutineWoken
)</pre> * )</pre>
* *
* The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
* co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
@ -622,75 +631,75 @@ void vCoRoutineSchedule( void );
* pdFALSE. * pdFALSE.
* *
* Example usage: * Example usage:
<pre> * <pre>
// A co-routine that posts a character to a queue then blocks for a fixed * // A co-routine that posts a character to a queue then blocks for a fixed
// period. The character is incremented each time. * // period. The character is incremented each time.
static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) * static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
{ * {
// cChar holds its value while this co-routine is blocked and must therefore * // cChar holds its value while this co-routine is blocked and must therefore
// be declared static. * // be declared static.
static char cCharToTx = 'a'; * static char cCharToTx = 'a';
BaseType_t xResult; * BaseType_t xResult;
*
// All co-routines must start with a call to crSTART(). * // All co-routines must start with a call to crSTART().
crSTART( xHandle ); * crSTART( xHandle );
*
for( ;; ) * for( ;; )
{ * {
// Send the next character to the queue. * // Send the next character to the queue.
crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult ); * crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
*
if( xResult == pdPASS ) * if( xResult == pdPASS )
{ * {
// The character was successfully posted to the queue. * // The character was successfully posted to the queue.
} * }
else * else
{ * {
// Could not post the character to the queue. * // Could not post the character to the queue.
} * }
*
// Enable the UART Tx interrupt to cause an interrupt in this * // Enable the UART Tx interrupt to cause an interrupt in this
// hypothetical UART. The interrupt will obtain the character * // hypothetical UART. The interrupt will obtain the character
// from the queue and send it. * // from the queue and send it.
ENABLE_RX_INTERRUPT(); * ENABLE_RX_INTERRUPT();
*
// Increment to the next character then block for a fixed period. * // Increment to the next character then block for a fixed period.
// cCharToTx will maintain its value across the delay as it is * // cCharToTx will maintain its value across the delay as it is
// declared static. * // declared static.
cCharToTx++; * cCharToTx++;
if( cCharToTx > 'x' ) * if( cCharToTx > 'x' )
{ * {
cCharToTx = 'a'; * cCharToTx = 'a';
} * }
crDELAY( 100 ); * crDELAY( 100 );
} * }
*
// All co-routines must end with a call to crEND(). * // All co-routines must end with a call to crEND().
crEND(); * crEND();
} * }
*
// An ISR that uses a queue to receive characters to send on a UART. * // An ISR that uses a queue to receive characters to send on a UART.
void vUART_ISR( void ) * void vUART_ISR( void )
{ * {
char cCharToTx; * char cCharToTx;
BaseType_t xCRWokenByPost = pdFALSE; * BaseType_t xCRWokenByPost = pdFALSE;
*
while( UART_TX_REG_EMPTY() ) * while( UART_TX_REG_EMPTY() )
{ * {
// Are there any characters in the queue waiting to be sent? * // Are there any characters in the queue waiting to be sent?
// xCRWokenByPost will automatically be set to pdTRUE if a co-routine * // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
// is woken by the post - ensuring that only a single co-routine is * // is woken by the post - ensuring that only a single co-routine is
// woken no matter how many times we go around this loop. * // woken no matter how many times we go around this loop.
if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) ) * if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
{ * {
SEND_CHARACTER( cCharToTx ); * SEND_CHARACTER( cCharToTx );
} * }
} * }
}</pre> * }</pre>
* \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR * \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR
* \ingroup Tasks * \ingroup Tasks
*/ */
#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) ) #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. * This function is intended for internal use by the co-routine macros only.
@ -701,7 +710,8 @@ void vCoRoutineSchedule( void );
* Removes the current co-routine from its ready list and places it in the * Removes the current co-routine from its ready list and places it in the
* appropriate delayed list. * appropriate delayed list.
*/ */
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList ); void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay,
List_t * pxEventList );
/* /*
* This function is intended for internal use by the queue implementation only. * This function is intended for internal use by the queue implementation only.
@ -710,10 +720,10 @@ void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList )
* Removes the highest priority co-routine from the event list and places it in * Removes the highest priority co-routine from the event list and places it in
* the pending ready list. * the pending ready list.
*/ */
BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList ); BaseType_t xCoRoutineRemoveFromEventList( const List_t * pxEventList );
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* CO_ROUTINE_H */ #endif /* CO_ROUTINE_H */

View file

@ -29,22 +29,22 @@
/* Each FreeRTOS port has a unique portmacro.h header file. Originally a /* 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 * 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 * 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 * 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 - removing the need for the constant and allowing the
portmacro.h file to be located anywhere in relation to the port being used. 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 * definitions below remain in the code for backward compatibility only. New
projects should not use them. */ * projects should not use them. */
#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT #ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT
#include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h" #include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h"
typedef void ( __interrupt __far *pxISR )(); typedef void ( __interrupt __far * pxISR )();
#endif #endif
#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT #ifdef OPEN_WATCOM_FLASH_LITE_186_PORT
#include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h" #include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h"
typedef void ( __interrupt __far *pxISR )(); typedef void ( __interrupt __far * pxISR )();
#endif #endif
#ifdef GCC_MEGA_AVR #ifdef GCC_MEGA_AVR
@ -208,19 +208,21 @@ projects should not use them. */
#endif #endif
#ifdef BCC_INDUSTRIAL_PC_PORT #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. */ /* A short file name has to be used in place of the normal
* FreeRTOSConfig.h when using the Borland compiler. */
#include "frconfig.h" #include "frconfig.h"
#include "..\portable\BCC\16BitDOS\PC\prtmacro.h" #include "..\portable\BCC\16BitDOS\PC\prtmacro.h"
typedef void ( __interrupt __far *pxISR )(); typedef void ( __interrupt __far * pxISR )();
#endif #endif
#ifdef BCC_FLASH_LITE_186_PORT #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. */ /* A short file name has to be used in place of the normal
* FreeRTOSConfig.h when using the Borland compiler. */
#include "frconfig.h" #include "frconfig.h"
#include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h" #include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h"
typedef void ( __interrupt __far *pxISR )(); typedef void ( __interrupt __far * pxISR )();
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
@ -275,4 +277,3 @@ projects should not use them. */
#endif #endif
#endif /* DEPRECATED_DEFINITIONS_H */ #endif /* DEPRECATED_DEFINITIONS_H */

View file

@ -25,18 +25,18 @@
*/ */
#ifndef EVENT_GROUPS_H #ifndef EVENT_GROUPS_H
#define EVENT_GROUPS_H #define EVENT_GROUPS_H
#ifndef INC_FREERTOS_H #ifndef INC_FREERTOS_H
#error "include FreeRTOS.h" must appear in source files before "include event_groups.h" #error "include FreeRTOS.h" must appear in source files before "include event_groups.h"
#endif #endif
/* FreeRTOS includes. */ /* FreeRTOS includes. */
#include "timers.h" #include "timers.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/** /**
* An event group is a collection of bits to which an application can assign a * An event group is a collection of bits to which an application can assign a
@ -77,8 +77,8 @@ extern "C" {
* \defgroup EventGroupHandle_t EventGroupHandle_t * \defgroup EventGroupHandle_t EventGroupHandle_t
* \ingroup EventGroup * \ingroup EventGroup
*/ */
struct EventGroupDef_t; struct EventGroupDef_t;
typedef struct EventGroupDef_t * EventGroupHandle_t; typedef struct EventGroupDef_t * EventGroupHandle_t;
/* /*
* The type that holds event bits always matches TickType_t - therefore the * The type that holds event bits always matches TickType_t - therefore the
@ -88,13 +88,13 @@ typedef struct EventGroupDef_t * EventGroupHandle_t;
* \defgroup EventBits_t EventBits_t * \defgroup EventBits_t EventBits_t
* \ingroup EventGroup * \ingroup EventGroup
*/ */
typedef TickType_t EventBits_t; typedef TickType_t EventBits_t;
/** /**
* event_groups.h * event_groups.h
*<pre> *<pre>
EventGroupHandle_t xEventGroupCreate( void ); * EventGroupHandle_t xEventGroupCreate( void );
</pre> * </pre>
* *
* Create a new event group. * Create a new event group.
* *
@ -121,36 +121,36 @@ typedef TickType_t EventBits_t;
* event group then NULL is returned. See http://www.freertos.org/a00111.html * event group then NULL is returned. See http://www.freertos.org/a00111.html
* *
* Example usage: * Example usage:
<pre> * <pre>
// Declare a variable to hold the created event group. * // Declare a variable to hold the created event group.
EventGroupHandle_t xCreatedEventGroup; * EventGroupHandle_t xCreatedEventGroup;
*
// Attempt to create the event group. * // Attempt to create the event group.
xCreatedEventGroup = xEventGroupCreate(); * xCreatedEventGroup = xEventGroupCreate();
*
// Was the event group created successfully? * // Was the event group created successfully?
if( xCreatedEventGroup == NULL ) * if( xCreatedEventGroup == NULL )
{ * {
// The event group was not created because there was insufficient * // The event group was not created because there was insufficient
// FreeRTOS heap available. * // FreeRTOS heap available.
} * }
else * else
{ * {
// The event group was created. * // The event group was created.
} * }
</pre> * </pre>
* \defgroup xEventGroupCreate xEventGroupCreate * \defgroup xEventGroupCreate xEventGroupCreate
* \ingroup EventGroup * \ingroup EventGroup
*/ */
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION; EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
#endif #endif
/** /**
* event_groups.h * event_groups.h
*<pre> *<pre>
EventGroupHandle_t xEventGroupCreateStatic( EventGroupHandle_t * pxEventGroupBuffer ); * EventGroupHandle_t xEventGroupCreateStatic( EventGroupHandle_t * pxEventGroupBuffer );
</pre> * </pre>
* *
* Create a new event group. * Create a new event group.
* *
@ -180,34 +180,34 @@ typedef TickType_t EventBits_t;
* returned. If pxEventGroupBuffer was NULL then NULL is returned. * returned. If pxEventGroupBuffer was NULL then NULL is returned.
* *
* Example usage: * Example usage:
<pre> * <pre>
// StaticEventGroup_t is a publicly accessible structure that has the same * // StaticEventGroup_t is a publicly accessible structure that has the same
// size and alignment requirements as the real event group structure. It is * // 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 * // provided as a mechanism for applications to know the size of the event
// group (which is dependent on the architecture and configuration file * // group (which is dependent on the architecture and configuration file
// settings) without breaking the strict data hiding policy by exposing the * // settings) without breaking the strict data hiding policy by exposing the
// real event group internals. This StaticEventGroup_t variable is passed * // real event group internals. This StaticEventGroup_t variable is passed
// into the xSemaphoreCreateEventGroupStatic() function and is used to store * // into the xSemaphoreCreateEventGroupStatic() function and is used to store
// the event group's data structures * // the event group's data structures
StaticEventGroup_t xEventGroupBuffer; * StaticEventGroup_t xEventGroupBuffer;
*
// Create the event group without dynamically allocating any memory. * // Create the event group without dynamically allocating any memory.
xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer ); * xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
</pre> * </pre>
*/ */
#if( configSUPPORT_STATIC_ALLOCATION == 1 ) #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ) PRIVILEGED_FUNCTION; EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) PRIVILEGED_FUNCTION;
#endif #endif
/** /**
* event_groups.h * event_groups.h
*<pre> *<pre>
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, * EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor, * const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit, * const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits, * const BaseType_t xWaitForAllBits,
const TickType_t xTicksToWait ); * const TickType_t xTicksToWait );
</pre> * </pre>
* *
* [Potentially] block to wait for one or more bits to be set within a * [Potentially] block to wait for one or more bits to be set within a
* previously created event group. * previously created event group.
@ -251,53 +251,57 @@ typedef TickType_t EventBits_t;
* pdTRUE. * pdTRUE.
* *
* Example usage: * Example usage:
<pre> * <pre>
#define BIT_0 ( 1 << 0 ) #define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 ) #define BIT_4 ( 1 << 4 )
*
void aFunction( EventGroupHandle_t xEventGroup ) * void aFunction( EventGroupHandle_t xEventGroup )
{ * {
EventBits_t uxBits; * EventBits_t uxBits;
const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS; * const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
*
// Wait a maximum of 100ms for either bit 0 or bit 4 to be set within * // Wait a maximum of 100ms for either bit 0 or bit 4 to be set within
// the event group. Clear the bits before exiting. * // the event group. Clear the bits before exiting.
uxBits = xEventGroupWaitBits( * uxBits = xEventGroupWaitBits(
xEventGroup, // The event group being tested. * xEventGroup, // The event group being tested.
BIT_0 | BIT_4, // The bits within the event group to wait for. * BIT_0 | BIT_4, // The bits within the event group to wait for.
pdTRUE, // BIT_0 and BIT_4 should be cleared before returning. * pdTRUE, // BIT_0 and BIT_4 should be cleared before returning.
pdFALSE, // Don't wait for both bits, either bit will do. * pdFALSE, // Don't wait for both bits, either bit will do.
xTicksToWait ); // Wait a maximum of 100ms for either bit to be set. * xTicksToWait ); // Wait a maximum of 100ms for either bit to be set.
*
if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) ) * if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
{ * {
// xEventGroupWaitBits() returned because both bits were set. * // xEventGroupWaitBits() returned because both bits were set.
} * }
else if( ( uxBits & BIT_0 ) != 0 ) * else if( ( uxBits & BIT_0 ) != 0 )
{ * {
// xEventGroupWaitBits() returned because just BIT_0 was set. * // xEventGroupWaitBits() returned because just BIT_0 was set.
} * }
else if( ( uxBits & BIT_4 ) != 0 ) * else if( ( uxBits & BIT_4 ) != 0 )
{ * {
// xEventGroupWaitBits() returned because just BIT_4 was set. * // xEventGroupWaitBits() returned because just BIT_4 was set.
} * }
else * else
{ * {
// xEventGroupWaitBits() returned because xTicksToWait ticks passed * // xEventGroupWaitBits() returned because xTicksToWait ticks passed
// without either BIT_0 or BIT_4 becoming set. * // without either BIT_0 or BIT_4 becoming set.
} * }
} * }
</pre> * </pre>
* \defgroup xEventGroupWaitBits xEventGroupWaitBits * \defgroup xEventGroupWaitBits xEventGroupWaitBits
* \ingroup EventGroup * \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; 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 * event_groups.h
*<pre> *<pre>
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ); * EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
</pre> * </pre>
* *
* Clear bits within an event group. This function cannot be called from an * Clear bits within an event group. This function cannot be called from an
* interrupt. * interrupt.
@ -311,50 +315,51 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits
* @return The value of the event group before the specified bits were cleared. * @return The value of the event group before the specified bits were cleared.
* *
* Example usage: * Example usage:
<pre> * <pre>
#define BIT_0 ( 1 << 0 ) #define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 ) #define BIT_4 ( 1 << 4 )
*
void aFunction( EventGroupHandle_t xEventGroup ) * void aFunction( EventGroupHandle_t xEventGroup )
{ * {
EventBits_t uxBits; * EventBits_t uxBits;
*
// Clear bit 0 and bit 4 in xEventGroup. * // Clear bit 0 and bit 4 in xEventGroup.
uxBits = xEventGroupClearBits( * uxBits = xEventGroupClearBits(
xEventGroup, // The event group being updated. * xEventGroup, // The event group being updated.
BIT_0 | BIT_4 );// The bits being cleared. * BIT_0 | BIT_4 );// The bits being cleared.
*
if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) ) * if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
{ * {
// Both bit 0 and bit 4 were set before xEventGroupClearBits() was * // Both bit 0 and bit 4 were set before xEventGroupClearBits() was
// called. Both will now be clear (not set). * // called. Both will now be clear (not set).
} * }
else if( ( uxBits & BIT_0 ) != 0 ) * else if( ( uxBits & BIT_0 ) != 0 )
{ * {
// Bit 0 was set before xEventGroupClearBits() was called. It will * // Bit 0 was set before xEventGroupClearBits() was called. It will
// now be clear. * // now be clear.
} * }
else if( ( uxBits & BIT_4 ) != 0 ) * else if( ( uxBits & BIT_4 ) != 0 )
{ * {
// Bit 4 was set before xEventGroupClearBits() was called. It will * // Bit 4 was set before xEventGroupClearBits() was called. It will
// now be clear. * // now be clear.
} * }
else * else
{ * {
// Neither bit 0 nor bit 4 were set in the first place. * // Neither bit 0 nor bit 4 were set in the first place.
} * }
} * }
</pre> * </pre>
* \defgroup xEventGroupClearBits xEventGroupClearBits * \defgroup xEventGroupClearBits xEventGroupClearBits
* \ingroup EventGroup * \ingroup EventGroup
*/ */
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION; EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
/** /**
* event_groups.h * event_groups.h
*<pre> *<pre>
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ); * BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
</pre> * </pre>
* *
* A version of xEventGroupClearBits() that can be called from an interrupt. * A version of xEventGroupClearBits() that can be called from an interrupt.
* *
@ -379,41 +384,42 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBit
* if the timer service queue was full. * if the timer service queue was full.
* *
* Example usage: * Example usage:
<pre> * <pre>
#define BIT_0 ( 1 << 0 ) #define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 ) #define BIT_4 ( 1 << 4 )
*
// An event group which it is assumed has already been created by a call to * // An event group which it is assumed has already been created by a call to
// xEventGroupCreate(). * // xEventGroupCreate().
EventGroupHandle_t xEventGroup; * EventGroupHandle_t xEventGroup;
*
void anInterruptHandler( void ) * void anInterruptHandler( void )
{ * {
// Clear bit 0 and bit 4 in xEventGroup. * // Clear bit 0 and bit 4 in xEventGroup.
xResult = xEventGroupClearBitsFromISR( * xResult = xEventGroupClearBitsFromISR(
xEventGroup, // The event group being updated. * xEventGroup, // The event group being updated.
BIT_0 | BIT_4 ); // The bits being set. * BIT_0 | BIT_4 ); // The bits being set.
*
if( xResult == pdPASS ) * if( xResult == pdPASS )
{ * {
// The message was posted successfully. * // The message was posted successfully.
} * }
} * }
</pre> * </pre>
* \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR * \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR
* \ingroup EventGroup * \ingroup EventGroup
*/ */
#if( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION; BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
#else const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
#else
#define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ) #define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL )
#endif #endif
/** /**
* event_groups.h * event_groups.h
*<pre> *<pre>
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ); * EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
</pre> * </pre>
* *
* Set bits within an event group. * Set bits within an event group.
* This function cannot be called from an interrupt. xEventGroupSetBitsFromISR() * This function cannot be called from an interrupt. xEventGroupSetBitsFromISR()
@ -439,55 +445,56 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBit
* event group value before the call to xEventGroupSetBits() returns. * event group value before the call to xEventGroupSetBits() returns.
* *
* Example usage: * Example usage:
<pre> * <pre>
#define BIT_0 ( 1 << 0 ) #define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 ) #define BIT_4 ( 1 << 4 )
*
void aFunction( EventGroupHandle_t xEventGroup ) * void aFunction( EventGroupHandle_t xEventGroup )
{ * {
EventBits_t uxBits; * EventBits_t uxBits;
*
// Set bit 0 and bit 4 in xEventGroup. * // Set bit 0 and bit 4 in xEventGroup.
uxBits = xEventGroupSetBits( * uxBits = xEventGroupSetBits(
xEventGroup, // The event group being updated. * xEventGroup, // The event group being updated.
BIT_0 | BIT_4 );// The bits being set. * BIT_0 | BIT_4 );// The bits being set.
*
if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) ) * if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
{ * {
// Both bit 0 and bit 4 remained set when the function returned. * // Both bit 0 and bit 4 remained set when the function returned.
} * }
else if( ( uxBits & BIT_0 ) != 0 ) * else if( ( uxBits & BIT_0 ) != 0 )
{ * {
// Bit 0 remained set when the function returned, but bit 4 was * // Bit 0 remained set when the function returned, but bit 4 was
// cleared. It might be that bit 4 was cleared automatically as a * // cleared. It might be that bit 4 was cleared automatically as a
// task that was waiting for bit 4 was removed from the Blocked * // task that was waiting for bit 4 was removed from the Blocked
// state. * // state.
} * }
else if( ( uxBits & BIT_4 ) != 0 ) * else if( ( uxBits & BIT_4 ) != 0 )
{ * {
// Bit 4 remained set when the function returned, but bit 0 was * // Bit 4 remained set when the function returned, but bit 0 was
// cleared. It might be that bit 0 was cleared automatically as a * // cleared. It might be that bit 0 was cleared automatically as a
// task that was waiting for bit 0 was removed from the Blocked * // task that was waiting for bit 0 was removed from the Blocked
// state. * // state.
} * }
else * else
{ * {
// Neither bit 0 nor bit 4 remained set. It might be that a task * // 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 * // was waiting for both of the bits to be set, and the bits were
// cleared as the task left the Blocked state. * // cleared as the task left the Blocked state.
} * }
} * }
</pre> * </pre>
* \defgroup xEventGroupSetBits xEventGroupSetBits * \defgroup xEventGroupSetBits xEventGroupSetBits
* \ingroup EventGroup * \ingroup EventGroup
*/ */
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION; EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION;
/** /**
* event_groups.h * event_groups.h
*<pre> *<pre>
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ); * BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
</pre> * </pre>
* *
* A version of xEventGroupSetBits() that can be called from an interrupt. * A version of xEventGroupSetBits() that can be called from an interrupt.
* *
@ -520,55 +527,57 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_
* if the timer service queue was full. * if the timer service queue was full.
* *
* Example usage: * Example usage:
<pre> * <pre>
#define BIT_0 ( 1 << 0 ) #define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 ) #define BIT_4 ( 1 << 4 )
*
// An event group which it is assumed has already been created by a call to * // An event group which it is assumed has already been created by a call to
// xEventGroupCreate(). * // xEventGroupCreate().
EventGroupHandle_t xEventGroup; * EventGroupHandle_t xEventGroup;
*
void anInterruptHandler( void ) * void anInterruptHandler( void )
{ * {
BaseType_t xHigherPriorityTaskWoken, xResult; * BaseType_t xHigherPriorityTaskWoken, xResult;
*
// xHigherPriorityTaskWoken must be initialised to pdFALSE. * // xHigherPriorityTaskWoken must be initialised to pdFALSE.
xHigherPriorityTaskWoken = pdFALSE; * xHigherPriorityTaskWoken = pdFALSE;
*
// Set bit 0 and bit 4 in xEventGroup. * // Set bit 0 and bit 4 in xEventGroup.
xResult = xEventGroupSetBitsFromISR( * xResult = xEventGroupSetBitsFromISR(
xEventGroup, // The event group being updated. * xEventGroup, // The event group being updated.
BIT_0 | BIT_4 // The bits being set. * BIT_0 | BIT_4 // The bits being set.
&xHigherPriorityTaskWoken ); * &xHigherPriorityTaskWoken );
*
// Was the message posted successfully? * // Was the message posted successfully?
if( xResult == pdPASS ) * if( xResult == pdPASS )
{ * {
// If xHigherPriorityTaskWoken is now set to pdTRUE then a context * // If xHigherPriorityTaskWoken is now set to pdTRUE then a context
// switch should be requested. The macro used is port specific and * // switch should be requested. The macro used is port specific and
// will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - * // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
// refer to the documentation page for the port being used. * // refer to the documentation page for the port being used.
portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); * portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
} * }
} * }
</pre> * </pre>
* \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR * \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR
* \ingroup EventGroup * \ingroup EventGroup
*/ */
#if( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
#else const EventBits_t uxBitsToSet,
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
#else
#define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ) #define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken )
#endif #endif
/** /**
* event_groups.h * event_groups.h
*<pre> *<pre>
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, * EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet, * const EventBits_t uxBitsToSet,
const EventBits_t uxBitsToWaitFor, * const EventBits_t uxBitsToWaitFor,
TickType_t xTicksToWait ); * TickType_t xTicksToWait );
</pre> * </pre>
* *
* Atomically set bits within an event group, then wait for a combination of * 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 * bits to be set within the same event group. This functionality is typically
@ -607,92 +616,95 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_
* automatically cleared. * automatically cleared.
* *
* Example usage: * Example usage:
<pre> * <pre>
// Bits used by the three tasks. * // Bits used by the three tasks.
#define TASK_0_BIT ( 1 << 0 ) #define TASK_0_BIT ( 1 << 0 )
#define TASK_1_BIT ( 1 << 1 ) #define TASK_1_BIT ( 1 << 1 )
#define TASK_2_BIT ( 1 << 2 ) #define TASK_2_BIT ( 1 << 2 )
*
#define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT ) #define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )
*
// Use an event group to synchronise three tasks. It is assumed this event * // Use an event group to synchronise three tasks. It is assumed this event
// group has already been created elsewhere. * // group has already been created elsewhere.
EventGroupHandle_t xEventBits; * EventGroupHandle_t xEventBits;
*
void vTask0( void *pvParameters ) * void vTask0( void *pvParameters )
{ * {
EventBits_t uxReturn; * EventBits_t uxReturn;
TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS; * TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
*
for( ;; ) * for( ;; )
{ * {
// Perform task functionality here. * // Perform task functionality here.
*
// Set bit 0 in the event flag to note this task has reached the * // 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 * // sync point. The other two tasks will set the other two bits defined
// by ALL_SYNC_BITS. All three tasks have reached the synchronisation * // 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 * // point when all the ALL_SYNC_BITS are set. Wait a maximum of 100ms
// for this to happen. * // for this to happen.
uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait ); * uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait );
*
if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS ) * if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
{ * {
// All three tasks reached the synchronisation point before the call * // All three tasks reached the synchronisation point before the call
// to xEventGroupSync() timed out. * // to xEventGroupSync() timed out.
} * }
} * }
} * }
*
void vTask1( void *pvParameters ) * void vTask1( void *pvParameters )
{ * {
for( ;; ) * for( ;; )
{ * {
// Perform task functionality here. * // Perform task functionality here.
*
// Set bit 1 in the event flag to note this task has reached the * // 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 * // synchronisation point. The other two tasks will set the other two
// bits defined by ALL_SYNC_BITS. All three tasks have reached the * // bits defined by ALL_SYNC_BITS. All three tasks have reached the
// synchronisation point when all the ALL_SYNC_BITS are set. Wait * // synchronisation point when all the ALL_SYNC_BITS are set. Wait
// indefinitely for this to happen. * // indefinitely for this to happen.
xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY ); * xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );
*
// xEventGroupSync() was called with an indefinite block time, so * // xEventGroupSync() was called with an indefinite block time, so
// this task will only reach here if the syncrhonisation was made by all * // this task will only reach here if the syncrhonisation was made by all
// three tasks, so there is no need to test the return value. * // three tasks, so there is no need to test the return value.
} * }
} * }
*
void vTask2( void *pvParameters ) * void vTask2( void *pvParameters )
{ * {
for( ;; ) * for( ;; )
{ * {
// Perform task functionality here. * // Perform task functionality here.
*
// Set bit 2 in the event flag to note this task has reached the * // 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 * // synchronisation point. The other two tasks will set the other two
// bits defined by ALL_SYNC_BITS. All three tasks have reached the * // bits defined by ALL_SYNC_BITS. All three tasks have reached the
// synchronisation point when all the ALL_SYNC_BITS are set. Wait * // synchronisation point when all the ALL_SYNC_BITS are set. Wait
// indefinitely for this to happen. * // indefinitely for this to happen.
xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY ); * xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );
*
// xEventGroupSync() was called with an indefinite block time, so * // xEventGroupSync() was called with an indefinite block time, so
// this task will only reach here if the syncrhonisation was made by all * // this task will only reach here if the syncrhonisation was made by all
// three tasks, so there is no need to test the return value. * // three tasks, so there is no need to test the return value.
} * }
} * }
*
</pre> * </pre>
* \defgroup xEventGroupSync xEventGroupSync * \defgroup xEventGroupSync xEventGroupSync
* \ingroup EventGroup * \ingroup EventGroup
*/ */
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
const EventBits_t uxBitsToWaitFor,
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/** /**
* event_groups.h * event_groups.h
*<pre> *<pre>
EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup ); * EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
</pre> * </pre>
* *
* Returns the current value of the bits in an event group. This function * Returns the current value of the bits in an event group. This function
* cannot be used from an interrupt. * cannot be used from an interrupt.
@ -704,13 +716,13 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t u
* \defgroup xEventGroupGetBits xEventGroupGetBits * \defgroup xEventGroupGetBits xEventGroupGetBits
* \ingroup EventGroup * \ingroup EventGroup
*/ */
#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 ) #define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 )
/** /**
* event_groups.h * event_groups.h
*<pre> *<pre>
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ); * EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
</pre> * </pre>
* *
* A version of xEventGroupGetBits() that can be called from an ISR. * A version of xEventGroupGetBits() that can be called from an ISR.
* *
@ -721,13 +733,13 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t u
* \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR * \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR
* \ingroup EventGroup * \ingroup EventGroup
*/ */
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION; EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
/** /**
* event_groups.h * event_groups.h
*<pre> *<pre>
void xEventGroupDelete( EventGroupHandle_t xEventGroup ); * void xEventGroupDelete( EventGroupHandle_t xEventGroup );
</pre> * </pre>
* *
* Delete an event group that was previously created by a call to * Delete an event group that was previously created by a call to
* xEventGroupCreate(). Tasks that are blocked on the event group will be * xEventGroupCreate(). Tasks that are blocked on the event group will be
@ -735,22 +747,23 @@ EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEG
* *
* @param xEventGroup The event group being deleted. * @param xEventGroup The event group being deleted.
*/ */
void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION; void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
/* For internal use only. */ /* For internal use only. */
void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION; void vEventGroupSetBitsCallback( void * pvEventGroup,
void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION; const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION;
void vEventGroupClearBitsCallback( void * pvEventGroup,
const uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION;
#if (configUSE_TRACE_FACILITY == 1) #if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) PRIVILEGED_FUNCTION; UBaseType_t uxEventGroupGetNumber( void * xEventGroup ) PRIVILEGED_FUNCTION;
void vEventGroupSetNumber( void* xEventGroup, UBaseType_t uxEventGroupNumber ) PRIVILEGED_FUNCTION; void vEventGroupSetNumber( void * xEventGroup,
#endif UBaseType_t uxEventGroupNumber ) PRIVILEGED_FUNCTION;
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* EVENT_GROUPS_H */ #endif /* EVENT_GROUPS_H */

View file

@ -57,7 +57,7 @@
#endif #endif
#ifndef LIST_H #ifndef LIST_H
#define LIST_H #define LIST_H
/* /*
* The list structure members are modified from within interrupts, and therefore * The list structure members are modified from within interrupts, and therefore
@ -87,20 +87,20 @@
* FreeRTOSConfig.h (without the quotes): * FreeRTOSConfig.h (without the quotes):
* "#define configLIST_VOLATILE volatile" * "#define configLIST_VOLATILE volatile"
*/ */
#ifndef configLIST_VOLATILE #ifndef configLIST_VOLATILE
#define configLIST_VOLATILE #define configLIST_VOLATILE
#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */ #endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Macros that can be used to place known values within the list structures, /* 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 * 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 * the application. These may catch the list data structures being overwritten in
memory. They will not catch data errors caused by incorrect configuration or * memory. They will not catch data errors caused by incorrect configuration or
use of FreeRTOS.*/ * use of FreeRTOS.*/
#if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 )
/* Define the macros to do nothing. */ /* Define the macros to do nothing. */
#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
@ -112,32 +112,32 @@ use of FreeRTOS.*/
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )
#define listTEST_LIST_ITEM_INTEGRITY( pxItem ) #define listTEST_LIST_ITEM_INTEGRITY( pxItem )
#define listTEST_LIST_INTEGRITY( pxList ) #define listTEST_LIST_INTEGRITY( pxList )
#else #else /* if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) */
/* Define macros that add new members into the list structures. */ /* Define macros that add new members into the list structures. */
#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1; #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1;
#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2; #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2;
#define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1; #define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1;
#define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2; #define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2;
/* Define macros that set the new structure members to known values. */ /* 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_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_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_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = 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 /* Define macros that will assert if one of the structure members does not
contain its expected value. */ * contain its expected value. */
#define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_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 ) ) #define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
#endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */ #endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */
/* /*
* Definition of the only type of object that a list can contain. * Definition of the only type of object that a list can contain.
*/ */
struct xLIST; struct xLIST;
struct xLIST_ITEM struct xLIST_ITEM
{ {
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */ configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */
struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */ struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */
@ -145,29 +145,29 @@ struct xLIST_ITEM
void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ void * 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). */ 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. */ listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
}; };
typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */ typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */
struct xMINI_LIST_ITEM struct xMINI_LIST_ITEM
{ {
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
configLIST_VOLATILE TickType_t xItemValue; configLIST_VOLATILE TickType_t xItemValue;
struct xLIST_ITEM * configLIST_VOLATILE pxNext; struct xLIST_ITEM * configLIST_VOLATILE pxNext;
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
}; };
typedef struct xMINI_LIST_ITEM MiniListItem_t; typedef struct xMINI_LIST_ITEM MiniListItem_t;
/* /*
* Definition of the type of queue used by the scheduler. * Definition of the type of queue used by the scheduler.
*/ */
typedef struct xLIST typedef struct xLIST
{ {
listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
volatile UBaseType_t uxNumberOfItems; 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 (). */ 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. */ 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. */ listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
} List_t; } List_t;
/* /*
* Access macro to set the owner of a list item. The owner of a list item * Access macro to set the owner of a list item. The owner of a list item
@ -176,7 +176,7 @@ typedef struct xLIST
* \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
* \ingroup LinkedList * \ingroup LinkedList
*/ */
#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) ) #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 * Access macro to get the owner of a list item. The owner of a list item
@ -185,7 +185,7 @@ typedef struct xLIST
* \page listGET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER * \page listGET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
* \ingroup LinkedList * \ingroup LinkedList
*/ */
#define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner ) #define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner )
/* /*
* Access macro to set the value of the list item. In most cases the value is * Access macro to set the value of the list item. In most cases the value is
@ -194,7 +194,7 @@ typedef struct xLIST
* \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE
* \ingroup LinkedList * \ingroup LinkedList
*/ */
#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) ) #define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) )
/* /*
* Access macro to retrieve the value of the list item. The value can * Access macro to retrieve the value of the list item. The value can
@ -204,7 +204,7 @@ typedef struct xLIST
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
* \ingroup LinkedList * \ingroup LinkedList
*/ */
#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue ) #define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue )
/* /*
* Access macro to retrieve the value of the list item at the head of a given * Access macro to retrieve the value of the list item at the head of a given
@ -213,7 +213,7 @@ typedef struct xLIST
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
* \ingroup LinkedList * \ingroup LinkedList
*/ */
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue ) #define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue )
/* /*
* Return the list item at the head of the list. * Return the list item at the head of the list.
@ -221,7 +221,7 @@ typedef struct xLIST
* \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY * \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY
* \ingroup LinkedList * \ingroup LinkedList
*/ */
#define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext ) #define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext )
/* /*
* Return the next list item. * Return the next list item.
@ -229,7 +229,7 @@ typedef struct xLIST
* \page listGET_NEXT listGET_NEXT * \page listGET_NEXT listGET_NEXT
* \ingroup LinkedList * \ingroup LinkedList
*/ */
#define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext ) #define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext )
/* /*
* Return the list item that marks the end of the list * Return the list item that marks the end of the list
@ -237,7 +237,7 @@ typedef struct xLIST
* \page listGET_END_MARKER listGET_END_MARKER * \page listGET_END_MARKER listGET_END_MARKER
* \ingroup LinkedList * \ingroup LinkedList
*/ */
#define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) ) #define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )
/* /*
* Access macro to determine if a list contains any items. The macro will * Access macro to determine if a list contains any items. The macro will
@ -246,12 +246,12 @@ typedef struct xLIST
* \page listLIST_IS_EMPTY listLIST_IS_EMPTY * \page listLIST_IS_EMPTY listLIST_IS_EMPTY
* \ingroup LinkedList * \ingroup LinkedList
*/ */
#define listLIST_IS_EMPTY( pxList ) ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE ) #define listLIST_IS_EMPTY( pxList ) ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE )
/* /*
* Access macro to return the number of items in the list. * Access macro to return the number of items in the list.
*/ */
#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems ) #define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems )
/* /*
* Access function to obtain the owner of the next entry in a list. * Access function to obtain the owner of the next entry in a list.
@ -273,9 +273,9 @@ typedef struct xLIST
* \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY
* \ingroup LinkedList * \ingroup LinkedList
*/ */
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ #define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \
{ \ { \
List_t * const pxConstList = ( pxList ); \ List_t * const pxConstList = ( pxList ); \
/* Increment the index to the next item and return the item, ensuring */ \ /* 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. */ \ /* we don't return the marker used at the end of the list. */ \
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
@ -284,7 +284,7 @@ List_t * const pxConstList = ( pxList ); \
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
} \ } \
( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \ ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \
} }
/* /*
@ -303,7 +303,7 @@ List_t * const pxConstList = ( pxList ); \
* \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY
* \ingroup LinkedList * \ingroup LinkedList
*/ */
#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner ) #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 * Check to see if a list item is within a list. The list item maintains a
@ -314,7 +314,7 @@ List_t * const pxConstList = ( pxList ); \
* @param pxListItem The list item we want to know if is in the list. * @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. * @return pdTRUE if the list item is in the list, otherwise pdFALSE.
*/ */
#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( ( pxListItem )->pxContainer == ( pxList ) ) ? ( pdTRUE ) : ( pdFALSE ) ) #define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( ( pxListItem )->pxContainer == ( pxList ) ) ? ( pdTRUE ) : ( pdFALSE ) )
/* /*
* Return the list a list item is contained within (referenced from). * Return the list a list item is contained within (referenced from).
@ -322,14 +322,14 @@ List_t * const pxConstList = ( pxList ); \
* @param pxListItem The list item being queried. * @param pxListItem The list item being queried.
* @return A pointer to the List_t object that references the pxListItem * @return A pointer to the List_t object that references the pxListItem
*/ */
#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pxContainer ) #define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pxContainer )
/* /*
* This provides a crude means of knowing if a list has been initialised, as * 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() * pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise()
* function. * function.
*/ */
#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY ) #define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY )
/* /*
* Must be called before a list is used! This initialises all the members * Must be called before a list is used! This initialises all the members
@ -341,7 +341,7 @@ List_t * const pxConstList = ( pxList ); \
* \page vListInitialise vListInitialise * \page vListInitialise vListInitialise
* \ingroup LinkedList * \ingroup LinkedList
*/ */
void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION; void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION;
/* /*
* Must be called before a list item is used. This sets the list container to * Must be called before a list item is used. This sets the list container to
@ -352,7 +352,7 @@ void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION;
* \page vListInitialiseItem vListInitialiseItem * \page vListInitialiseItem vListInitialiseItem
* \ingroup LinkedList * \ingroup LinkedList
*/ */
void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION; void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION;
/* /*
* Insert a list item into a list. The item will be inserted into the list in * Insert a list item into a list. The item will be inserted into the list in
@ -365,7 +365,8 @@ void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION;
* \page vListInsert vListInsert * \page vListInsert vListInsert
* \ingroup LinkedList * \ingroup LinkedList
*/ */
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION; 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 * Insert a list item into a list. The item will be inserted in a position
@ -386,7 +387,8 @@ void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIV
* \page vListInsertEnd vListInsertEnd * \page vListInsertEnd vListInsertEnd
* \ingroup LinkedList * \ingroup LinkedList
*/ */
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION; 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 * Remove an item from a list. The list item has a pointer to the list that
@ -401,11 +403,10 @@ void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) P
* \page uxListRemove uxListRemove * \page uxListRemove uxListRemove
* \ingroup LinkedList * \ingroup LinkedList
*/ */
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION; UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif
#endif /* ifndef LIST_H */

View file

@ -59,18 +59,18 @@
*/ */
#ifndef FREERTOS_MESSAGE_BUFFER_H #ifndef FREERTOS_MESSAGE_BUFFER_H
#define FREERTOS_MESSAGE_BUFFER_H #define FREERTOS_MESSAGE_BUFFER_H
#ifndef INC_FREERTOS_H #ifndef INC_FREERTOS_H
#error "include FreeRTOS.h must appear in source files before include message_buffer.h" #error "include FreeRTOS.h must appear in source files before include message_buffer.h"
#endif #endif
/* Message buffers are built onto of stream buffers. */ /* Message buffers are built onto of stream buffers. */
#include "stream_buffer.h" #include "stream_buffer.h"
#if defined( __cplusplus ) #if defined( __cplusplus )
extern "C" { extern "C" {
#endif #endif
/** /**
* Type by which message buffers are referenced. For example, a call to * Type by which message buffers are referenced. For example, a call to
@ -78,16 +78,16 @@ extern "C" {
* then be used as a parameter to xMessageBufferSend(), xMessageBufferReceive(), * then be used as a parameter to xMessageBufferSend(), xMessageBufferReceive(),
* etc. * etc.
*/ */
typedef void * MessageBufferHandle_t; typedef void * MessageBufferHandle_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* message_buffer.h * message_buffer.h
* *
<pre> * <pre>
MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes ); * MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes );
</pre> * </pre>
* *
* Creates a new message buffer using dynamically allocated memory. See * Creates a new message buffer using dynamically allocated memory. See
* xMessageBufferCreateStatic() for a version that uses statically allocated * xMessageBufferCreateStatic() for a version that uses statically allocated
@ -111,43 +111,43 @@ MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes );
* buffer. * buffer.
* *
* Example use: * Example use:
<pre> * <pre>
*
void vAFunction( void ) * void vAFunction( void )
{ * {
MessageBufferHandle_t xMessageBuffer; * MessageBufferHandle_t xMessageBuffer;
const size_t xMessageBufferSizeBytes = 100; * const size_t xMessageBufferSizeBytes = 100;
*
// Create a message buffer that can hold 100 bytes. The memory used to hold * // 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 * // both the message buffer structure and the messages themselves is allocated
// dynamically. Each message added to the buffer consumes an additional 4 * // dynamically. Each message added to the buffer consumes an additional 4
// bytes which are used to hold the lengh of the message. * // bytes which are used to hold the lengh of the message.
xMessageBuffer = xMessageBufferCreate( xMessageBufferSizeBytes ); * xMessageBuffer = xMessageBufferCreate( xMessageBufferSizeBytes );
*
if( xMessageBuffer == NULL ) * if( xMessageBuffer == NULL )
{ * {
// There was not enough heap memory space available to create the * // There was not enough heap memory space available to create the
// message buffer. * // message buffer.
} * }
else * else
{ * {
// The message buffer was created successfully and can now be used. * // The message buffer was created successfully and can now be used.
} * }
*
</pre> * </pre>
* \defgroup xMessageBufferCreate xMessageBufferCreate * \defgroup xMessageBufferCreate xMessageBufferCreate
* \ingroup MessageBufferManagement * \ingroup MessageBufferManagement
*/ */
#define xMessageBufferCreate( xBufferSizeBytes ) ( MessageBufferHandle_t ) xStreamBufferGenericCreate( xBufferSizeBytes, ( size_t ) 0, pdTRUE ) #define xMessageBufferCreate( xBufferSizeBytes ) ( MessageBufferHandle_t ) xStreamBufferGenericCreate( xBufferSizeBytes, ( size_t ) 0, pdTRUE )
/** /**
* message_buffer.h * message_buffer.h
* *
<pre> * <pre>
MessageBufferHandle_t xMessageBufferCreateStatic( size_t xBufferSizeBytes, * MessageBufferHandle_t xMessageBufferCreateStatic( size_t xBufferSizeBytes,
uint8_t *pucMessageBufferStorageArea, * uint8_t *pucMessageBufferStorageArea,
StaticMessageBuffer_t *pxStaticMessageBuffer ); * StaticMessageBuffer_t *pxStaticMessageBuffer );
</pre> * </pre>
* Creates a new message buffer using statically allocated memory. See * Creates a new message buffer using statically allocated memory. See
* xMessageBufferCreate() for a version that uses dynamically allocated memory. * xMessageBufferCreate() for a version that uses dynamically allocated memory.
* *
@ -172,49 +172,49 @@ MessageBufferHandle_t xMessageBufferCreateStatic( size_t xBufferSizeBytes,
* pxStaticmessageBuffer are NULL then NULL is returned. * pxStaticmessageBuffer are NULL then NULL is returned.
* *
* Example use: * Example use:
<pre> * <pre>
*
// Used to dimension the array used to hold the messages. The available space * // Used to dimension the array used to hold the messages. The available space
// will actually be one less than this, so 999. * // will actually be one less than this, so 999.
#define STORAGE_SIZE_BYTES 1000 #define STORAGE_SIZE_BYTES 1000
*
// Defines the memory that will actually hold the messages within the message * // Defines the memory that will actually hold the messages within the message
// buffer. * // buffer.
static uint8_t ucStorageBuffer[ STORAGE_SIZE_BYTES ]; * static uint8_t ucStorageBuffer[ STORAGE_SIZE_BYTES ];
*
// The variable used to hold the message buffer structure. * // The variable used to hold the message buffer structure.
StaticMessageBuffer_t xMessageBufferStruct; * StaticMessageBuffer_t xMessageBufferStruct;
*
void MyFunction( void ) * void MyFunction( void )
{ * {
MessageBufferHandle_t xMessageBuffer; * MessageBufferHandle_t xMessageBuffer;
*
xMessageBuffer = xMessageBufferCreateStatic( sizeof( ucBufferStorage ), * xMessageBuffer = xMessageBufferCreateStatic( sizeof( ucBufferStorage ),
ucBufferStorage, * ucBufferStorage,
&xMessageBufferStruct ); * &xMessageBufferStruct );
*
// As neither the pucMessageBufferStorageArea or pxStaticMessageBuffer * // As neither the pucMessageBufferStorageArea or pxStaticMessageBuffer
// parameters were NULL, xMessageBuffer will not be NULL, and can be used to * // parameters were NULL, xMessageBuffer will not be NULL, and can be used to
// reference the created message buffer in other message buffer API calls. * // reference the created message buffer in other message buffer API calls.
*
// Other code that uses the message buffer can go here. * // Other code that uses the message buffer can go here.
} * }
*
</pre> * </pre>
* \defgroup xMessageBufferCreateStatic xMessageBufferCreateStatic * \defgroup xMessageBufferCreateStatic xMessageBufferCreateStatic
* \ingroup MessageBufferManagement * \ingroup MessageBufferManagement
*/ */
#define xMessageBufferCreateStatic( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer ) ( MessageBufferHandle_t ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, 0, pdTRUE, pucMessageBufferStorageArea, pxStaticMessageBuffer ) #define xMessageBufferCreateStatic( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer ) ( MessageBufferHandle_t ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, 0, pdTRUE, pucMessageBufferStorageArea, pxStaticMessageBuffer )
/** /**
* message_buffer.h * message_buffer.h
* *
<pre> * <pre>
size_t xMessageBufferSend( MessageBufferHandle_t xMessageBuffer, * size_t xMessageBufferSend( MessageBufferHandle_t xMessageBuffer,
const void *pvTxData, * const void *pvTxData,
size_t xDataLengthBytes, * size_t xDataLengthBytes,
TickType_t xTicksToWait ); * TickType_t xTicksToWait );
<pre> * <pre>
* *
* Sends a discrete message to the message buffer. The message can be any * 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 * length that fits within the buffer's free space, and is copied into the
@ -271,49 +271,49 @@ size_t xMessageBufferSend( MessageBufferHandle_t xMessageBuffer,
* time out then xDataLengthBytes is returned. * time out then xDataLengthBytes is returned.
* *
* Example use: * Example use:
<pre> * <pre>
void vAFunction( MessageBufferHandle_t xMessageBuffer ) * void vAFunction( MessageBufferHandle_t xMessageBuffer )
{ * {
size_t xBytesSent; * size_t xBytesSent;
uint8_t ucArrayToSend[] = { 0, 1, 2, 3 }; * uint8_t ucArrayToSend[] = { 0, 1, 2, 3 };
char *pcStringToSend = "String to send"; * char *pcStringToSend = "String to send";
const TickType_t x100ms = pdMS_TO_TICKS( 100 ); * const TickType_t x100ms = pdMS_TO_TICKS( 100 );
*
// Send an array to the message buffer, blocking for a maximum of 100ms to * // 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. * // wait for enough space to be available in the message buffer.
xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms ); * xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms );
*
if( xBytesSent != sizeof( ucArrayToSend ) ) * if( xBytesSent != sizeof( ucArrayToSend ) )
{ * {
// The call to xMessageBufferSend() times out before there was enough * // The call to xMessageBufferSend() times out before there was enough
// space in the buffer for the data to be written. * // space in the buffer for the data to be written.
} * }
*
// Send the string to the message buffer. Return immediately if there is * // Send the string to the message buffer. Return immediately if there is
// not enough space in the buffer. * // not enough space in the buffer.
xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 ); * xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 );
*
if( xBytesSent != strlen( pcStringToSend ) ) * if( xBytesSent != strlen( pcStringToSend ) )
{ * {
// The string could not be added to the message buffer because there was * // The string could not be added to the message buffer because there was
// not enough free space in the buffer. * // not enough free space in the buffer.
} * }
} * }
</pre> * </pre>
* \defgroup xMessageBufferSend xMessageBufferSend * \defgroup xMessageBufferSend xMessageBufferSend
* \ingroup MessageBufferManagement * \ingroup MessageBufferManagement
*/ */
#define xMessageBufferSend( xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) xStreamBufferSend( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) #define xMessageBufferSend( xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) xStreamBufferSend( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait )
/** /**
* message_buffer.h * message_buffer.h
* *
<pre> * <pre>
size_t xMessageBufferSendFromISR( MessageBufferHandle_t xMessageBuffer, * size_t xMessageBufferSendFromISR( MessageBufferHandle_t xMessageBuffer,
const void *pvTxData, * const void *pvTxData,
size_t xDataLengthBytes, * size_t xDataLengthBytes,
BaseType_t *pxHigherPriorityTaskWoken ); * BaseType_t *pxHigherPriorityTaskWoken );
<pre> * <pre>
* *
* Interrupt safe version of the API function that sends a discrete message to * 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 * the message buffer. The message can be any length that fits within the
@ -371,53 +371,53 @@ size_t xMessageBufferSendFromISR( MessageBufferHandle_t xMessageBuffer,
* then 0 is returned, otherwise xDataLengthBytes is returned. * then 0 is returned, otherwise xDataLengthBytes is returned.
* *
* Example use: * Example use:
<pre> * <pre>
// A message buffer that has already been created. * // A message buffer that has already been created.
MessageBufferHandle_t xMessageBuffer; * MessageBufferHandle_t xMessageBuffer;
*
void vAnInterruptServiceRoutine( void ) * void vAnInterruptServiceRoutine( void )
{ * {
size_t xBytesSent; * size_t xBytesSent;
char *pcStringToSend = "String to send"; * char *pcStringToSend = "String to send";
BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE. * BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
*
// Attempt to send the string to the message buffer. * // Attempt to send the string to the message buffer.
xBytesSent = xMessageBufferSendFromISR( xMessageBuffer, * xBytesSent = xMessageBufferSendFromISR( xMessageBuffer,
( void * ) pcStringToSend, * ( void * ) pcStringToSend,
strlen( pcStringToSend ), * strlen( pcStringToSend ),
&xHigherPriorityTaskWoken ); * &xHigherPriorityTaskWoken );
*
if( xBytesSent != strlen( pcStringToSend ) ) * if( xBytesSent != strlen( pcStringToSend ) )
{ * {
// The string could not be added to the message buffer because there was * // The string could not be added to the message buffer because there was
// not enough free space in the buffer. * // not enough free space in the buffer.
} * }
*
// If xHigherPriorityTaskWoken was set to pdTRUE inside * // If xHigherPriorityTaskWoken was set to pdTRUE inside
// xMessageBufferSendFromISR() then a task that has a priority above the * // xMessageBufferSendFromISR() then a task that has a priority above the
// priority of the currently executing task was unblocked and a context * // priority of the currently executing task was unblocked and a context
// switch should be performed to ensure the ISR returns to the unblocked * // switch should be performed to ensure the ISR returns to the unblocked
// task. In most FreeRTOS ports this is done by simply passing * // task. In most FreeRTOS ports this is done by simply passing
// xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the * // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the
// variables value, and perform the context switch if necessary. Check the * // variables value, and perform the context switch if necessary. Check the
// documentation for the port in use for port specific instructions. * // documentation for the port in use for port specific instructions.
portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); * portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
} * }
</pre> * </pre>
* \defgroup xMessageBufferSendFromISR xMessageBufferSendFromISR * \defgroup xMessageBufferSendFromISR xMessageBufferSendFromISR
* \ingroup MessageBufferManagement * \ingroup MessageBufferManagement
*/ */
#define xMessageBufferSendFromISR( xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) xStreamBufferSendFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) #define xMessageBufferSendFromISR( xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) xStreamBufferSendFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken )
/** /**
* message_buffer.h * message_buffer.h
* *
<pre> * <pre>
size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer, * size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer,
void *pvRxData, * void *pvRxData,
size_t xBufferLengthBytes, * size_t xBufferLengthBytes,
TickType_t xTicksToWait ); * TickType_t xTicksToWait );
</pre> * </pre>
* *
* Receives a discrete message from a message buffer. Messages can be of * Receives a discrete message from a message buffer. Messages can be of
* variable length and are copied out of the buffer. * variable length and are copied out of the buffer.
@ -470,43 +470,43 @@ size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer,
* zero is returned. * zero is returned.
* *
* Example use: * Example use:
<pre> * <pre>
void vAFunction( MessageBuffer_t xMessageBuffer ) * void vAFunction( MessageBuffer_t xMessageBuffer )
{ * {
uint8_t ucRxData[ 20 ]; * uint8_t ucRxData[ 20 ];
size_t xReceivedBytes; * size_t xReceivedBytes;
const TickType_t xBlockTime = pdMS_TO_TICKS( 20 ); * const TickType_t xBlockTime = pdMS_TO_TICKS( 20 );
*
// Receive the next message from the message buffer. Wait in the Blocked * // 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 * // state (so not using any CPU processing time) for a maximum of 100ms for
// a message to become available. * // a message to become available.
xReceivedBytes = xMessageBufferReceive( xMessageBuffer, * xReceivedBytes = xMessageBufferReceive( xMessageBuffer,
( void * ) ucRxData, * ( void * ) ucRxData,
sizeof( ucRxData ), * sizeof( ucRxData ),
xBlockTime ); * xBlockTime );
*
if( xReceivedBytes > 0 ) * if( xReceivedBytes > 0 )
{ * {
// A ucRxData contains a message that is xReceivedBytes long. Process * // A ucRxData contains a message that is xReceivedBytes long. Process
// the message here.... * // the message here....
} * }
} * }
</pre> * </pre>
* \defgroup xMessageBufferReceive xMessageBufferReceive * \defgroup xMessageBufferReceive xMessageBufferReceive
* \ingroup MessageBufferManagement * \ingroup MessageBufferManagement
*/ */
#define xMessageBufferReceive( xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) xStreamBufferReceive( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) #define xMessageBufferReceive( xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) xStreamBufferReceive( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait )
/** /**
* message_buffer.h * message_buffer.h
* *
<pre> * <pre>
size_t xMessageBufferReceiveFromISR( MessageBufferHandle_t xMessageBuffer, * size_t xMessageBufferReceiveFromISR( MessageBufferHandle_t xMessageBuffer,
void *pvRxData, * void *pvRxData,
size_t xBufferLengthBytes, * size_t xBufferLengthBytes,
BaseType_t *pxHigherPriorityTaskWoken ); * BaseType_t *pxHigherPriorityTaskWoken );
</pre> * </pre>
* *
* An interrupt safe version of the API function that receives a discrete * 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 * message from a message buffer. Messages can be of variable length and are
@ -560,50 +560,50 @@ size_t xMessageBufferReceiveFromISR( MessageBufferHandle_t xMessageBuffer,
* any. * any.
* *
* Example use: * Example use:
<pre> * <pre>
// A message buffer that has already been created. * // A message buffer that has already been created.
MessageBuffer_t xMessageBuffer; * MessageBuffer_t xMessageBuffer;
*
void vAnInterruptServiceRoutine( void ) * void vAnInterruptServiceRoutine( void )
{ * {
uint8_t ucRxData[ 20 ]; * uint8_t ucRxData[ 20 ];
size_t xReceivedBytes; * size_t xReceivedBytes;
BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE. * BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
*
// Receive the next message from the message buffer. * // Receive the next message from the message buffer.
xReceivedBytes = xMessageBufferReceiveFromISR( xMessageBuffer, * xReceivedBytes = xMessageBufferReceiveFromISR( xMessageBuffer,
( void * ) ucRxData, * ( void * ) ucRxData,
sizeof( ucRxData ), * sizeof( ucRxData ),
&xHigherPriorityTaskWoken ); * &xHigherPriorityTaskWoken );
*
if( xReceivedBytes > 0 ) * if( xReceivedBytes > 0 )
{ * {
// A ucRxData contains a message that is xReceivedBytes long. Process * // A ucRxData contains a message that is xReceivedBytes long. Process
// the message here.... * // the message here....
} * }
*
// If xHigherPriorityTaskWoken was set to pdTRUE inside * // If xHigherPriorityTaskWoken was set to pdTRUE inside
// xMessageBufferReceiveFromISR() then a task that has a priority above the * // xMessageBufferReceiveFromISR() then a task that has a priority above the
// priority of the currently executing task was unblocked and a context * // priority of the currently executing task was unblocked and a context
// switch should be performed to ensure the ISR returns to the unblocked * // switch should be performed to ensure the ISR returns to the unblocked
// task. In most FreeRTOS ports this is done by simply passing * // task. In most FreeRTOS ports this is done by simply passing
// xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the * // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the
// variables value, and perform the context switch if necessary. Check the * // variables value, and perform the context switch if necessary. Check the
// documentation for the port in use for port specific instructions. * // documentation for the port in use for port specific instructions.
portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); * portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
} * }
</pre> * </pre>
* \defgroup xMessageBufferReceiveFromISR xMessageBufferReceiveFromISR * \defgroup xMessageBufferReceiveFromISR xMessageBufferReceiveFromISR
* \ingroup MessageBufferManagement * \ingroup MessageBufferManagement
*/ */
#define xMessageBufferReceiveFromISR( xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) xStreamBufferReceiveFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) #define xMessageBufferReceiveFromISR( xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) xStreamBufferReceiveFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken )
/** /**
* message_buffer.h * message_buffer.h
* *
<pre> * <pre>
void vMessageBufferDelete( MessageBufferHandle_t xMessageBuffer ); * void vMessageBufferDelete( MessageBufferHandle_t xMessageBuffer );
</pre> * </pre>
* *
* Deletes a message buffer that was previously created using a call to * Deletes a message buffer that was previously created using a call to
* xMessageBufferCreate() or xMessageBufferCreateStatic(). If the message * xMessageBufferCreate() or xMessageBufferCreateStatic(). If the message
@ -616,13 +616,13 @@ void vMessageBufferDelete( MessageBufferHandle_t xMessageBuffer );
* @param xMessageBuffer The handle of the message buffer to be deleted. * @param xMessageBuffer The handle of the message buffer to be deleted.
* *
*/ */
#define vMessageBufferDelete( xMessageBuffer ) vStreamBufferDelete( ( StreamBufferHandle_t ) xMessageBuffer ) #define vMessageBufferDelete( xMessageBuffer ) vStreamBufferDelete( ( StreamBufferHandle_t ) xMessageBuffer )
/** /**
* message_buffer.h * message_buffer.h
<pre> * <pre>
BaseType_t xMessageBufferIsFull( MessageBufferHandle_t xMessageBuffer ) ); * BaseType_t xMessageBufferIsFull( MessageBufferHandle_t xMessageBuffer ) );
</pre> * </pre>
* *
* Tests to see if a message buffer is full. A message buffer is full if it * 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 * cannot accept any more messages, of any size, until space is made available
@ -633,13 +633,13 @@ BaseType_t xMessageBufferIsFull( MessageBufferHandle_t xMessageBuffer ) );
* @return If the message buffer referenced by xMessageBuffer is full then * @return If the message buffer referenced by xMessageBuffer is full then
* pdTRUE is returned. Otherwise pdFALSE is returned. * pdTRUE is returned. Otherwise pdFALSE is returned.
*/ */
#define xMessageBufferIsFull( xMessageBuffer ) xStreamBufferIsFull( ( StreamBufferHandle_t ) xMessageBuffer ) #define xMessageBufferIsFull( xMessageBuffer ) xStreamBufferIsFull( ( StreamBufferHandle_t ) xMessageBuffer )
/** /**
* message_buffer.h * message_buffer.h
<pre> * <pre>
BaseType_t xMessageBufferIsEmpty( MessageBufferHandle_t xMessageBuffer ) ); * BaseType_t xMessageBufferIsEmpty( MessageBufferHandle_t xMessageBuffer ) );
</pre> * </pre>
* *
* Tests to see if a message buffer is empty (does not contain any messages). * Tests to see if a message buffer is empty (does not contain any messages).
* *
@ -649,13 +649,13 @@ BaseType_t xMessageBufferIsEmpty( MessageBufferHandle_t xMessageBuffer ) );
* pdTRUE is returned. Otherwise pdFALSE is returned. * pdTRUE is returned. Otherwise pdFALSE is returned.
* *
*/ */
#define xMessageBufferIsEmpty( xMessageBuffer ) xStreamBufferIsEmpty( ( StreamBufferHandle_t ) xMessageBuffer ) #define xMessageBufferIsEmpty( xMessageBuffer ) xStreamBufferIsEmpty( ( StreamBufferHandle_t ) xMessageBuffer )
/** /**
* message_buffer.h * message_buffer.h
<pre> * <pre>
BaseType_t xMessageBufferReset( MessageBufferHandle_t xMessageBuffer ); * BaseType_t xMessageBufferReset( MessageBufferHandle_t xMessageBuffer );
</pre> * </pre>
* *
* Resets a message buffer to its initial empty state, discarding any message it * Resets a message buffer to its initial empty state, discarding any message it
* contained. * contained.
@ -672,14 +672,14 @@ BaseType_t xMessageBufferReset( MessageBufferHandle_t xMessageBuffer );
* \defgroup xMessageBufferReset xMessageBufferReset * \defgroup xMessageBufferReset xMessageBufferReset
* \ingroup MessageBufferManagement * \ingroup MessageBufferManagement
*/ */
#define xMessageBufferReset( xMessageBuffer ) xStreamBufferReset( ( StreamBufferHandle_t ) xMessageBuffer ) #define xMessageBufferReset( xMessageBuffer ) xStreamBufferReset( ( StreamBufferHandle_t ) xMessageBuffer )
/** /**
* message_buffer.h * message_buffer.h
<pre> * <pre>
size_t xMessageBufferSpaceAvailable( MessageBufferHandle_t xMessageBuffer ) ); * size_t xMessageBufferSpaceAvailable( MessageBufferHandle_t xMessageBuffer ) );
</pre> * </pre>
* Returns the number of bytes of free space in the message buffer. * Returns the number of bytes of free space in the message buffer.
* *
* @param xMessageBuffer The handle of the message buffer being queried. * @param xMessageBuffer The handle of the message buffer being queried.
@ -694,14 +694,14 @@ size_t xMessageBufferSpaceAvailable( MessageBufferHandle_t xMessageBuffer ) );
* \defgroup xMessageBufferSpaceAvailable xMessageBufferSpaceAvailable * \defgroup xMessageBufferSpaceAvailable xMessageBufferSpaceAvailable
* \ingroup MessageBufferManagement * \ingroup MessageBufferManagement
*/ */
#define xMessageBufferSpaceAvailable( xMessageBuffer ) xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer ) #define xMessageBufferSpaceAvailable( xMessageBuffer ) xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer )
#define xMessageBufferSpacesAvailable( xMessageBuffer ) xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer ) /* Corrects typo in original macro name. */ #define xMessageBufferSpacesAvailable( xMessageBuffer ) xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer ) /* Corrects typo in original macro name. */
/** /**
* message_buffer.h * message_buffer.h
<pre> * <pre>
size_t xMessageBufferNextLengthBytes( MessageBufferHandle_t xMessageBuffer ) ); * size_t xMessageBufferNextLengthBytes( MessageBufferHandle_t xMessageBuffer ) );
</pre> * </pre>
* Returns the length (in bytes) of the next message in a message buffer. * Returns the length (in bytes) of the next message in a message buffer.
* Useful if xMessageBufferReceive() returned 0 because the size of the buffer * Useful if xMessageBufferReceive() returned 0 because the size of the buffer
* passed into xMessageBufferReceive() was too small to hold the next message. * passed into xMessageBufferReceive() was too small to hold the next message.
@ -714,14 +714,14 @@ size_t xMessageBufferSpaceAvailable( MessageBufferHandle_t xMessageBuffer ) );
* \defgroup xMessageBufferNextLengthBytes xMessageBufferNextLengthBytes * \defgroup xMessageBufferNextLengthBytes xMessageBufferNextLengthBytes
* \ingroup MessageBufferManagement * \ingroup MessageBufferManagement
*/ */
#define xMessageBufferNextLengthBytes( xMessageBuffer ) xStreamBufferNextMessageLengthBytes( ( StreamBufferHandle_t ) xMessageBuffer ) PRIVILEGED_FUNCTION; #define xMessageBufferNextLengthBytes( xMessageBuffer ) xStreamBufferNextMessageLengthBytes( ( StreamBufferHandle_t ) xMessageBuffer ) PRIVILEGED_FUNCTION;
/** /**
* message_buffer.h * message_buffer.h
* *
<pre> * <pre>
BaseType_t xMessageBufferSendCompletedFromISR( MessageBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ); * BaseType_t xMessageBufferSendCompletedFromISR( MessageBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
</pre> * </pre>
* *
* For advanced users only. * For advanced users only.
* *
@ -753,14 +753,14 @@ BaseType_t xMessageBufferSendCompletedFromISR( MessageBufferHandle_t xStreamBuff
* \defgroup xMessageBufferSendCompletedFromISR xMessageBufferSendCompletedFromISR * \defgroup xMessageBufferSendCompletedFromISR xMessageBufferSendCompletedFromISR
* \ingroup StreamBufferManagement * \ingroup StreamBufferManagement
*/ */
#define xMessageBufferSendCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) xStreamBufferSendCompletedFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pxHigherPriorityTaskWoken ) #define xMessageBufferSendCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) xStreamBufferSendCompletedFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pxHigherPriorityTaskWoken )
/** /**
* message_buffer.h * message_buffer.h
* *
<pre> * <pre>
BaseType_t xMessageBufferReceiveCompletedFromISR( MessageBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ); * BaseType_t xMessageBufferReceiveCompletedFromISR( MessageBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
</pre> * </pre>
* *
* For advanced users only. * For advanced users only.
* *
@ -793,10 +793,10 @@ BaseType_t xMessageBufferReceiveCompletedFromISR( MessageBufferHandle_t xStreamB
* \defgroup xMessageBufferReceiveCompletedFromISR xMessageBufferReceiveCompletedFromISR * \defgroup xMessageBufferReceiveCompletedFromISR xMessageBufferReceiveCompletedFromISR
* \ingroup StreamBufferManagement * \ingroup StreamBufferManagement
*/ */
#define xMessageBufferReceiveCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) xStreamBufferReceiveCompletedFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pxHigherPriorityTaskWoken ) #define xMessageBufferReceiveCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) xStreamBufferReceiveCompletedFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pxHigherPriorityTaskWoken )
#if defined( __cplusplus ) #if defined( __cplusplus )
} /* extern "C" */ } /* extern "C" */
#endif #endif
#endif /* !defined( FREERTOS_MESSAGE_BUFFER_H ) */ #endif /* !defined( FREERTOS_MESSAGE_BUFFER_H ) */

View file

@ -37,19 +37,38 @@
#define MPU_PROTOTYPES_H #define MPU_PROTOTYPES_H
/* MPU versions of tasks.h API functions. */ /* MPU versions of tasks.h API functions. */
BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode,
TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer ) FREERTOS_SYSTEM_CALL; const char * const pcName,
BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) FREERTOS_SYSTEM_CALL; const uint16_t usStackDepth,
BaseType_t MPU_xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) FREERTOS_SYSTEM_CALL; void * const pvParameters,
void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions ) FREERTOS_SYSTEM_CALL; UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask ) FREERTOS_SYSTEM_CALL;
TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint32_t ulStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
StackType_t * const puxStackBuffer,
StaticTask_t * const pxTaskBuffer ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition,
TaskHandle_t * pxCreatedTask ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition,
TaskHandle_t * pxCreatedTask ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask,
const MemoryRegion_t * const pxRegions ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskDelete( TaskHandle_t xTaskToDelete ) FREERTOS_SYSTEM_CALL; void MPU_vTaskDelete( TaskHandle_t xTaskToDelete ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskDelay( const TickType_t xTicksToDelay ) FREERTOS_SYSTEM_CALL; void MPU_vTaskDelay( const TickType_t xTicksToDelay ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) FREERTOS_SYSTEM_CALL; void MPU_vTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
const TickType_t xTimeIncrement ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
UBaseType_t MPU_uxTaskPriorityGet( const 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; 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_vTaskGetInfo( TaskHandle_t xTask,
void MPU_vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) FREERTOS_SYSTEM_CALL; TaskStatus_t * pxTaskStatus,
BaseType_t xGetFreeStackSpace,
eTaskState eState ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskPrioritySet( TaskHandle_t xTask,
UBaseType_t uxNewPriority ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend ) FREERTOS_SYSTEM_CALL; void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskResume( TaskHandle_t xTaskToResume ) FREERTOS_SYSTEM_CALL; void MPU_vTaskResume( TaskHandle_t xTaskToResume ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskStartScheduler( void ) FREERTOS_SYSTEM_CALL; void MPU_vTaskStartScheduler( void ) FREERTOS_SYSTEM_CALL;
@ -58,90 +77,169 @@ BaseType_t MPU_xTaskResumeAll( void ) FREERTOS_SYSTEM_CALL;
TickType_t MPU_xTaskGetTickCount( void ) FREERTOS_SYSTEM_CALL; TickType_t MPU_xTaskGetTickCount( void ) FREERTOS_SYSTEM_CALL;
UBaseType_t MPU_uxTaskGetNumberOfTasks( void ) FREERTOS_SYSTEM_CALL; UBaseType_t MPU_uxTaskGetNumberOfTasks( void ) FREERTOS_SYSTEM_CALL;
char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ) FREERTOS_SYSTEM_CALL; char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ) FREERTOS_SYSTEM_CALL;
TaskHandle_t MPU_xTaskGetHandle( const char *pcNameToQuery ) FREERTOS_SYSTEM_CALL; TaskHandle_t MPU_xTaskGetHandle( const char * pcNameToQuery ) FREERTOS_SYSTEM_CALL;
UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
configSTACK_DEPTH_TYPE MPU_uxTaskGetStackHighWaterMark2( 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; void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask,
TaskHookFunction_t pxHookFunction ) FREERTOS_SYSTEM_CALL;
TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask ) 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_vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet,
void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ) FREERTOS_SYSTEM_CALL; BaseType_t xIndex,
BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) FREERTOS_SYSTEM_CALL; void * pvValue ) FREERTOS_SYSTEM_CALL;
void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery,
BaseType_t xIndex ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask,
void * pvParameter ) FREERTOS_SYSTEM_CALL;
TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ) FREERTOS_SYSTEM_CALL; TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ) FREERTOS_SYSTEM_CALL;
UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ) FREERTOS_SYSTEM_CALL; UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
const UBaseType_t uxArraySize,
uint32_t * const pulTotalRunTime ) FREERTOS_SYSTEM_CALL;
uint32_t MPU_ulTaskGetIdleRunTimeCounter( void ) FREERTOS_SYSTEM_CALL; uint32_t MPU_ulTaskGetIdleRunTimeCounter( void ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskList( char * pcWriteBuffer ) FREERTOS_SYSTEM_CALL; void MPU_vTaskList( char * pcWriteBuffer ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskGetRunTimeStats( char *pcWriteBuffer ) FREERTOS_SYSTEM_CALL; void MPU_vTaskGetRunTimeStats( char * pcWriteBuffer ) 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_xTaskGenericNotify( TaskHandle_t xTaskToNotify,
BaseType_t MPU_xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; UBaseType_t uxIndexToNotify,
uint32_t MPU_ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; uint32_t ulValue,
BaseType_t MPU_xTaskGenericNotifyStateClear( TaskHandle_t xTask, UBaseType_t uxIndexToClear ) FREERTOS_SYSTEM_CALL; eNotifyAction eAction,
uint32_t MPU_ulTaskGenericNotifyValueClear( TaskHandle_t xTask, UBaseType_t uxIndexToClear, uint32_t ulBitsToClear ) FREERTOS_SYSTEM_CALL; uint32_t * pulPreviousNotificationValue ) 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;
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;
BaseType_t MPU_xTaskIncrementTick( void ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xTaskIncrementTick( void ) FREERTOS_SYSTEM_CALL;
TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) FREERTOS_SYSTEM_CALL; TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) 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; BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
TickType_t * const pxTicksToWait ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskMissedYield( void ) FREERTOS_SYSTEM_CALL; void MPU_vTaskMissedYield( void ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskGetSchedulerState( void ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xTaskGetSchedulerState( void ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) FREERTOS_SYSTEM_CALL;
/* MPU versions of queue.h API functions. */ /* 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_xQueueGenericSend( QueueHandle_t xQueue,
BaseType_t MPU_xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; const void * const pvItemToQueue,
BaseType_t MPU_xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; TickType_t xTicksToWait,
BaseType_t MPU_xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; 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_uxQueueMessagesWaiting( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
void MPU_vQueueDelete( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; void MPU_vQueueDelete( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL; QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL;
QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ) FREERTOS_SYSTEM_CALL; QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType,
QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) FREERTOS_SYSTEM_CALL; StaticQueue_t * pxStaticQueue ) FREERTOS_SYSTEM_CALL;
QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ) FREERTOS_SYSTEM_CALL; QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,
const UBaseType_t uxInitialCount ) FREERTOS_SYSTEM_CALL;
QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount,
const UBaseType_t uxInitialCount,
StaticQueue_t * pxStaticQueue ) FREERTOS_SYSTEM_CALL;
TaskHandle_t MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ) FREERTOS_SYSTEM_CALL; 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_xQueueTakeMutexRecursive( QueueHandle_t xMutex,
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) 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_vQueueAddToRegistry( QueueHandle_t xQueue,
const char * pcName ) FREERTOS_SYSTEM_CALL;
void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
const char * MPU_pcQueueGetName( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; const char * MPU_pcQueueGetName( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL; QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength,
QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL; const UBaseType_t uxItemSize,
const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL;
QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength,
const UBaseType_t uxItemSize,
uint8_t * pucQueueStorage,
StaticQueue_t * pxStaticQueue,
const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL;
QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength ) FREERTOS_SYSTEM_CALL; QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL; QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL;
QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore,
BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) FREERTOS_SYSTEM_CALL; QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL;
void MPU_vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) FREERTOS_SYSTEM_CALL; QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet,
const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue,
BaseType_t xNewQueue ) FREERTOS_SYSTEM_CALL;
void MPU_vQueueSetQueueNumber( QueueHandle_t xQueue,
UBaseType_t uxQueueNumber ) FREERTOS_SYSTEM_CALL;
UBaseType_t MPU_uxQueueGetQueueNumber( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; UBaseType_t MPU_uxQueueGetQueueNumber( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
uint8_t MPU_ucQueueGetQueueType( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; uint8_t MPU_ucQueueGetQueueType( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
/* MPU versions of timers.h API functions. */ /* MPU versions of timers.h API functions. */
TimerHandle_t MPU_xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) FREERTOS_SYSTEM_CALL; TimerHandle_t MPU_xTimerCreate( const char * const pcTimerName,
TimerHandle_t MPU_xTimerCreateStatic( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, StaticTimer_t *pxTimerBuffer ) FREERTOS_SYSTEM_CALL; const TickType_t xTimerPeriodInTicks,
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction ) FREERTOS_SYSTEM_CALL;
TimerHandle_t MPU_xTimerCreateStatic( const char * const pcTimerName,
const TickType_t xTimerPeriodInTicks,
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction,
StaticTimer_t * pxTimerBuffer ) FREERTOS_SYSTEM_CALL;
void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
void MPU_vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ) FREERTOS_SYSTEM_CALL; void MPU_vTimerSetTimerID( TimerHandle_t xTimer,
void * pvNewID ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void ) FREERTOS_SYSTEM_CALL; TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xTimerPendFunctionCall( PendedFunction_t xFunctionToPend,
void * pvParameter1,
uint32_t ulParameter2,
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
const char * MPU_pcTimerGetName( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; const char * MPU_pcTimerGetName( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
void MPU_vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload ) FREERTOS_SYSTEM_CALL; void MPU_vTimerSetReloadMode( TimerHandle_t xTimer,
const UBaseType_t uxAutoReload ) FREERTOS_SYSTEM_CALL;
UBaseType_t MPU_uxTimerGetReloadMode( 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_xTimerGetPeriod( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTimerCreateTimerTask( void ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xTimerCreateTimerTask( void ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xTimerGenericCommand( TimerHandle_t xTimer,
const BaseType_t xCommandID,
const TickType_t xOptionalValue,
BaseType_t * const pxHigherPriorityTaskWoken,
const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
/* MPU versions of event_group.h API functions. */ /* MPU versions of event_group.h API functions. */
EventGroupHandle_t MPU_xEventGroupCreate( void ) FREERTOS_SYSTEM_CALL; EventGroupHandle_t MPU_xEventGroupCreate( void ) FREERTOS_SYSTEM_CALL;
EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ) FREERTOS_SYSTEM_CALL; EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) FREERTOS_SYSTEM_CALL;
EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
EventBits_t MPU_xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) FREERTOS_SYSTEM_CALL; const EventBits_t uxBitsToWaitFor,
EventBits_t MPU_xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) FREERTOS_SYSTEM_CALL; const BaseType_t xClearOnExit,
EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; const BaseType_t xWaitForAllBits,
TickType_t xTicksToWait ) 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;
void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup ) FREERTOS_SYSTEM_CALL; void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup ) FREERTOS_SYSTEM_CALL;
UBaseType_t MPU_uxEventGroupGetNumber( void* xEventGroup ) FREERTOS_SYSTEM_CALL; UBaseType_t MPU_uxEventGroupGetNumber( void * xEventGroup ) FREERTOS_SYSTEM_CALL;
/* MPU versions of message/stream_buffer.h API functions. */ /* 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_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
size_t MPU_xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, void *pvRxData, size_t xBufferLengthBytes, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; 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;
size_t MPU_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; size_t MPU_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
void MPU_vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; void MPU_vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
@ -149,11 +247,17 @@ BaseType_t MPU_xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) FREERT
BaseType_t MPU_xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
size_t MPU_xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; size_t MPU_xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
size_t MPU_xStreamBufferBytesAvailable( 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; BaseType_t MPU_xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer,
StreamBufferHandle_t MPU_xStreamBufferGenericCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes, BaseType_t xIsMessageBuffer ) FREERTOS_SYSTEM_CALL; size_t xTriggerLevel ) FREERTOS_SYSTEM_CALL;
StreamBufferHandle_t MPU_xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes, size_t xTriggerLevelBytes, BaseType_t xIsMessageBuffer, uint8_t * const pucStreamBufferStorageArea, StaticStreamBuffer_t * const pxStaticStreamBuffer ) FREERTOS_SYSTEM_CALL; StreamBufferHandle_t MPU_xStreamBufferGenericCreate( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer ) FREERTOS_SYSTEM_CALL;
StreamBufferHandle_t MPU_xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer,
uint8_t * const pucStreamBufferStorageArea,
StaticStreamBuffer_t * const pxStaticStreamBuffer ) FREERTOS_SYSTEM_CALL;
#endif /* MPU_PROTOTYPES_H */ #endif /* MPU_PROTOTYPES_H */

View file

@ -28,15 +28,15 @@
#define MPU_WRAPPERS_H #define MPU_WRAPPERS_H
/* This file redefines API functions to be called through a wrapper macro, but /* This file redefines API functions to be called through a wrapper macro, but
only for ports that are using the MPU. */ * only for ports that are using the MPU. */
#ifdef portUSING_MPU_WRAPPERS #ifdef portUSING_MPU_WRAPPERS
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is /* 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 * included from queue.c or task.c to prevent it from having an effect within
those files. */ * those files. */
#ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE #ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* /*
* Map standard (non MPU) API functions to equivalents that start * Map standard (non MPU) API functions to equivalents that start
* "MPU_". This will cause the application code to call the MPU_ * "MPU_". This will cause the application code to call the MPU_
* version, which wraps the non-MPU version with privilege promoting * version, which wraps the non-MPU version with privilege promoting
@ -44,7 +44,7 @@ only for ports that are using the MPU. */
* privileges. * privileges.
*/ */
/* Map standard tasks.h API functions to the MPU equivalents. */ /* Map standard tasks.h API functions to the MPU equivalents. */
#define xTaskCreate MPU_xTaskCreate #define xTaskCreate MPU_xTaskCreate
#define xTaskCreateStatic MPU_xTaskCreateStatic #define xTaskCreateStatic MPU_xTaskCreateStatic
#define xTaskCreateRestricted MPU_xTaskCreateRestricted #define xTaskCreateRestricted MPU_xTaskCreateRestricted
@ -89,7 +89,7 @@ only for ports that are using the MPU. */
#define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut #define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut
#define xTaskGetSchedulerState MPU_xTaskGetSchedulerState #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState
/* Map standard queue.h API functions to the MPU equivalents. */ /* Map standard queue.h API functions to the MPU equivalents. */
#define xQueueGenericSend MPU_xQueueGenericSend #define xQueueGenericSend MPU_xQueueGenericSend
#define xQueueReceive MPU_xQueueReceive #define xQueueReceive MPU_xQueueReceive
#define xQueuePeek MPU_xQueuePeek #define xQueuePeek MPU_xQueuePeek
@ -112,13 +112,13 @@ only for ports that are using the MPU. */
#define xQueueSelectFromSet MPU_xQueueSelectFromSet #define xQueueSelectFromSet MPU_xQueueSelectFromSet
#define xQueueGenericReset MPU_xQueueGenericReset #define xQueueGenericReset MPU_xQueueGenericReset
#if( configQUEUE_REGISTRY_SIZE > 0 ) #if ( configQUEUE_REGISTRY_SIZE > 0 )
#define vQueueAddToRegistry MPU_vQueueAddToRegistry #define vQueueAddToRegistry MPU_vQueueAddToRegistry
#define vQueueUnregisterQueue MPU_vQueueUnregisterQueue #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue
#define pcQueueGetName MPU_pcQueueGetName #define pcQueueGetName MPU_pcQueueGetName
#endif #endif
/* Map standard timer.h API functions to the MPU equivalents. */ /* Map standard timer.h API functions to the MPU equivalents. */
#define xTimerCreate MPU_xTimerCreate #define xTimerCreate MPU_xTimerCreate
#define xTimerCreateStatic MPU_xTimerCreateStatic #define xTimerCreateStatic MPU_xTimerCreateStatic
#define pvTimerGetTimerID MPU_pvTimerGetTimerID #define pvTimerGetTimerID MPU_pvTimerGetTimerID
@ -133,7 +133,7 @@ only for ports that are using the MPU. */
#define xTimerGetExpiryTime MPU_xTimerGetExpiryTime #define xTimerGetExpiryTime MPU_xTimerGetExpiryTime
#define xTimerGenericCommand MPU_xTimerGenericCommand #define xTimerGenericCommand MPU_xTimerGenericCommand
/* Map standard event_group.h API functions to the MPU equivalents. */ /* Map standard event_group.h API functions to the MPU equivalents. */
#define xEventGroupCreate MPU_xEventGroupCreate #define xEventGroupCreate MPU_xEventGroupCreate
#define xEventGroupCreateStatic MPU_xEventGroupCreateStatic #define xEventGroupCreateStatic MPU_xEventGroupCreateStatic
#define xEventGroupWaitBits MPU_xEventGroupWaitBits #define xEventGroupWaitBits MPU_xEventGroupWaitBits
@ -142,8 +142,8 @@ only for ports that are using the MPU. */
#define xEventGroupSync MPU_xEventGroupSync #define xEventGroupSync MPU_xEventGroupSync
#define vEventGroupDelete MPU_vEventGroupDelete #define vEventGroupDelete MPU_vEventGroupDelete
/* Map standard message/stream_buffer.h API functions to the MPU /* Map standard message/stream_buffer.h API functions to the MPU
equivalents. */ * equivalents. */
#define xStreamBufferSend MPU_xStreamBufferSend #define xStreamBufferSend MPU_xStreamBufferSend
#define xStreamBufferReceive MPU_xStreamBufferReceive #define xStreamBufferReceive MPU_xStreamBufferReceive
#define xStreamBufferNextMessageLengthBytes MPU_xStreamBufferNextMessageLengthBytes #define xStreamBufferNextMessageLengthBytes MPU_xStreamBufferNextMessageLengthBytes
@ -158,19 +158,19 @@ only for ports that are using the MPU. */
#define xStreamBufferGenericCreateStatic MPU_xStreamBufferGenericCreateStatic #define xStreamBufferGenericCreateStatic MPU_xStreamBufferGenericCreateStatic
/* Remove the privileged function macro, but keep the PRIVILEGED_DATA /* Remove the privileged function macro, but keep the PRIVILEGED_DATA
macro so applications can place data in privileged access sections * macro so applications can place data in privileged access sections
(useful when using statically allocated objects). */ * (useful when using statically allocated objects). */
#define PRIVILEGED_FUNCTION #define PRIVILEGED_FUNCTION
#define PRIVILEGED_DATA __attribute__((section("privileged_data"))) #define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) )
#define FREERTOS_SYSTEM_CALL #define FREERTOS_SYSTEM_CALL
#else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ #else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
/* Ensure API functions go in the privileged execution section. */ /* Ensure API functions go in the privileged execution section. */
#define PRIVILEGED_FUNCTION __attribute__((section("privileged_functions"))) #define PRIVILEGED_FUNCTION __attribute__( ( section( "privileged_functions" ) ) )
#define PRIVILEGED_DATA __attribute__((section("privileged_data"))) #define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) )
#define FREERTOS_SYSTEM_CALL __attribute__((section( "freertos_system_calls"))) #define FREERTOS_SYSTEM_CALL __attribute__( ( section( "freertos_system_calls" ) ) )
#endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ #endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
@ -185,4 +185,3 @@ only for ports that are using the MPU. */
#endif /* MPU_WRAPPERS_H */ #endif /* MPU_WRAPPERS_H */

View file

@ -25,77 +25,77 @@
*/ */
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Portable layer API. Each function must be defined for each port. * Portable layer API. Each function must be defined for each port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
#ifndef PORTABLE_H #ifndef PORTABLE_H
#define PORTABLE_H #define PORTABLE_H
/* Each FreeRTOS port has a unique portmacro.h header file. Originally a /* 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 * 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 * 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 * 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 - removing the need for the constant and allowing the
portmacro.h file to be located anywhere in relation to the port being used. * 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 * 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 * 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 * specific constants has been moved into the deprecated_definitions.h header
file. */ * file. */
#include "deprecated_definitions.h" #include "deprecated_definitions.h"
/* If portENTER_CRITICAL is not defined then including 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 * 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 * included here. In this case the path to the correct portmacro.h header file
must be set in the compiler's include path. */ * must be set in the compiler's include path. */
#ifndef portENTER_CRITICAL #ifndef portENTER_CRITICAL
#include "portmacro.h" #include "portmacro.h"
#endif #endif
#if portBYTE_ALIGNMENT == 32 #if portBYTE_ALIGNMENT == 32
#define portBYTE_ALIGNMENT_MASK ( 0x001f ) #define portBYTE_ALIGNMENT_MASK ( 0x001f )
#endif #endif
#if portBYTE_ALIGNMENT == 16 #if portBYTE_ALIGNMENT == 16
#define portBYTE_ALIGNMENT_MASK ( 0x000f ) #define portBYTE_ALIGNMENT_MASK ( 0x000f )
#endif #endif
#if portBYTE_ALIGNMENT == 8 #if portBYTE_ALIGNMENT == 8
#define portBYTE_ALIGNMENT_MASK ( 0x0007 ) #define portBYTE_ALIGNMENT_MASK ( 0x0007 )
#endif #endif
#if portBYTE_ALIGNMENT == 4 #if portBYTE_ALIGNMENT == 4
#define portBYTE_ALIGNMENT_MASK ( 0x0003 ) #define portBYTE_ALIGNMENT_MASK ( 0x0003 )
#endif #endif
#if portBYTE_ALIGNMENT == 2 #if portBYTE_ALIGNMENT == 2
#define portBYTE_ALIGNMENT_MASK ( 0x0001 ) #define portBYTE_ALIGNMENT_MASK ( 0x0001 )
#endif #endif
#if portBYTE_ALIGNMENT == 1 #if portBYTE_ALIGNMENT == 1
#define portBYTE_ALIGNMENT_MASK ( 0x0000 ) #define portBYTE_ALIGNMENT_MASK ( 0x0000 )
#endif #endif
#ifndef portBYTE_ALIGNMENT_MASK #ifndef portBYTE_ALIGNMENT_MASK
#error "Invalid portBYTE_ALIGNMENT definition" #error "Invalid portBYTE_ALIGNMENT definition"
#endif #endif
#ifndef portNUM_CONFIGURABLE_REGIONS #ifndef portNUM_CONFIGURABLE_REGIONS
#define portNUM_CONFIGURABLE_REGIONS 1 #define portNUM_CONFIGURABLE_REGIONS 1
#endif #endif
#ifndef portHAS_STACK_OVERFLOW_CHECKING #ifndef portHAS_STACK_OVERFLOW_CHECKING
#define portHAS_STACK_OVERFLOW_CHECKING 0 #define portHAS_STACK_OVERFLOW_CHECKING 0
#endif #endif
#ifndef portARCH_NAME #ifndef portARCH_NAME
#define portARCH_NAME NULL #define portARCH_NAME NULL
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include "mpu_wrappers.h" #include "mpu_wrappers.h"
/* /*
* Setup the stack of a new task so it is ready to be placed under the * Setup the stack of a new task so it is ready to be placed under the
@ -103,31 +103,43 @@ extern "C" {
* the order that the port expects to find them. * the order that the port expects to find them.
* *
*/ */
#if( portUSING_MPU_WRAPPERS == 1 ) #if ( portUSING_MPU_WRAPPERS == 1 )
#if( portHAS_STACK_OVERFLOW_CHECKING == 1 ) #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION; StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION;
#else #else
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION; StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION;
#endif #endif
#else #else /* if ( portUSING_MPU_WRAPPERS == 1 ) */
#if( portHAS_STACK_OVERFLOW_CHECKING == 1 ) #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION; StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters ) PRIVILEGED_FUNCTION;
#else #else
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION; StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters ) PRIVILEGED_FUNCTION;
#endif #endif
#endif #endif /* if ( portUSING_MPU_WRAPPERS == 1 ) */
/* Used by heap_5.c to define the start address and size of each memory region /* Used by heap_5.c to define the start address and size of each memory region
that together comprise the total FreeRTOS heap space. */ * that together comprise the total FreeRTOS heap space. */
typedef struct HeapRegion typedef struct HeapRegion
{ {
uint8_t *pucStartAddress; uint8_t * pucStartAddress;
size_t xSizeInBytes; size_t xSizeInBytes;
} HeapRegion_t; } HeapRegion_t;
/* Used to pass information about the heap out of vPortGetHeapStats(). */ /* Used to pass information about the heap out of vPortGetHeapStats(). */
typedef struct xHeapStats 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 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 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 xSizeOfSmallestFreeBlockInBytes; /* The minimum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */
@ -135,7 +147,7 @@ typedef struct xHeapStats
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 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 xNumberOfSuccessfulAllocations; /* The number of calls to pvPortMalloc() that have returned a valid memory block. */
size_t xNumberOfSuccessfulFrees; /* The number of calls to vPortFree() that has successfully freed a block of memory. */ size_t xNumberOfSuccessfulFrees; /* The number of calls to vPortFree() that has successfully freed a block of memory. */
} HeapStats_t; } HeapStats_t;
/* /*
* Used to define multiple heap regions for use by heap_5.c. This function * Used to define multiple heap regions for use by heap_5.c. This function
@ -148,35 +160,35 @@ typedef struct xHeapStats
* terminated by a HeapRegions_t structure that has a size of 0. The region * 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. * with the lowest start address must appear first in the array.
*/ */
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION; void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION;
/* /*
* Returns a HeapStats_t structure filled with information about the current * Returns a HeapStats_t structure filled with information about the current
* heap state. * heap state.
*/ */
void vPortGetHeapStats( HeapStats_t *pxHeapStats ); void vPortGetHeapStats( HeapStats_t * pxHeapStats );
/* /*
* Map to the memory management routines required for the port. * Map to the memory management routines required for the port.
*/ */
void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION; void * pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION;
void vPortFree( void *pv ) PRIVILEGED_FUNCTION; void vPortFree( void * pv ) PRIVILEGED_FUNCTION;
void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION; void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION;
size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION; size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION;
size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION; size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION;
/* /*
* Setup the hardware ready for the scheduler to take control. This generally * 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. * sets up a tick interrupt and sets timers for the correct tick frequency.
*/ */
BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION; BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION;
/* /*
* Undo any hardware/ISR setup that was performed by xPortStartScheduler() so * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so
* the hardware is left in its original condition after the scheduler stops * the hardware is left in its original condition after the scheduler stops
* executing. * executing.
*/ */
void vPortEndScheduler( void ) PRIVILEGED_FUNCTION; void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
/* /*
* The structures and methods of manipulating the MPU are contained within the * The structures and methods of manipulating the MPU are contained within the
@ -185,14 +197,16 @@ void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
* Fills the xMPUSettings structure with the memory region information * Fills the xMPUSettings structure with the memory region information
* contained in xRegions. * contained in xRegions.
*/ */
#if( portUSING_MPU_WRAPPERS == 1 ) #if ( portUSING_MPU_WRAPPERS == 1 )
struct xMEMORY_REGION; struct xMEMORY_REGION;
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth ) PRIVILEGED_FUNCTION; void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
#endif const struct xMEMORY_REGION * const xRegions,
StackType_t * pxBottomOfStack,
uint32_t ulStackDepth ) PRIVILEGED_FUNCTION;
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTABLE_H */ #endif /* PORTABLE_H */

View file

@ -31,11 +31,11 @@
* Defines the prototype to which task functions must conform. Defined in this * Defines the prototype to which task functions must conform. Defined in this
* file to ensure the type is known before portable.h is included. * file to ensure the type is known before portable.h is included.
*/ */
typedef void (*TaskFunction_t)( void * ); typedef void (* TaskFunction_t)( void * );
/* Converts a time in milliseconds to a time in ticks. This macro can be /* 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 * overridden by a macro of the same name defined in FreeRTOSConfig.h in case the
definition here is not suitable for your application. */ * definition here is not suitable for your application. */
#ifndef pdMS_TO_TICKS #ifndef pdMS_TO_TICKS
#define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) ) #define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) )
#endif #endif
@ -58,14 +58,14 @@ definition here is not suitable for your application. */
#define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0 #define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0
#endif #endif
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
#define pdINTEGRITY_CHECK_VALUE 0x5a5a #define pdINTEGRITY_CHECK_VALUE 0x5a5a
#else #else
#define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL #define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL
#endif #endif
/* The following errno values are used by FreeRTOS+ components, not FreeRTOS /* The following errno values are used by FreeRTOS+ components, not FreeRTOS
itself. */ * itself. */
#define pdFREERTOS_ERRNO_NONE 0 /* No errors */ #define pdFREERTOS_ERRNO_NONE 0 /* No errors */
#define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */ #define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */
#define pdFREERTOS_ERRNO_EINTR 4 /* Interrupted system call */ #define pdFREERTOS_ERRNO_EINTR 4 /* Interrupted system call */
@ -108,7 +108,7 @@ itself. */
#define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */ #define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */
/* The following endian values are used by FreeRTOS+ components, not FreeRTOS /* The following endian values are used by FreeRTOS+ components, not FreeRTOS
itself. */ * itself. */
#define pdFREERTOS_LITTLE_ENDIAN 0 #define pdFREERTOS_LITTLE_ENDIAN 0
#define pdFREERTOS_BIG_ENDIAN 1 #define pdFREERTOS_BIG_ENDIAN 1
@ -118,6 +118,3 @@ itself. */
#endif /* PROJDEFS_H */ #endif /* PROJDEFS_H */

File diff suppressed because it is too large Load diff

View file

@ -70,26 +70,26 @@ typedef QueueHandle_t SemaphoreHandle_t;
* @param xSemaphore Handle to the created semaphore. Should be of type SemaphoreHandle_t. * @param xSemaphore Handle to the created semaphore. Should be of type SemaphoreHandle_t.
* *
* Example usage: * Example usage:
<pre> * <pre>
SemaphoreHandle_t xSemaphore = NULL; * SemaphoreHandle_t xSemaphore = NULL;
*
void vATask( void * pvParameters ) * void vATask( void * pvParameters )
{ * {
// Semaphore cannot be used before a call to vSemaphoreCreateBinary (). * // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
// This is a macro so pass the variable in directly. * // This is a macro so pass the variable in directly.
vSemaphoreCreateBinary( xSemaphore ); * vSemaphoreCreateBinary( xSemaphore );
*
if( xSemaphore != NULL ) * if( xSemaphore != NULL )
{ * {
// The semaphore was created successfully. * // The semaphore was created successfully.
// The semaphore can now be used. * // The semaphore can now be used.
} * }
} * }
</pre> * </pre>
* \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary
* \ingroup Semaphores * \ingroup Semaphores
*/ */
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
#define vSemaphoreCreateBinary( xSemaphore ) \ #define vSemaphoreCreateBinary( xSemaphore ) \
{ \ { \
( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \
@ -138,26 +138,26 @@ typedef QueueHandle_t SemaphoreHandle_t;
* hold the semaphore's data structures could not be allocated. * hold the semaphore's data structures could not be allocated.
* *
* Example usage: * Example usage:
<pre> * <pre>
SemaphoreHandle_t xSemaphore = NULL; * SemaphoreHandle_t xSemaphore = NULL;
*
void vATask( void * pvParameters ) * void vATask( void * pvParameters )
{ * {
// Semaphore cannot be used before a call to xSemaphoreCreateBinary(). * // Semaphore cannot be used before a call to xSemaphoreCreateBinary().
// This is a macro so pass the variable in directly. * // This is a macro so pass the variable in directly.
xSemaphore = xSemaphoreCreateBinary(); * xSemaphore = xSemaphoreCreateBinary();
*
if( xSemaphore != NULL ) * if( xSemaphore != NULL )
{ * {
// The semaphore was created successfully. * // The semaphore was created successfully.
// The semaphore can now be used. * // The semaphore can now be used.
} * }
} * }
</pre> * </pre>
* \defgroup xSemaphoreCreateBinary xSemaphoreCreateBinary * \defgroup xSemaphoreCreateBinary xSemaphoreCreateBinary
* \ingroup Semaphores * \ingroup Semaphores
*/ */
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ) #define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
#endif #endif
@ -196,27 +196,27 @@ typedef QueueHandle_t SemaphoreHandle_t;
* returned. If pxSemaphoreBuffer is NULL then NULL is returned. * returned. If pxSemaphoreBuffer is NULL then NULL is returned.
* *
* Example usage: * Example usage:
<pre> * <pre>
SemaphoreHandle_t xSemaphore = NULL; * SemaphoreHandle_t xSemaphore = NULL;
StaticSemaphore_t xSemaphoreBuffer; * StaticSemaphore_t xSemaphoreBuffer;
*
void vATask( void * pvParameters ) * void vATask( void * pvParameters )
{ * {
// Semaphore cannot be used before a call to xSemaphoreCreateBinary(). * // Semaphore cannot be used before a call to xSemaphoreCreateBinary().
// The semaphore's data structures will be placed in the xSemaphoreBuffer * // The semaphore's data structures will be placed in the xSemaphoreBuffer
// variable, the address of which is passed into the function. The * // variable, the address of which is passed into the function. The
// function's parameter is not NULL, so the function will not attempt any * // function's parameter is not NULL, so the function will not attempt any
// dynamic memory allocation, and therefore the function will not return * // dynamic memory allocation, and therefore the function will not return
// return NULL. * // return NULL.
xSemaphore = xSemaphoreCreateBinary( &xSemaphoreBuffer ); * xSemaphore = xSemaphoreCreateBinary( &xSemaphoreBuffer );
*
// Rest of task code goes here. * // Rest of task code goes here.
} * }
</pre> * </pre>
* \defgroup xSemaphoreCreateBinaryStatic xSemaphoreCreateBinaryStatic * \defgroup xSemaphoreCreateBinaryStatic xSemaphoreCreateBinaryStatic
* \ingroup Semaphores * \ingroup Semaphores
*/ */
#if( configSUPPORT_STATIC_ALLOCATION == 1 ) #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
#define xSemaphoreCreateBinaryStatic( pxStaticSemaphore ) xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticSemaphore, queueQUEUE_TYPE_BINARY_SEMAPHORE ) #define xSemaphoreCreateBinaryStatic( pxStaticSemaphore ) xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticSemaphore, queueQUEUE_TYPE_BINARY_SEMAPHORE )
#endif /* configSUPPORT_STATIC_ALLOCATION */ #endif /* configSUPPORT_STATIC_ALLOCATION */
@ -244,44 +244,44 @@ typedef QueueHandle_t SemaphoreHandle_t;
* if xBlockTime expired without the semaphore becoming available. * if xBlockTime expired without the semaphore becoming available.
* *
* Example usage: * Example usage:
<pre> * <pre>
SemaphoreHandle_t xSemaphore = NULL; * SemaphoreHandle_t xSemaphore = NULL;
*
// A task that creates a semaphore. * // A task that creates a semaphore.
void vATask( void * pvParameters ) * void vATask( void * pvParameters )
{ * {
// Create the semaphore to guard a shared resource. * // Create the semaphore to guard a shared resource.
xSemaphore = xSemaphoreCreateBinary(); * xSemaphore = xSemaphoreCreateBinary();
} * }
*
// A task that uses the semaphore. * // A task that uses the semaphore.
void vAnotherTask( void * pvParameters ) * void vAnotherTask( void * pvParameters )
{ * {
// ... Do other things. * // ... Do other things.
*
if( xSemaphore != NULL ) * if( xSemaphore != NULL )
{ * {
// See if we can obtain the semaphore. If the semaphore is not available * // See if we can obtain the semaphore. If the semaphore is not available
// wait 10 ticks to see if it becomes free. * // wait 10 ticks to see if it becomes free.
if( xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ) == pdTRUE ) * if( xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
{ * {
// We were able to obtain the semaphore and can now access the * // We were able to obtain the semaphore and can now access the
// shared resource. * // shared resource.
*
// ... * // ...
*
// We have finished accessing the shared resource. Release the * // We have finished accessing the shared resource. Release the
// semaphore. * // semaphore.
xSemaphoreGive( xSemaphore ); * xSemaphoreGive( xSemaphore );
} * }
else * else
{ * {
// We could not obtain the semaphore and can therefore not access * // We could not obtain the semaphore and can therefore not access
// the shared resource safely. * // the shared resource safely.
} * }
} * }
} * }
</pre> * </pre>
* \defgroup xSemaphoreTake xSemaphoreTake * \defgroup xSemaphoreTake xSemaphoreTake
* \ingroup Semaphores * \ingroup Semaphores
*/ */
@ -323,62 +323,62 @@ typedef QueueHandle_t SemaphoreHandle_t;
* expired without the semaphore becoming available. * expired without the semaphore becoming available.
* *
* Example usage: * Example usage:
<pre> * <pre>
SemaphoreHandle_t xMutex = NULL; * SemaphoreHandle_t xMutex = NULL;
*
// A task that creates a mutex. * // A task that creates a mutex.
void vATask( void * pvParameters ) * void vATask( void * pvParameters )
{ * {
// Create the mutex to guard a shared resource. * // Create the mutex to guard a shared resource.
xMutex = xSemaphoreCreateRecursiveMutex(); * xMutex = xSemaphoreCreateRecursiveMutex();
} * }
*
// A task that uses the mutex. * // A task that uses the mutex.
void vAnotherTask( void * pvParameters ) * void vAnotherTask( void * pvParameters )
{ * {
// ... Do other things. * // ... Do other things.
*
if( xMutex != NULL ) * if( xMutex != NULL )
{ * {
// See if we can obtain the mutex. If the mutex is not available * // See if we can obtain the mutex. If the mutex is not available
// wait 10 ticks to see if it becomes free. * // wait 10 ticks to see if it becomes free.
if( xSemaphoreTakeRecursive( xSemaphore, ( TickType_t ) 10 ) == pdTRUE ) * if( xSemaphoreTakeRecursive( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
{ * {
// We were able to obtain the mutex and can now access the * // We were able to obtain the mutex and can now access the
// shared resource. * // shared resource.
*
// ... * // ...
// For some reason due to the nature of the code further calls to * // For some reason due to the nature of the code further calls to
// xSemaphoreTakeRecursive() are made on the same mutex. In real * // xSemaphoreTakeRecursive() are made on the same mutex. In real
// code these would not be just sequential calls as this would make * // code these would not be just sequential calls as this would make
// no sense. Instead the calls are likely to be buried inside * // no sense. Instead the calls are likely to be buried inside
// a more complex call structure. * // a more complex call structure.
xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
*
// The mutex has now been 'taken' three times, so will not be * // The mutex has now been 'taken' three times, so will not be
// available to another task until it has also been given back * // available to another task until it has also been given back
// three times. Again it is unlikely that real code would have * // three times. Again it is unlikely that real code would have
// these calls sequentially, but instead buried in a more complex * // these calls sequentially, but instead buried in a more complex
// call structure. This is just for illustrative purposes. * // call structure. This is just for illustrative purposes.
xSemaphoreGiveRecursive( xMutex ); * xSemaphoreGiveRecursive( xMutex );
xSemaphoreGiveRecursive( xMutex ); * xSemaphoreGiveRecursive( xMutex );
xSemaphoreGiveRecursive( xMutex ); * xSemaphoreGiveRecursive( xMutex );
*
// Now the mutex can be taken by other tasks. * // Now the mutex can be taken by other tasks.
} * }
else * else
{ * {
// We could not obtain the mutex and can therefore not access * // We could not obtain the mutex and can therefore not access
// the shared resource safely. * // the shared resource safely.
} * }
} * }
} * }
</pre> * </pre>
* \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive
* \ingroup Semaphores * \ingroup Semaphores
*/ */
#if( configUSE_RECURSIVE_MUTEXES == 1 ) #if ( configUSE_RECURSIVE_MUTEXES == 1 )
#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) #define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) )
#endif #endif
@ -405,41 +405,41 @@ typedef QueueHandle_t SemaphoreHandle_t;
* semaphore was not first obtained correctly. * semaphore was not first obtained correctly.
* *
* Example usage: * Example usage:
<pre> * <pre>
SemaphoreHandle_t xSemaphore = NULL; * SemaphoreHandle_t xSemaphore = NULL;
*
void vATask( void * pvParameters ) * void vATask( void * pvParameters )
{ * {
// Create the semaphore to guard a shared resource. * // Create the semaphore to guard a shared resource.
xSemaphore = vSemaphoreCreateBinary(); * xSemaphore = vSemaphoreCreateBinary();
*
if( xSemaphore != NULL ) * if( xSemaphore != NULL )
{ * {
if( xSemaphoreGive( xSemaphore ) != pdTRUE ) * if( xSemaphoreGive( xSemaphore ) != pdTRUE )
{ * {
// We would expect this call to fail because we cannot give * // We would expect this call to fail because we cannot give
// a semaphore without first "taking" it! * // a semaphore without first "taking" it!
} * }
*
// Obtain the semaphore - don't block if the semaphore is not * // Obtain the semaphore - don't block if the semaphore is not
// immediately available. * // immediately available.
if( xSemaphoreTake( xSemaphore, ( TickType_t ) 0 ) ) * if( xSemaphoreTake( xSemaphore, ( TickType_t ) 0 ) )
{ * {
// We now have the semaphore and can access the shared resource. * // We now have the semaphore and can access the shared resource.
*
// ... * // ...
*
// We have finished accessing the shared resource so can free the * // We have finished accessing the shared resource so can free the
// semaphore. * // semaphore.
if( xSemaphoreGive( xSemaphore ) != pdTRUE ) * if( xSemaphoreGive( xSemaphore ) != pdTRUE )
{ * {
// We would not expect this call to fail because we must have * // We would not expect this call to fail because we must have
// obtained the semaphore to get here. * // obtained the semaphore to get here.
} * }
} * }
} * }
} * }
</pre> * </pre>
* \defgroup xSemaphoreGive xSemaphoreGive * \defgroup xSemaphoreGive xSemaphoreGive
* \ingroup Semaphores * \ingroup Semaphores
*/ */
@ -471,73 +471,73 @@ typedef QueueHandle_t SemaphoreHandle_t;
* @return pdTRUE if the semaphore was given. * @return pdTRUE if the semaphore was given.
* *
* Example usage: * Example usage:
<pre> * <pre>
SemaphoreHandle_t xMutex = NULL; * SemaphoreHandle_t xMutex = NULL;
*
// A task that creates a mutex. * // A task that creates a mutex.
void vATask( void * pvParameters ) * void vATask( void * pvParameters )
{ * {
// Create the mutex to guard a shared resource. * // Create the mutex to guard a shared resource.
xMutex = xSemaphoreCreateRecursiveMutex(); * xMutex = xSemaphoreCreateRecursiveMutex();
} * }
*
// A task that uses the mutex. * // A task that uses the mutex.
void vAnotherTask( void * pvParameters ) * void vAnotherTask( void * pvParameters )
{ * {
// ... Do other things. * // ... Do other things.
*
if( xMutex != NULL ) * if( xMutex != NULL )
{ * {
// See if we can obtain the mutex. If the mutex is not available * // See if we can obtain the mutex. If the mutex is not available
// wait 10 ticks to see if it becomes free. * // wait 10 ticks to see if it becomes free.
if( xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ) == pdTRUE ) * if( xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ) == pdTRUE )
{ * {
// We were able to obtain the mutex and can now access the * // We were able to obtain the mutex and can now access the
// shared resource. * // shared resource.
*
// ... * // ...
// For some reason due to the nature of the code further calls to * // For some reason due to the nature of the code further calls to
// xSemaphoreTakeRecursive() are made on the same mutex. In real * // xSemaphoreTakeRecursive() are made on the same mutex. In real
// code these would not be just sequential calls as this would make * // code these would not be just sequential calls as this would make
// no sense. Instead the calls are likely to be buried inside * // no sense. Instead the calls are likely to be buried inside
// a more complex call structure. * // a more complex call structure.
xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
*
// The mutex has now been 'taken' three times, so will not be * // The mutex has now been 'taken' three times, so will not be
// available to another task until it has also been given back * // available to another task until it has also been given back
// three times. Again it is unlikely that real code would have * // three times. Again it is unlikely that real code would have
// these calls sequentially, it would be more likely that the calls * // these calls sequentially, it would be more likely that the calls
// to xSemaphoreGiveRecursive() would be called as a call stack * // to xSemaphoreGiveRecursive() would be called as a call stack
// unwound. This is just for demonstrative purposes. * // unwound. This is just for demonstrative purposes.
xSemaphoreGiveRecursive( xMutex ); * xSemaphoreGiveRecursive( xMutex );
xSemaphoreGiveRecursive( xMutex ); * xSemaphoreGiveRecursive( xMutex );
xSemaphoreGiveRecursive( xMutex ); * xSemaphoreGiveRecursive( xMutex );
*
// Now the mutex can be taken by other tasks. * // Now the mutex can be taken by other tasks.
} * }
else * else
{ * {
// We could not obtain the mutex and can therefore not access * // We could not obtain the mutex and can therefore not access
// the shared resource safely. * // the shared resource safely.
} * }
} * }
} * }
</pre> * </pre>
* \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive
* \ingroup Semaphores * \ingroup Semaphores
*/ */
#if( configUSE_RECURSIVE_MUTEXES == 1 ) #if ( configUSE_RECURSIVE_MUTEXES == 1 )
#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) #define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) )
#endif #endif
/** /**
* semphr. h * semphr. h
* <pre> * <pre>
xSemaphoreGiveFromISR( * xSemaphoreGiveFromISR(
SemaphoreHandle_t xSemaphore, * SemaphoreHandle_t xSemaphore,
BaseType_t *pxHigherPriorityTaskWoken * BaseType_t *pxHigherPriorityTaskWoken
)</pre> * )</pre>
* *
* <i>Macro</i> to release a semaphore. The semaphore must have previously been * <i>Macro</i> to release a semaphore. The semaphore must have previously been
* created with a call to xSemaphoreCreateBinary() or xSemaphoreCreateCounting(). * created with a call to xSemaphoreCreateBinary() or xSemaphoreCreateCounting().
@ -559,64 +559,64 @@ typedef QueueHandle_t SemaphoreHandle_t;
* @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL. * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL.
* *
* Example usage: * Example usage:
<pre> * <pre>
\#define LONG_TIME 0xffff \#define LONG_TIME 0xffff
\#define TICKS_TO_WAIT 10 \#define TICKS_TO_WAIT 10
SemaphoreHandle_t xSemaphore = NULL; * SemaphoreHandle_t xSemaphore = NULL;
*
// Repetitive task. * // Repetitive task.
void vATask( void * pvParameters ) * void vATask( void * pvParameters )
{ * {
for( ;; ) * for( ;; )
{ * {
// We want this task to run every 10 ticks of a timer. The semaphore * // We want this task to run every 10 ticks of a timer. The semaphore
// was created before this task was started. * // was created before this task was started.
*
// Block waiting for the semaphore to become available. * // Block waiting for the semaphore to become available.
if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE ) * if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE )
{ * {
// It is time to execute. * // It is time to execute.
*
// ... * // ...
*
// We have finished our task. Return to the top of the loop where * // We have finished our task. Return to the top of the loop where
// we will block on the semaphore until it is time to execute * // we will block on the semaphore until it is time to execute
// again. Note when using the semaphore for synchronisation with an * // again. Note when using the semaphore for synchronisation with an
// ISR in this manner there is no need to 'give' the semaphore back. * // ISR in this manner there is no need to 'give' the semaphore back.
} * }
} * }
} * }
*
// Timer ISR * // Timer ISR
void vTimerISR( void * pvParameters ) * void vTimerISR( void * pvParameters )
{ * {
static uint8_t ucLocalTickCount = 0; * static uint8_t ucLocalTickCount = 0;
static BaseType_t xHigherPriorityTaskWoken; * static BaseType_t xHigherPriorityTaskWoken;
*
// A timer tick has occurred. * // A timer tick has occurred.
*
// ... Do other time functions. * // ... Do other time functions.
*
// Is it time for vATask () to run? * // Is it time for vATask () to run?
xHigherPriorityTaskWoken = pdFALSE; * xHigherPriorityTaskWoken = pdFALSE;
ucLocalTickCount++; * ucLocalTickCount++;
if( ucLocalTickCount >= TICKS_TO_WAIT ) * if( ucLocalTickCount >= TICKS_TO_WAIT )
{ * {
// Unblock the task by releasing the semaphore. * // Unblock the task by releasing the semaphore.
xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken ); * xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );
*
// Reset the count so we release the semaphore again in 10 ticks time. * // Reset the count so we release the semaphore again in 10 ticks time.
ucLocalTickCount = 0; * ucLocalTickCount = 0;
} * }
*
if( xHigherPriorityTaskWoken != pdFALSE ) * if( xHigherPriorityTaskWoken != pdFALSE )
{ * {
// We can force a context switch here. Context switching from an * // We can force a context switch here. Context switching from an
// ISR uses port specific syntax. Check the demo task for your port * // ISR uses port specific syntax. Check the demo task for your port
// to find the syntax required. * // to find the syntax required.
} * }
} * }
</pre> * </pre>
* \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR
* \ingroup Semaphores * \ingroup Semaphores
*/ */
@ -625,10 +625,10 @@ typedef QueueHandle_t SemaphoreHandle_t;
/** /**
* semphr. h * semphr. h
* <pre> * <pre>
xSemaphoreTakeFromISR( * xSemaphoreTakeFromISR(
SemaphoreHandle_t xSemaphore, * SemaphoreHandle_t xSemaphore,
BaseType_t *pxHigherPriorityTaskWoken * BaseType_t *pxHigherPriorityTaskWoken
)</pre> * )</pre>
* *
* <i>Macro</i> to take a semaphore from an ISR. The semaphore must have * <i>Macro</i> to take a semaphore from an ISR. The semaphore must have
* previously been created with a call to xSemaphoreCreateBinary() or * previously been created with a call to xSemaphoreCreateBinary() or
@ -692,26 +692,26 @@ typedef QueueHandle_t SemaphoreHandle_t;
* data structures then NULL is returned. * data structures then NULL is returned.
* *
* Example usage: * Example usage:
<pre> * <pre>
SemaphoreHandle_t xSemaphore; * SemaphoreHandle_t xSemaphore;
*
void vATask( void * pvParameters ) * void vATask( void * pvParameters )
{ * {
// Semaphore cannot be used before a call to xSemaphoreCreateMutex(). * // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
// This is a macro so pass the variable in directly. * // This is a macro so pass the variable in directly.
xSemaphore = xSemaphoreCreateMutex(); * xSemaphore = xSemaphoreCreateMutex();
*
if( xSemaphore != NULL ) * if( xSemaphore != NULL )
{ * {
// The semaphore was created successfully. * // The semaphore was created successfully.
// The semaphore can now be used. * // The semaphore can now be used.
} * }
} * }
</pre> * </pre>
* \defgroup xSemaphoreCreateMutex xSemaphoreCreateMutex * \defgroup xSemaphoreCreateMutex xSemaphoreCreateMutex
* \ingroup Semaphores * \ingroup Semaphores
*/ */
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ) #define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
#endif #endif
@ -754,25 +754,25 @@ typedef QueueHandle_t SemaphoreHandle_t;
* mutex is returned. If pxMutexBuffer was NULL then NULL is returned. * mutex is returned. If pxMutexBuffer was NULL then NULL is returned.
* *
* Example usage: * Example usage:
<pre> * <pre>
SemaphoreHandle_t xSemaphore; * SemaphoreHandle_t xSemaphore;
StaticSemaphore_t xMutexBuffer; * StaticSemaphore_t xMutexBuffer;
*
void vATask( void * pvParameters ) * void vATask( void * pvParameters )
{ * {
// A mutex cannot be used before it has been created. xMutexBuffer is * // A mutex cannot be used before it has been created. xMutexBuffer is
// into xSemaphoreCreateMutexStatic() so no dynamic memory allocation is * // into xSemaphoreCreateMutexStatic() so no dynamic memory allocation is
// attempted. * // attempted.
xSemaphore = xSemaphoreCreateMutexStatic( &xMutexBuffer ); * xSemaphore = xSemaphoreCreateMutexStatic( &xMutexBuffer );
*
// As no dynamic memory allocation was performed, xSemaphore cannot be NULL, * // As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
// so there is no need to check it. * // so there is no need to check it.
} * }
</pre> * </pre>
* \defgroup xSemaphoreCreateMutexStatic xSemaphoreCreateMutexStatic * \defgroup xSemaphoreCreateMutexStatic xSemaphoreCreateMutexStatic
* \ingroup Semaphores * \ingroup Semaphores
*/ */
#if( configSUPPORT_STATIC_ALLOCATION == 1 ) #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
#define xSemaphoreCreateMutexStatic( pxMutexBuffer ) xQueueCreateMutexStatic( queueQUEUE_TYPE_MUTEX, ( pxMutexBuffer ) ) #define xSemaphoreCreateMutexStatic( pxMutexBuffer ) xQueueCreateMutexStatic( queueQUEUE_TYPE_MUTEX, ( pxMutexBuffer ) )
#endif /* configSUPPORT_STATIC_ALLOCATION */ #endif /* configSUPPORT_STATIC_ALLOCATION */
@ -821,26 +821,26 @@ typedef QueueHandle_t SemaphoreHandle_t;
* SemaphoreHandle_t. * SemaphoreHandle_t.
* *
* Example usage: * Example usage:
<pre> * <pre>
SemaphoreHandle_t xSemaphore; * SemaphoreHandle_t xSemaphore;
*
void vATask( void * pvParameters ) * void vATask( void * pvParameters )
{ * {
// Semaphore cannot be used before a call to xSemaphoreCreateMutex(). * // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
// This is a macro so pass the variable in directly. * // This is a macro so pass the variable in directly.
xSemaphore = xSemaphoreCreateRecursiveMutex(); * xSemaphore = xSemaphoreCreateRecursiveMutex();
*
if( xSemaphore != NULL ) * if( xSemaphore != NULL )
{ * {
// The semaphore was created successfully. * // The semaphore was created successfully.
// The semaphore can now be used. * // The semaphore can now be used.
} * }
} * }
</pre> * </pre>
* \defgroup xSemaphoreCreateRecursiveMutex xSemaphoreCreateRecursiveMutex * \defgroup xSemaphoreCreateRecursiveMutex xSemaphoreCreateRecursiveMutex
* \ingroup Semaphores * \ingroup Semaphores
*/ */
#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) ) #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) )
#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX ) #define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX )
#endif #endif
@ -893,27 +893,27 @@ typedef QueueHandle_t SemaphoreHandle_t;
* returned. * returned.
* *
* Example usage: * Example usage:
<pre> * <pre>
SemaphoreHandle_t xSemaphore; * SemaphoreHandle_t xSemaphore;
StaticSemaphore_t xMutexBuffer; * StaticSemaphore_t xMutexBuffer;
*
void vATask( void * pvParameters ) * void vATask( void * pvParameters )
{ * {
// A recursive semaphore cannot be used before it is created. Here a * // A recursive semaphore cannot be used before it is created. Here a
// recursive mutex is created using xSemaphoreCreateRecursiveMutexStatic(). * // recursive mutex is created using xSemaphoreCreateRecursiveMutexStatic().
// The address of xMutexBuffer is passed into the function, and will hold * // The address of xMutexBuffer is passed into the function, and will hold
// the mutexes data structures - so no dynamic memory allocation will be * // the mutexes data structures - so no dynamic memory allocation will be
// attempted. * // attempted.
xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xMutexBuffer ); * xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xMutexBuffer );
*
// As no dynamic memory allocation was performed, xSemaphore cannot be NULL, * // As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
// so there is no need to check it. * // so there is no need to check it.
} * }
</pre> * </pre>
* \defgroup xSemaphoreCreateRecursiveMutexStatic xSemaphoreCreateRecursiveMutexStatic * \defgroup xSemaphoreCreateRecursiveMutexStatic xSemaphoreCreateRecursiveMutexStatic
* \ingroup Semaphores * \ingroup Semaphores
*/ */
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) ) #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) )
#define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutexStatic( queueQUEUE_TYPE_RECURSIVE_MUTEX, pxStaticSemaphore ) #define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutexStatic( queueQUEUE_TYPE_RECURSIVE_MUTEX, pxStaticSemaphore )
#endif /* configSUPPORT_STATIC_ALLOCATION */ #endif /* configSUPPORT_STATIC_ALLOCATION */
@ -971,29 +971,29 @@ typedef QueueHandle_t SemaphoreHandle_t;
* created. * created.
* *
* Example usage: * Example usage:
<pre> * <pre>
SemaphoreHandle_t xSemaphore; * SemaphoreHandle_t xSemaphore;
*
void vATask( void * pvParameters ) * void vATask( void * pvParameters )
{ * {
SemaphoreHandle_t xSemaphore = NULL; * SemaphoreHandle_t xSemaphore = NULL;
*
// Semaphore cannot be used before a call to xSemaphoreCreateCounting(). * // Semaphore cannot be used before a call to xSemaphoreCreateCounting().
// The max value to which the semaphore can count should be 10, and the * // The max value to which the semaphore can count should be 10, and the
// initial value assigned to the count should be 0. * // initial value assigned to the count should be 0.
xSemaphore = xSemaphoreCreateCounting( 10, 0 ); * xSemaphore = xSemaphoreCreateCounting( 10, 0 );
*
if( xSemaphore != NULL ) * if( xSemaphore != NULL )
{ * {
// The semaphore was created successfully. * // The semaphore was created successfully.
// The semaphore can now be used. * // The semaphore can now be used.
} * }
} * }
</pre> * </pre>
* \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting
* \ingroup Semaphores * \ingroup Semaphores
*/ */
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) #define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
#endif #endif
@ -1055,30 +1055,30 @@ typedef QueueHandle_t SemaphoreHandle_t;
* then NULL is returned. * then NULL is returned.
* *
* Example usage: * Example usage:
<pre> * <pre>
SemaphoreHandle_t xSemaphore; * SemaphoreHandle_t xSemaphore;
StaticSemaphore_t xSemaphoreBuffer; * StaticSemaphore_t xSemaphoreBuffer;
*
void vATask( void * pvParameters ) * void vATask( void * pvParameters )
{ * {
SemaphoreHandle_t xSemaphore = NULL; * SemaphoreHandle_t xSemaphore = NULL;
*
// Counting semaphore cannot be used before they have been created. Create * // Counting semaphore cannot be used before they have been created. Create
// a counting semaphore using xSemaphoreCreateCountingStatic(). The max * // a counting semaphore using xSemaphoreCreateCountingStatic(). The max
// value to which the semaphore can count is 10, and the initial value * // value to which the semaphore can count is 10, and the initial value
// assigned to the count will be 0. The address of xSemaphoreBuffer is * // assigned to the count will be 0. The address of xSemaphoreBuffer is
// passed in and will be used to hold the semaphore structure, so no dynamic * // passed in and will be used to hold the semaphore structure, so no dynamic
// memory allocation will be used. * // memory allocation will be used.
xSemaphore = xSemaphoreCreateCounting( 10, 0, &xSemaphoreBuffer ); * xSemaphore = xSemaphoreCreateCounting( 10, 0, &xSemaphoreBuffer );
*
// No memory allocation was attempted so xSemaphore cannot be NULL, so there * // No memory allocation was attempted so xSemaphore cannot be NULL, so there
// is no need to check its value. * // is no need to check its value.
} * }
</pre> * </pre>
* \defgroup xSemaphoreCreateCountingStatic xSemaphoreCreateCountingStatic * \defgroup xSemaphoreCreateCountingStatic xSemaphoreCreateCountingStatic
* \ingroup Semaphores * \ingroup Semaphores
*/ */
#if( configSUPPORT_STATIC_ALLOCATION == 1 ) #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
#define xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxSemaphoreBuffer ) xQueueCreateCountingSemaphoreStatic( ( uxMaxCount ), ( uxInitialCount ), ( pxSemaphoreBuffer ) ) #define xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxSemaphoreBuffer ) xQueueCreateCountingSemaphoreStatic( ( uxMaxCount ), ( uxInitialCount ), ( pxSemaphoreBuffer ) )
#endif /* configSUPPORT_STATIC_ALLOCATION */ #endif /* configSUPPORT_STATIC_ALLOCATION */
@ -1135,5 +1135,3 @@ typedef QueueHandle_t SemaphoreHandle_t;
#define uxSemaphoreGetCount( xSemaphore ) uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) ) #define uxSemaphoreGetCount( xSemaphore ) uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) )
#endif /* SEMAPHORE_H */ #endif /* SEMAPHORE_H */

View file

@ -43,9 +43,9 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) ) #if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) )
/* Only the current stack state is to be checked. */ /* Only the current stack state is to be checked. */
#define taskCHECK_FOR_STACK_OVERFLOW() \ #define taskCHECK_FOR_STACK_OVERFLOW() \
{ \ { \
/* Is the currently saved stack pointer within the stack limit? */ \ /* Is the currently saved stack pointer within the stack limit? */ \
@ -58,9 +58,9 @@
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) ) #if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) )
/* Only the current stack state is to be checked. */ /* Only the current stack state is to be checked. */
#define taskCHECK_FOR_STACK_OVERFLOW() \ #define taskCHECK_FOR_STACK_OVERFLOW() \
{ \ { \
\ \
@ -74,7 +74,7 @@
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) #if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) )
#define taskCHECK_FOR_STACK_OVERFLOW() \ #define taskCHECK_FOR_STACK_OVERFLOW() \
{ \ { \
@ -93,11 +93,11 @@
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) #if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) )
#define taskCHECK_FOR_STACK_OVERFLOW() \ #define taskCHECK_FOR_STACK_OVERFLOW() \
{ \ { \
int8_t *pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \ int8_t * pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \
static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 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, \
@ -125,4 +125,3 @@
#endif /* STACK_MACROS_H */ #endif /* STACK_MACROS_H */

View file

@ -48,15 +48,15 @@
*/ */
#ifndef STREAM_BUFFER_H #ifndef STREAM_BUFFER_H
#define STREAM_BUFFER_H #define STREAM_BUFFER_H
#ifndef INC_FREERTOS_H #ifndef INC_FREERTOS_H
#error "include FreeRTOS.h must appear in source files before include stream_buffer.h" #error "include FreeRTOS.h must appear in source files before include stream_buffer.h"
#endif #endif
#if defined( __cplusplus ) #if defined( __cplusplus )
extern "C" { extern "C" {
#endif #endif
/** /**
* Type by which stream buffers are referenced. For example, a call to * Type by which stream buffers are referenced. For example, a call to
@ -64,16 +64,16 @@ extern "C" {
* then be used as a parameter to xStreamBufferSend(), xStreamBufferReceive(), * then be used as a parameter to xStreamBufferSend(), xStreamBufferReceive(),
* etc. * etc.
*/ */
struct StreamBufferDef_t; struct StreamBufferDef_t;
typedef struct StreamBufferDef_t * StreamBufferHandle_t; typedef struct StreamBufferDef_t * StreamBufferHandle_t;
/** /**
* message_buffer.h * message_buffer.h
* *
<pre> * <pre>
StreamBufferHandle_t xStreamBufferCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes ); * StreamBufferHandle_t xStreamBufferCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes );
</pre> * </pre>
* *
* Creates a new stream buffer using dynamically allocated memory. See * Creates a new stream buffer using dynamically allocated memory. See
* xStreamBufferCreateStatic() for a version that uses statically allocated * xStreamBufferCreateStatic() for a version that uses statically allocated
@ -107,43 +107,43 @@ StreamBufferHandle_t xStreamBufferCreate( size_t xBufferSizeBytes, size_t xTrigg
* buffer. * buffer.
* *
* Example use: * Example use:
<pre> * <pre>
*
void vAFunction( void ) * void vAFunction( void )
{ * {
StreamBufferHandle_t xStreamBuffer; * StreamBufferHandle_t xStreamBuffer;
const size_t xStreamBufferSizeBytes = 100, xTriggerLevel = 10; * const size_t xStreamBufferSizeBytes = 100, xTriggerLevel = 10;
*
// Create a stream buffer that can hold 100 bytes. The memory used to hold * // 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 * // both the stream buffer structure and the data in the stream buffer is
// allocated dynamically. * // allocated dynamically.
xStreamBuffer = xStreamBufferCreate( xStreamBufferSizeBytes, xTriggerLevel ); * xStreamBuffer = xStreamBufferCreate( xStreamBufferSizeBytes, xTriggerLevel );
*
if( xStreamBuffer == NULL ) * if( xStreamBuffer == NULL )
{ * {
// There was not enough heap memory space available to create the * // There was not enough heap memory space available to create the
// stream buffer. * // stream buffer.
} * }
else * else
{ * {
// The stream buffer was created successfully and can now be used. * // The stream buffer was created successfully and can now be used.
} * }
} * }
</pre> * </pre>
* \defgroup xStreamBufferCreate xStreamBufferCreate * \defgroup xStreamBufferCreate xStreamBufferCreate
* \ingroup StreamBufferManagement * \ingroup StreamBufferManagement
*/ */
#define xStreamBufferCreate( xBufferSizeBytes, xTriggerLevelBytes ) xStreamBufferGenericCreate( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE ) #define xStreamBufferCreate( xBufferSizeBytes, xTriggerLevelBytes ) xStreamBufferGenericCreate( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE )
/** /**
* stream_buffer.h * stream_buffer.h
* *
<pre> * <pre>
StreamBufferHandle_t xStreamBufferCreateStatic( size_t xBufferSizeBytes, * StreamBufferHandle_t xStreamBufferCreateStatic( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes, * size_t xTriggerLevelBytes,
uint8_t *pucStreamBufferStorageArea, * uint8_t *pucStreamBufferStorageArea,
StaticStreamBuffer_t *pxStaticStreamBuffer ); * StaticStreamBuffer_t *pxStaticStreamBuffer );
</pre> * </pre>
* Creates a new stream buffer using statically allocated memory. See * Creates a new stream buffer using statically allocated memory. See
* xStreamBufferCreate() for a version that uses dynamically allocated memory. * xStreamBufferCreate() for a version that uses dynamically allocated memory.
* *
@ -180,51 +180,51 @@ StreamBufferHandle_t xStreamBufferCreateStatic( size_t xBufferSizeBytes,
* pxStaticstreamBuffer are NULL then NULL is returned. * pxStaticstreamBuffer are NULL then NULL is returned.
* *
* Example use: * Example use:
<pre> * <pre>
*
// Used to dimension the array used to hold the streams. The available space * // Used to dimension the array used to hold the streams. The available space
// will actually be one less than this, so 999. * // will actually be one less than this, so 999.
#define STORAGE_SIZE_BYTES 1000 #define STORAGE_SIZE_BYTES 1000
*
// Defines the memory that will actually hold the streams within the stream * // Defines the memory that will actually hold the streams within the stream
// buffer. * // buffer.
static uint8_t ucStorageBuffer[ STORAGE_SIZE_BYTES ]; * static uint8_t ucStorageBuffer[ STORAGE_SIZE_BYTES ];
*
// The variable used to hold the stream buffer structure. * // The variable used to hold the stream buffer structure.
StaticStreamBuffer_t xStreamBufferStruct; * StaticStreamBuffer_t xStreamBufferStruct;
*
void MyFunction( void ) * void MyFunction( void )
{ * {
StreamBufferHandle_t xStreamBuffer; * StreamBufferHandle_t xStreamBuffer;
const size_t xTriggerLevel = 1; * const size_t xTriggerLevel = 1;
*
xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucBufferStorage ), * xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucBufferStorage ),
xTriggerLevel, * xTriggerLevel,
ucBufferStorage, * ucBufferStorage,
&xStreamBufferStruct ); * &xStreamBufferStruct );
*
// As neither the pucStreamBufferStorageArea or pxStaticStreamBuffer * // As neither the pucStreamBufferStorageArea or pxStaticStreamBuffer
// parameters were NULL, xStreamBuffer will not be NULL, and can be used to * // parameters were NULL, xStreamBuffer will not be NULL, and can be used to
// reference the created stream buffer in other stream buffer API calls. * // reference the created stream buffer in other stream buffer API calls.
*
// Other code that uses the stream buffer can go here. * // Other code that uses the stream buffer can go here.
} * }
*
</pre> * </pre>
* \defgroup xStreamBufferCreateStatic xStreamBufferCreateStatic * \defgroup xStreamBufferCreateStatic xStreamBufferCreateStatic
* \ingroup StreamBufferManagement * \ingroup StreamBufferManagement
*/ */
#define xStreamBufferCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE, pucStreamBufferStorageArea, pxStaticStreamBuffer ) #define xStreamBufferCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE, pucStreamBufferStorageArea, pxStaticStreamBuffer )
/** /**
* stream_buffer.h * stream_buffer.h
* *
<pre> * <pre>
size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, * size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
const void *pvTxData, * const void *pvTxData,
size_t xDataLengthBytes, * size_t xDataLengthBytes,
TickType_t xTicksToWait ); * TickType_t xTicksToWait );
</pre> * </pre>
* *
* Sends bytes to a stream buffer. The bytes are copied into the stream buffer. * Sends bytes to a stream buffer. The bytes are copied into the stream buffer.
* *
@ -274,54 +274,54 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
* write as many bytes as possible. * write as many bytes as possible.
* *
* Example use: * Example use:
<pre> * <pre>
void vAFunction( StreamBufferHandle_t xStreamBuffer ) * void vAFunction( StreamBufferHandle_t xStreamBuffer )
{ * {
size_t xBytesSent; * size_t xBytesSent;
uint8_t ucArrayToSend[] = { 0, 1, 2, 3 }; * uint8_t ucArrayToSend[] = { 0, 1, 2, 3 };
char *pcStringToSend = "String to send"; * char *pcStringToSend = "String to send";
const TickType_t x100ms = pdMS_TO_TICKS( 100 ); * const TickType_t x100ms = pdMS_TO_TICKS( 100 );
*
// Send an array to the stream buffer, blocking for a maximum of 100ms to * // 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. * // wait for enough space to be available in the stream buffer.
xBytesSent = xStreamBufferSend( xStreamBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms ); * xBytesSent = xStreamBufferSend( xStreamBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms );
*
if( xBytesSent != sizeof( ucArrayToSend ) ) * if( xBytesSent != sizeof( ucArrayToSend ) )
{ * {
// The call to xStreamBufferSend() times out before there was enough * // The call to xStreamBufferSend() times out before there was enough
// space in the buffer for the data to be written, but it did * // space in the buffer for the data to be written, but it did
// successfully write xBytesSent bytes. * // successfully write xBytesSent bytes.
} * }
*
// Send the string to the stream buffer. Return immediately if there is not * // Send the string to the stream buffer. Return immediately if there is not
// enough space in the buffer. * // enough space in the buffer.
xBytesSent = xStreamBufferSend( xStreamBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 ); * xBytesSent = xStreamBufferSend( xStreamBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 );
*
if( xBytesSent != strlen( pcStringToSend ) ) * if( xBytesSent != strlen( pcStringToSend ) )
{ * {
// The entire string could not be added to the stream buffer because * // The entire string could not be added to the stream buffer because
// there was not enough free space in the buffer, but xBytesSent bytes * // there was not enough free space in the buffer, but xBytesSent bytes
// were sent. Could try again to send the remaining bytes. * // were sent. Could try again to send the remaining bytes.
} * }
} * }
</pre> * </pre>
* \defgroup xStreamBufferSend xStreamBufferSend * \defgroup xStreamBufferSend xStreamBufferSend
* \ingroup StreamBufferManagement * \ingroup StreamBufferManagement
*/ */
size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
const void *pvTxData, const void * pvTxData,
size_t xDataLengthBytes, size_t xDataLengthBytes,
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/** /**
* stream_buffer.h * stream_buffer.h
* *
<pre> * <pre>
size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, * size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
const void *pvTxData, * const void *pvTxData,
size_t xDataLengthBytes, * size_t xDataLengthBytes,
BaseType_t *pxHigherPriorityTaskWoken ); * BaseType_t *pxHigherPriorityTaskWoken );
</pre> * </pre>
* *
* Interrupt safe version of the API function that sends a stream of bytes to * Interrupt safe version of the API function that sends a stream of bytes to
* the stream buffer. * the stream buffer.
@ -373,56 +373,56 @@ size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
* space for all the bytes to be written. * space for all the bytes to be written.
* *
* Example use: * Example use:
<pre> * <pre>
// A stream buffer that has already been created. * // A stream buffer that has already been created.
StreamBufferHandle_t xStreamBuffer; * StreamBufferHandle_t xStreamBuffer;
*
void vAnInterruptServiceRoutine( void ) * void vAnInterruptServiceRoutine( void )
{ * {
size_t xBytesSent; * size_t xBytesSent;
char *pcStringToSend = "String to send"; * char *pcStringToSend = "String to send";
BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE. * BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
*
// Attempt to send the string to the stream buffer. * // Attempt to send the string to the stream buffer.
xBytesSent = xStreamBufferSendFromISR( xStreamBuffer, * xBytesSent = xStreamBufferSendFromISR( xStreamBuffer,
( void * ) pcStringToSend, * ( void * ) pcStringToSend,
strlen( pcStringToSend ), * strlen( pcStringToSend ),
&xHigherPriorityTaskWoken ); * &xHigherPriorityTaskWoken );
*
if( xBytesSent != strlen( pcStringToSend ) ) * if( xBytesSent != strlen( pcStringToSend ) )
{ * {
// There was not enough free space in the stream buffer for the entire * // There was not enough free space in the stream buffer for the entire
// string to be written, ut xBytesSent bytes were written. * // string to be written, ut xBytesSent bytes were written.
} * }
*
// If xHigherPriorityTaskWoken was set to pdTRUE inside * // If xHigherPriorityTaskWoken was set to pdTRUE inside
// xStreamBufferSendFromISR() then a task that has a priority above the * // xStreamBufferSendFromISR() then a task that has a priority above the
// priority of the currently executing task was unblocked and a context * // priority of the currently executing task was unblocked and a context
// switch should be performed to ensure the ISR returns to the unblocked * // switch should be performed to ensure the ISR returns to the unblocked
// task. In most FreeRTOS ports this is done by simply passing * // task. In most FreeRTOS ports this is done by simply passing
// xHigherPriorityTaskWoken into taskYIELD_FROM_ISR(), which will test the * // xHigherPriorityTaskWoken into taskYIELD_FROM_ISR(), which will test the
// variables value, and perform the context switch if necessary. Check the * // variables value, and perform the context switch if necessary. Check the
// documentation for the port in use for port specific instructions. * // documentation for the port in use for port specific instructions.
taskYIELD_FROM_ISR( xHigherPriorityTaskWoken ); * taskYIELD_FROM_ISR( xHigherPriorityTaskWoken );
} * }
</pre> * </pre>
* \defgroup xStreamBufferSendFromISR xStreamBufferSendFromISR * \defgroup xStreamBufferSendFromISR xStreamBufferSendFromISR
* \ingroup StreamBufferManagement * \ingroup StreamBufferManagement
*/ */
size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
const void *pvTxData, const void * pvTxData,
size_t xDataLengthBytes, size_t xDataLengthBytes,
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
/** /**
* stream_buffer.h * stream_buffer.h
* *
<pre> * <pre>
size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, * size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
void *pvRxData, * void *pvRxData,
size_t xBufferLengthBytes, * size_t xBufferLengthBytes,
TickType_t xTicksToWait ); * TickType_t xTicksToWait );
</pre> * </pre>
* *
* Receives bytes from a stream buffer. * Receives bytes from a stream buffer.
* *
@ -472,46 +472,46 @@ size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
* out before xBufferLengthBytes were available. * out before xBufferLengthBytes were available.
* *
* Example use: * Example use:
<pre> * <pre>
void vAFunction( StreamBuffer_t xStreamBuffer ) * void vAFunction( StreamBuffer_t xStreamBuffer )
{ * {
uint8_t ucRxData[ 20 ]; * uint8_t ucRxData[ 20 ];
size_t xReceivedBytes; * size_t xReceivedBytes;
const TickType_t xBlockTime = pdMS_TO_TICKS( 20 ); * const TickType_t xBlockTime = pdMS_TO_TICKS( 20 );
*
// Receive up to another sizeof( ucRxData ) bytes from the stream buffer. * // 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 * // 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 * // maximum of 100ms for the full sizeof( ucRxData ) number of bytes to be
// available. * // available.
xReceivedBytes = xStreamBufferReceive( xStreamBuffer, * xReceivedBytes = xStreamBufferReceive( xStreamBuffer,
( void * ) ucRxData, * ( void * ) ucRxData,
sizeof( ucRxData ), * sizeof( ucRxData ),
xBlockTime ); * xBlockTime );
*
if( xReceivedBytes > 0 ) * if( xReceivedBytes > 0 )
{ * {
// A ucRxData contains another xRecievedBytes bytes of data, which can * // A ucRxData contains another xRecievedBytes bytes of data, which can
// be processed here.... * // be processed here....
} * }
} * }
</pre> * </pre>
* \defgroup xStreamBufferReceive xStreamBufferReceive * \defgroup xStreamBufferReceive xStreamBufferReceive
* \ingroup StreamBufferManagement * \ingroup StreamBufferManagement
*/ */
size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
void *pvRxData, void * pvRxData,
size_t xBufferLengthBytes, size_t xBufferLengthBytes,
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/** /**
* stream_buffer.h * stream_buffer.h
* *
<pre> * <pre>
size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, * size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
void *pvRxData, * void *pvRxData,
size_t xBufferLengthBytes, * size_t xBufferLengthBytes,
BaseType_t *pxHigherPriorityTaskWoken ); * BaseType_t *pxHigherPriorityTaskWoken );
</pre> * </pre>
* *
* An interrupt safe version of the API function that receives bytes from a * An interrupt safe version of the API function that receives bytes from a
* stream buffer. * stream buffer.
@ -548,53 +548,53 @@ size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
* @return The number of bytes read from the stream buffer, if any. * @return The number of bytes read from the stream buffer, if any.
* *
* Example use: * Example use:
<pre> * <pre>
// A stream buffer that has already been created. * // A stream buffer that has already been created.
StreamBuffer_t xStreamBuffer; * StreamBuffer_t xStreamBuffer;
*
void vAnInterruptServiceRoutine( void ) * void vAnInterruptServiceRoutine( void )
{ * {
uint8_t ucRxData[ 20 ]; * uint8_t ucRxData[ 20 ];
size_t xReceivedBytes; * size_t xReceivedBytes;
BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE. * BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
*
// Receive the next stream from the stream buffer. * // Receive the next stream from the stream buffer.
xReceivedBytes = xStreamBufferReceiveFromISR( xStreamBuffer, * xReceivedBytes = xStreamBufferReceiveFromISR( xStreamBuffer,
( void * ) ucRxData, * ( void * ) ucRxData,
sizeof( ucRxData ), * sizeof( ucRxData ),
&xHigherPriorityTaskWoken ); * &xHigherPriorityTaskWoken );
*
if( xReceivedBytes > 0 ) * if( xReceivedBytes > 0 )
{ * {
// ucRxData contains xReceivedBytes read from the stream buffer. * // ucRxData contains xReceivedBytes read from the stream buffer.
// Process the stream here.... * // Process the stream here....
} * }
*
// If xHigherPriorityTaskWoken was set to pdTRUE inside * // If xHigherPriorityTaskWoken was set to pdTRUE inside
// xStreamBufferReceiveFromISR() then a task that has a priority above the * // xStreamBufferReceiveFromISR() then a task that has a priority above the
// priority of the currently executing task was unblocked and a context * // priority of the currently executing task was unblocked and a context
// switch should be performed to ensure the ISR returns to the unblocked * // switch should be performed to ensure the ISR returns to the unblocked
// task. In most FreeRTOS ports this is done by simply passing * // task. In most FreeRTOS ports this is done by simply passing
// xHigherPriorityTaskWoken into taskYIELD_FROM_ISR(), which will test the * // xHigherPriorityTaskWoken into taskYIELD_FROM_ISR(), which will test the
// variables value, and perform the context switch if necessary. Check the * // variables value, and perform the context switch if necessary. Check the
// documentation for the port in use for port specific instructions. * // documentation for the port in use for port specific instructions.
taskYIELD_FROM_ISR( xHigherPriorityTaskWoken ); * taskYIELD_FROM_ISR( xHigherPriorityTaskWoken );
} * }
</pre> * </pre>
* \defgroup xStreamBufferReceiveFromISR xStreamBufferReceiveFromISR * \defgroup xStreamBufferReceiveFromISR xStreamBufferReceiveFromISR
* \ingroup StreamBufferManagement * \ingroup StreamBufferManagement
*/ */
size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
void *pvRxData, void * pvRxData,
size_t xBufferLengthBytes, size_t xBufferLengthBytes,
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
/** /**
* stream_buffer.h * stream_buffer.h
* *
<pre> * <pre>
void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ); * void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer );
</pre> * </pre>
* *
* Deletes a stream buffer that was previously created using a call to * Deletes a stream buffer that was previously created using a call to
* xStreamBufferCreate() or xStreamBufferCreateStatic(). If the stream * xStreamBufferCreate() or xStreamBufferCreateStatic(). If the stream
@ -609,14 +609,14 @@ void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer );
* \defgroup vStreamBufferDelete vStreamBufferDelete * \defgroup vStreamBufferDelete vStreamBufferDelete
* \ingroup StreamBufferManagement * \ingroup StreamBufferManagement
*/ */
void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/** /**
* stream_buffer.h * stream_buffer.h
* *
<pre> * <pre>
BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ); * BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer );
</pre> * </pre>
* *
* Queries a stream buffer to see if it is full. A stream buffer is full if it * 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. * does not have any free space, and therefore cannot accept any more data.
@ -629,14 +629,14 @@ BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer );
* \defgroup xStreamBufferIsFull xStreamBufferIsFull * \defgroup xStreamBufferIsFull xStreamBufferIsFull
* \ingroup StreamBufferManagement * \ingroup StreamBufferManagement
*/ */
BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/** /**
* stream_buffer.h * stream_buffer.h
* *
<pre> * <pre>
BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ); * BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer );
</pre> * </pre>
* *
* Queries a stream buffer to see if it is empty. A stream buffer is empty if * Queries a stream buffer to see if it is empty. A stream buffer is empty if
* it does not contain any data. * it does not contain any data.
@ -649,14 +649,14 @@ BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer );
* \defgroup xStreamBufferIsEmpty xStreamBufferIsEmpty * \defgroup xStreamBufferIsEmpty xStreamBufferIsEmpty
* \ingroup StreamBufferManagement * \ingroup StreamBufferManagement
*/ */
BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/** /**
* stream_buffer.h * stream_buffer.h
* *
<pre> * <pre>
BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ); * BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer );
</pre> * </pre>
* *
* Resets a stream buffer to its initial, empty, state. Any data that was in * 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 * the stream buffer is discarded. A stream buffer can only be reset if there
@ -672,14 +672,14 @@ BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer );
* \defgroup xStreamBufferReset xStreamBufferReset * \defgroup xStreamBufferReset xStreamBufferReset
* \ingroup StreamBufferManagement * \ingroup StreamBufferManagement
*/ */
BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/** /**
* stream_buffer.h * stream_buffer.h
* *
<pre> * <pre>
size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ); * size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer );
</pre> * </pre>
* *
* Queries a stream buffer to see how much free space it contains, which is * 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 * equal to the amount of data that can be sent to the stream buffer before it
@ -693,14 +693,14 @@ size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer );
* \defgroup xStreamBufferSpacesAvailable xStreamBufferSpacesAvailable * \defgroup xStreamBufferSpacesAvailable xStreamBufferSpacesAvailable
* \ingroup StreamBufferManagement * \ingroup StreamBufferManagement
*/ */
size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/** /**
* stream_buffer.h * stream_buffer.h
* *
<pre> * <pre>
size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ); * size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer );
</pre> * </pre>
* *
* Queries a stream buffer to see how much data it contains, which is equal to * 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 * the number of bytes that can be read from the stream buffer before the stream
@ -714,14 +714,14 @@ size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer );
* \defgroup xStreamBufferBytesAvailable xStreamBufferBytesAvailable * \defgroup xStreamBufferBytesAvailable xStreamBufferBytesAvailable
* \ingroup StreamBufferManagement * \ingroup StreamBufferManagement
*/ */
size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/** /**
* stream_buffer.h * stream_buffer.h
* *
<pre> * <pre>
BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel ); * BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel );
</pre> * </pre>
* *
* A stream buffer's trigger level is the number of bytes that must be in the * 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 * stream buffer before a task that is blocked on the stream buffer to
@ -751,14 +751,15 @@ BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, siz
* \defgroup xStreamBufferSetTriggerLevel xStreamBufferSetTriggerLevel * \defgroup xStreamBufferSetTriggerLevel xStreamBufferSetTriggerLevel
* \ingroup StreamBufferManagement * \ingroup StreamBufferManagement
*/ */
BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel ) PRIVILEGED_FUNCTION; BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer,
size_t xTriggerLevel ) PRIVILEGED_FUNCTION;
/** /**
* stream_buffer.h * stream_buffer.h
* *
<pre> * <pre>
BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ); * BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
</pre> * </pre>
* *
* For advanced users only. * For advanced users only.
* *
@ -790,14 +791,15 @@ BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer
* \defgroup xStreamBufferSendCompletedFromISR xStreamBufferSendCompletedFromISR * \defgroup xStreamBufferSendCompletedFromISR xStreamBufferSendCompletedFromISR
* \ingroup StreamBufferManagement * \ingroup StreamBufferManagement
*/ */
BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
/** /**
* stream_buffer.h * stream_buffer.h
* *
<pre> * <pre>
BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ); * BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
</pre> * </pre>
* *
* For advanced users only. * For advanced users only.
* *
@ -830,29 +832,31 @@ BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuf
* \defgroup xStreamBufferReceiveCompletedFromISR xStreamBufferReceiveCompletedFromISR * \defgroup xStreamBufferReceiveCompletedFromISR xStreamBufferReceiveCompletedFromISR
* \ingroup StreamBufferManagement * \ingroup StreamBufferManagement
*/ */
BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
/* Functions below here are not part of the public API. */ /* Functions below here are not part of the public API. */
StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes, StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes, size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer ) PRIVILEGED_FUNCTION; BaseType_t xIsMessageBuffer ) PRIVILEGED_FUNCTION;
StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes, StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes, size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer, BaseType_t xIsMessageBuffer,
uint8_t * const pucStreamBufferStorageArea, uint8_t * const pucStreamBufferStorageArea,
StaticStreamBuffer_t * const pxStaticStreamBuffer ) PRIVILEGED_FUNCTION; StaticStreamBuffer_t * const pxStaticStreamBuffer ) PRIVILEGED_FUNCTION;
size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
#if( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer, UBaseType_t uxStreamBufferNumber ) PRIVILEGED_FUNCTION; void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer,
UBaseType_t uxStreamBufferNumber ) PRIVILEGED_FUNCTION;
UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
#endif #endif
#if defined( __cplusplus ) #if defined( __cplusplus )
} }
#endif #endif
#endif /* !defined( STREAM_BUFFER_H ) */ #endif /* !defined( STREAM_BUFFER_H ) */

File diff suppressed because it is too large Load diff

View file

@ -26,44 +26,44 @@
#ifndef TIMERS_H #ifndef TIMERS_H
#define TIMERS_H #define TIMERS_H
#ifndef INC_FREERTOS_H #ifndef INC_FREERTOS_H
#error "include FreeRTOS.h must appear in source files before include timers.h" #error "include FreeRTOS.h must appear in source files before include timers.h"
#endif #endif
/*lint -save -e537 This headers are only multiply included if the application code /*lint -save -e537 This headers are only multiply included if the application code
happens to also be including task.h. */ * happens to also be including task.h. */
#include "task.h" #include "task.h"
/*lint -restore */ /*lint -restore */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* MACROS AND DEFINITIONS * MACROS AND DEFINITIONS
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* IDs for commands that can be sent/received on the timer queue. These are to /* IDs for commands that can be sent/received on the timer queue. These are to
be used solely through the macros that make up the public software timer API, * be used solely through the macros that make up the public software timer API,
as defined below. The commands that are sent from interrupts must use the * as defined below. The commands that are sent from interrupts must use the
highest numbers as tmrFIRST_FROM_ISR_COMMAND is used to determine if the task * highest numbers as tmrFIRST_FROM_ISR_COMMAND is used to determine if the task
or interrupt version of the queue send function should be used. */ * or interrupt version of the queue send function should be used. */
#define tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR ( ( BaseType_t ) -2 ) #define tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR ( ( BaseType_t ) -2 )
#define tmrCOMMAND_EXECUTE_CALLBACK ( ( BaseType_t ) -1 ) #define tmrCOMMAND_EXECUTE_CALLBACK ( ( BaseType_t ) -1 )
#define tmrCOMMAND_START_DONT_TRACE ( ( BaseType_t ) 0 ) #define tmrCOMMAND_START_DONT_TRACE ( ( BaseType_t ) 0 )
#define tmrCOMMAND_START ( ( BaseType_t ) 1 ) #define tmrCOMMAND_START ( ( BaseType_t ) 1 )
#define tmrCOMMAND_RESET ( ( BaseType_t ) 2 ) #define tmrCOMMAND_RESET ( ( BaseType_t ) 2 )
#define tmrCOMMAND_STOP ( ( BaseType_t ) 3 ) #define tmrCOMMAND_STOP ( ( BaseType_t ) 3 )
#define tmrCOMMAND_CHANGE_PERIOD ( ( BaseType_t ) 4 ) #define tmrCOMMAND_CHANGE_PERIOD ( ( BaseType_t ) 4 )
#define tmrCOMMAND_DELETE ( ( BaseType_t ) 5 ) #define tmrCOMMAND_DELETE ( ( BaseType_t ) 5 )
#define tmrFIRST_FROM_ISR_COMMAND ( ( BaseType_t ) 6 ) #define tmrFIRST_FROM_ISR_COMMAND ( ( BaseType_t ) 6 )
#define tmrCOMMAND_START_FROM_ISR ( ( BaseType_t ) 6 ) #define tmrCOMMAND_START_FROM_ISR ( ( BaseType_t ) 6 )
#define tmrCOMMAND_RESET_FROM_ISR ( ( BaseType_t ) 7 ) #define tmrCOMMAND_RESET_FROM_ISR ( ( BaseType_t ) 7 )
#define tmrCOMMAND_STOP_FROM_ISR ( ( BaseType_t ) 8 ) #define tmrCOMMAND_STOP_FROM_ISR ( ( BaseType_t ) 8 )
#define tmrCOMMAND_CHANGE_PERIOD_FROM_ISR ( ( BaseType_t ) 9 ) #define tmrCOMMAND_CHANGE_PERIOD_FROM_ISR ( ( BaseType_t ) 9 )
/** /**
@ -72,19 +72,20 @@ or interrupt version of the queue send function should be used. */
* reference the subject timer in calls to other software timer API functions * reference the subject timer in calls to other software timer API functions
* (for example, xTimerStart(), xTimerReset(), etc.). * (for example, xTimerStart(), xTimerReset(), etc.).
*/ */
struct tmrTimerControl; /* The old naming convention is used to prevent breaking kernel aware debuggers. */ struct tmrTimerControl; /* The old naming convention is used to prevent breaking kernel aware debuggers. */
typedef struct tmrTimerControl * TimerHandle_t; typedef struct tmrTimerControl * TimerHandle_t;
/* /*
* Defines the prototype to which timer callback functions must conform. * Defines the prototype to which timer callback functions must conform.
*/ */
typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer ); typedef void (* TimerCallbackFunction_t)( TimerHandle_t xTimer );
/* /*
* Defines the prototype to which functions used with the * Defines the prototype to which functions used with the
* xTimerPendFunctionCallFromISR() function must conform. * xTimerPendFunctionCallFromISR() function must conform.
*/ */
typedef void (*PendedFunction_t)( void *, uint32_t ); typedef void (* PendedFunction_t)( void *,
uint32_t );
/** /**
* TimerHandle_t xTimerCreate( const char * const pcTimerName, * TimerHandle_t xTimerCreate( const char * const pcTimerName,
@ -223,13 +224,13 @@ typedef void (*PendedFunction_t)( void *, uint32_t );
* } * }
* @endverbatim * @endverbatim
*/ */
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
TimerHandle_t xTimerCreate( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ TimerHandle_t xTimerCreate( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const TickType_t xTimerPeriodInTicks, const TickType_t xTimerPeriodInTicks,
const UBaseType_t uxAutoReload, const UBaseType_t uxAutoReload,
void * const pvTimerID, void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION; TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION;
#endif #endif
/** /**
* TimerHandle_t xTimerCreateStatic(const char * const pcTimerName, * TimerHandle_t xTimerCreateStatic(const char * const pcTimerName,
@ -353,14 +354,14 @@ typedef void (*PendedFunction_t)( void *, uint32_t );
* } * }
* @endverbatim * @endverbatim
*/ */
#if( configSUPPORT_STATIC_ALLOCATION == 1 ) #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const TickType_t xTimerPeriodInTicks, const TickType_t xTimerPeriodInTicks,
const UBaseType_t uxAutoReload, const UBaseType_t uxAutoReload,
void * const pvTimerID, void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction, TimerCallbackFunction_t pxCallbackFunction,
StaticTimer_t *pxTimerBuffer ) PRIVILEGED_FUNCTION; StaticTimer_t * pxTimerBuffer ) PRIVILEGED_FUNCTION;
#endif /* configSUPPORT_STATIC_ALLOCATION */ #endif /* configSUPPORT_STATIC_ALLOCATION */
/** /**
* void *pvTimerGetTimerID( TimerHandle_t xTimer ); * void *pvTimerGetTimerID( TimerHandle_t xTimer );
@ -382,7 +383,7 @@ typedef void (*PendedFunction_t)( void *, uint32_t );
* *
* See the xTimerCreate() API function example usage scenario. * See the xTimerCreate() API function example usage scenario.
*/ */
void *pvTimerGetTimerID( const TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; void * pvTimerGetTimerID( const TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
/** /**
* void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ); * void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID );
@ -403,7 +404,8 @@ void *pvTimerGetTimerID( const TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
* *
* See the xTimerCreate() API function example usage scenario. * See the xTimerCreate() API function example usage scenario.
*/ */
void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ) PRIVILEGED_FUNCTION; void vTimerSetTimerID( TimerHandle_t xTimer,
void * pvNewID ) PRIVILEGED_FUNCTION;
/** /**
* BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ); * BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer );
@ -440,7 +442,7 @@ void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ) PRIVILEGED_FUNCTION
* } * }
* @endverbatim * @endverbatim
*/ */
BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
/** /**
* TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); * TaskHandle_t xTimerGetTimerDaemonTaskHandle( void );
@ -448,7 +450,7 @@ BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
* Simply returns the handle of the timer service/daemon task. It it not valid * Simply returns the handle of the timer service/daemon task. It it not valid
* to call xTimerGetTimerDaemonTaskHandle() before the scheduler has been started. * to call xTimerGetTimerDaemonTaskHandle() before the scheduler has been started.
*/ */
TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
/** /**
* BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait ); * BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait );
@ -500,7 +502,7 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* See the xTimerCreate() API function example usage scenario. * See the xTimerCreate() API function example usage scenario.
* *
*/ */
#define xTimerStart( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) #define xTimerStart( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) )
/** /**
* BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait ); * BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait );
@ -542,7 +544,7 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* See the xTimerCreate() API function example usage scenario. * See the xTimerCreate() API function example usage scenario.
* *
*/ */
#define xTimerStop( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) ) #define xTimerStop( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) )
/** /**
* BaseType_t xTimerChangePeriod( TimerHandle_t xTimer, * BaseType_t xTimerChangePeriod( TimerHandle_t xTimer,
@ -660,7 +662,7 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* *
* See the xTimerChangePeriod() API function example usage scenario. * See the xTimerChangePeriod() API function example usage scenario.
*/ */
#define xTimerDelete( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xTicksToWait ) ) #define xTimerDelete( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xTicksToWait ) )
/** /**
* BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait ); * BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait );
@ -784,7 +786,7 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* } * }
* @endverbatim * @endverbatim
*/ */
#define xTimerReset( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) #define xTimerReset( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) )
/** /**
* BaseType_t xTimerStartFromISR( TimerHandle_t xTimer, * BaseType_t xTimerStartFromISR( TimerHandle_t xTimer,
@ -870,7 +872,7 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* } * }
* @endverbatim * @endverbatim
*/ */
#define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) #define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U )
/** /**
* BaseType_t xTimerStopFromISR( TimerHandle_t xTimer, * BaseType_t xTimerStopFromISR( TimerHandle_t xTimer,
@ -933,7 +935,7 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* } * }
* @endverbatim * @endverbatim
*/ */
#define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP_FROM_ISR, 0, ( pxHigherPriorityTaskWoken ), 0U ) #define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP_FROM_ISR, 0, ( pxHigherPriorityTaskWoken ), 0U )
/** /**
* BaseType_t xTimerChangePeriodFromISR( TimerHandle_t xTimer, * BaseType_t xTimerChangePeriodFromISR( TimerHandle_t xTimer,
@ -1006,7 +1008,7 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* } * }
* @endverbatim * @endverbatim
*/ */
#define xTimerChangePeriodFromISR( xTimer, xNewPeriod, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD_FROM_ISR, ( xNewPeriod ), ( pxHigherPriorityTaskWoken ), 0U ) #define xTimerChangePeriodFromISR( xTimer, xNewPeriod, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD_FROM_ISR, ( xNewPeriod ), ( pxHigherPriorityTaskWoken ), 0U )
/** /**
* BaseType_t xTimerResetFromISR( TimerHandle_t xTimer, * BaseType_t xTimerResetFromISR( TimerHandle_t xTimer,
@ -1092,7 +1094,7 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* } * }
* @endverbatim * @endverbatim
*/ */
#define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) #define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U )
/** /**
@ -1183,9 +1185,12 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* } * }
* @endverbatim * @endverbatim
*/ */
BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend,
void * pvParameter1,
uint32_t ulParameter2,
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
/** /**
* BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, * BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend,
* void *pvParameter1, * void *pvParameter1,
* uint32_t ulParameter2, * uint32_t ulParameter2,
@ -1217,7 +1222,10 @@ BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void
* timer daemon task, otherwise pdFALSE is returned. * timer daemon task, otherwise pdFALSE is returned.
* *
*/ */
BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend,
void * pvParameter1,
uint32_t ulParameter2,
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/** /**
* const char * const pcTimerGetName( TimerHandle_t xTimer ); * const char * const pcTimerGetName( TimerHandle_t xTimer );
@ -1228,7 +1236,7 @@ BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvPar
* *
* @return The name assigned to the timer specified by the xTimer parameter. * @return The name assigned to the timer specified by the xTimer parameter.
*/ */
const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
/** /**
* void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload ); * void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload );
@ -1245,21 +1253,22 @@ const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*lint
* uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and * uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and
* enter the dormant state after it expires. * enter the dormant state after it expires.
*/ */
void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload ) PRIVILEGED_FUNCTION; void vTimerSetReloadMode( TimerHandle_t xTimer,
const UBaseType_t uxAutoReload ) PRIVILEGED_FUNCTION;
/** /**
* UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer ); * UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer );
* *
* Queries a timer to determine if it is an auto-reload timer, in which case the timer * Queries a timer to determine if it is an auto-reload timer, in which case the timer
* automatically resets itself each time it expires, or a one-shot timer, in * automatically resets itself each time it expires, or a one-shot timer, in
* which case the timer will only expire once unless it is manually restarted. * which case the timer will only expire once unless it is manually restarted.
* *
* @param xTimer The handle of the timer being queried. * @param xTimer The handle of the timer being queried.
* *
* @return If the timer is an auto-reload timer then pdTRUE is returned, otherwise * @return If the timer is an auto-reload timer then pdTRUE is returned, otherwise
* pdFALSE is returned. * pdFALSE is returned.
*/ */
UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
/** /**
* TickType_t xTimerGetPeriod( TimerHandle_t xTimer ); * TickType_t xTimerGetPeriod( TimerHandle_t xTimer );
@ -1270,39 +1279,41 @@ UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
* *
* @return The period of the timer in ticks. * @return The period of the timer in ticks.
*/ */
TickType_t xTimerGetPeriod( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; TickType_t xTimerGetPeriod( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
/** /**
* TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ); * TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer );
* *
* Returns the time in ticks at which the timer will expire. If this is less * Returns the time in ticks at which the timer will expire. If this is less
* than the current tick count then the expiry time has overflowed from the * than the current tick count then the expiry time has overflowed from the
* current time. * current time.
* *
* @param xTimer The handle of the timer being queried. * @param xTimer The handle of the timer being queried.
* *
* @return If the timer is running then the time in ticks at which the timer * @return If the timer is running then the time in ticks at which the timer
* will next expire is returned. If the timer is not running then the return * will next expire is returned. If the timer is not running then the return
* value is undefined. * value is undefined.
*/ */
TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
/* /*
* Functions beyond this part are not part of the public API and are intended * Functions beyond this part are not part of the public API and are intended
* for use by the kernel only. * for use by the kernel only.
*/ */
BaseType_t xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION; BaseType_t xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION;
BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; BaseType_t xTimerGenericCommand( TimerHandle_t xTimer,
const BaseType_t xCommandID,
const TickType_t xOptionalValue,
BaseType_t * const pxHigherPriorityTaskWoken,
const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
#if( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
void vTimerSetTimerNumber( TimerHandle_t xTimer, UBaseType_t uxTimerNumber ) PRIVILEGED_FUNCTION; void vTimerSetTimerNumber( TimerHandle_t xTimer,
UBaseType_t uxTimerNumber ) PRIVILEGED_FUNCTION;
UBaseType_t uxTimerGetTimerNumber( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; UBaseType_t uxTimerGetTimerNumber( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* TIMERS_H */ #endif /* TIMERS_H */

103
list.c
View file

@ -30,29 +30,29 @@
#include "list.h" #include "list.h"
/*----------------------------------------------------------- /*-----------------------------------------------------------
* PUBLIC LIST API documented in list.h * PUBLIC LIST API documented in list.h
*----------------------------------------------------------*/ *----------------------------------------------------------*/
void vListInitialise( List_t * const pxList ) void vListInitialise( List_t * const pxList )
{ {
/* The list structure contains a list item which is used to mark the /* 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 * end of the list. To initialise the list the list end is inserted
as the only list entry. */ * as the only list entry. */
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
/* The list end value is the highest possible value in the list to /* The list end value is the highest possible value in the list to
ensure it remains at the end of the list. */ * ensure it remains at the end of the list. */
pxList->xListEnd.xItemValue = portMAX_DELAY; pxList->xListEnd.xItemValue = portMAX_DELAY;
/* The list end next and previous pointers point to itself so we know /* The list end next and previous pointers point to itself so we know
when the list is empty. */ * when the list is empty. */
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
pxList->uxNumberOfItems = ( UBaseType_t ) 0U; pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
/* Write known values into the list if /* Write known values into the list if
configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ * configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ); listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ); listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
} }
@ -64,25 +64,26 @@ void vListInitialiseItem( ListItem_t * const pxItem )
pxItem->pxContainer = NULL; pxItem->pxContainer = NULL;
/* Write known values into the list item if /* Write known values into the list item if
configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ * configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) void vListInsertEnd( List_t * const pxList,
ListItem_t * const pxNewListItem )
{ {
ListItem_t * const pxIndex = pxList->pxIndex; ListItem_t * const pxIndex = pxList->pxIndex;
/* Only effective when configASSERT() is also defined, these tests may catch /* Only effective when configASSERT() is also defined, these tests may catch
the list data structures being overwritten in memory. They will not catch * the list data structures being overwritten in memory. They will not catch
data errors caused by incorrect configuration or use of FreeRTOS. */ * data errors caused by incorrect configuration or use of FreeRTOS. */
listTEST_LIST_INTEGRITY( pxList ); listTEST_LIST_INTEGRITY( pxList );
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
/* Insert a new list item into pxList, but rather than sort the list, /* 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 * makes the new list item the last item to be removed by a call to
listGET_OWNER_OF_NEXT_ENTRY(). */ * listGET_OWNER_OF_NEXT_ENTRY(). */
pxNewListItem->pxNext = pxIndex; pxNewListItem->pxNext = pxIndex;
pxNewListItem->pxPrevious = pxIndex->pxPrevious; pxNewListItem->pxPrevious = pxIndex->pxPrevious;
@ -99,25 +100,26 @@ ListItem_t * const pxIndex = pxList->pxIndex;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) void vListInsert( List_t * const pxList,
ListItem_t * const pxNewListItem )
{ {
ListItem_t *pxIterator; ListItem_t * pxIterator;
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
/* Only effective when configASSERT() is also defined, these tests may catch /* Only effective when configASSERT() is also defined, these tests may catch
the list data structures being overwritten in memory. They will not catch * the list data structures being overwritten in memory. They will not catch
data errors caused by incorrect configuration or use of FreeRTOS. */ * data errors caused by incorrect configuration or use of FreeRTOS. */
listTEST_LIST_INTEGRITY( pxList ); listTEST_LIST_INTEGRITY( pxList );
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
/* Insert the new list item into the list, sorted in xItemValue order. /* 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 * 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 * 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 * 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 * 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 * the iteration loop below will not end. Therefore the value is checked
first, and the algorithm slightly modified if necessary. */ * first, and the algorithm slightly modified if necessary. */
if( xValueOfInsertion == portMAX_DELAY ) if( xValueOfInsertion == portMAX_DELAY )
{ {
pxIterator = pxList->xListEnd.pxPrevious; pxIterator = pxList->xListEnd.pxPrevious;
@ -125,31 +127,31 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
else else
{ {
/* *** NOTE *********************************************************** /* *** NOTE ***********************************************************
If you find your application is crashing here then likely causes are * If you find your application is crashing here then likely causes are
listed below. In addition see https://www.freertos.org/FAQHelp.html for * listed below. In addition see https://www.freertos.org/FAQHelp.html for
more tips, and ensure configASSERT() is defined! * more tips, and ensure configASSERT() is defined!
https://www.freertos.org/a00110.html#configASSERT * https://www.freertos.org/a00110.html#configASSERT
*
1) Stack overflow - * 1) Stack overflow -
see https://www.freertos.org/Stacks-and-stack-overflow-checking.html * see https://www.freertos.org/Stacks-and-stack-overflow-checking.html
2) Incorrect interrupt priority assignment, especially on Cortex-M * 2) Incorrect interrupt priority assignment, especially on Cortex-M
parts where numerically high priority values denote low actual * parts where numerically high priority values denote low actual
interrupt priorities, which can seem counter intuitive. See * interrupt priorities, which can seem counter intuitive. See
https://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition * https://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition
of configMAX_SYSCALL_INTERRUPT_PRIORITY on * of configMAX_SYSCALL_INTERRUPT_PRIORITY on
https://www.freertos.org/a00110.html * https://www.freertos.org/a00110.html
3) Calling an API function from within a critical section or when * 3) Calling an API function from within a critical section or when
the scheduler is suspended, or calling an API function that does * the scheduler is suspended, or calling an API function that does
not end in "FromISR" from an interrupt. * not end in "FromISR" from an interrupt.
4) Using a queue or semaphore before it has been initialised or * 4) Using a queue or semaphore before it has been initialised or
before the scheduler has been started (are interrupts firing * before the scheduler has been started (are interrupts firing
before vTaskStartScheduler() has been called?). * before vTaskStartScheduler() has been called?).
**********************************************************************/ **********************************************************************/
for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. *//*lint !e440 The iterator moves to a different value, not xValueOfInsertion. */ for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. *//*lint !e440 The iterator moves to a different value, not xValueOfInsertion. */
{ {
/* There is nothing to do here, just iterating to the wanted /* There is nothing to do here, just iterating to the wanted
insertion position. */ * insertion position. */
} }
} }
@ -159,7 +161,7 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
pxIterator->pxNext = pxNewListItem; pxIterator->pxNext = pxNewListItem;
/* Remember which list the item is in. This allows fast removal of the /* Remember which list the item is in. This allows fast removal of the
item later. */ * item later. */
pxNewListItem->pxContainer = pxList; pxNewListItem->pxContainer = pxList;
( pxList->uxNumberOfItems )++; ( pxList->uxNumberOfItems )++;
@ -169,8 +171,8 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{ {
/* The list item knows which list it is in. Obtain the list from the list /* The list item knows which list it is in. Obtain the list from the list
item. */ * item. */
List_t * const pxList = pxItemToRemove->pxContainer; List_t * const pxList = pxItemToRemove->pxContainer;
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
@ -194,4 +196,3 @@ List_t * const pxList = pxItemToRemove->pxContainer;
return pxList->uxNumberOfItems; return pxList->uxNumberOfItems;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -39,7 +39,7 @@
/* Portasm includes. */ /* Portasm includes. */
#include "portasm.h" #include "portasm.h"
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/* Secure components includes. */ /* Secure components includes. */
#include "secure_context.h" #include "secure_context.h"
#include "secure_init.h" #include "secure_init.h"
@ -62,7 +62,7 @@
* 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support: * 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 * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0
*/ */
#if( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) ) #if ( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) )
#error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side. #error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side.
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -70,10 +70,10 @@
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) #define portNVIC_SYSPRI2_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) #define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) #define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) #define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
@ -85,7 +85,8 @@
/* Ensure the SysTick is clocked at the same frequency as the core. */ /* Ensure the SysTick is clocked at the same frequency as the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#else #else
/* The way the SysTick is clocked is not modified in case it is not the
/* The way the SysTick is clocked is not modified in case it is not the
* same a the core. */ * same a the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 0 ) #define portNVIC_SYSTICK_CLK_BIT ( 0 )
#endif #endif
@ -94,7 +95,7 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -117,24 +118,24 @@
/** /**
* @brief Constants required to manipulate the MPU. * @brief Constants required to manipulate the MPU.
*/ */
#define portMPU_TYPE_REG ( * ( ( volatile uint32_t * ) 0xe000ed90 ) ) #define portMPU_TYPE_REG ( *( ( volatile uint32_t * ) 0xe000ed90 ) )
#define portMPU_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed94 ) ) #define portMPU_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed94 ) )
#define portMPU_RNR_REG ( * ( ( volatile uint32_t * ) 0xe000ed98 ) ) #define portMPU_RNR_REG ( *( ( volatile uint32_t * ) 0xe000ed98 ) )
#define portMPU_RBAR_REG ( * ( ( volatile uint32_t * ) 0xe000ed9c ) ) #define portMPU_RBAR_REG ( *( ( volatile uint32_t * ) 0xe000ed9c ) )
#define portMPU_RLAR_REG ( * ( ( volatile uint32_t * ) 0xe000eda0 ) ) #define portMPU_RLAR_REG ( *( ( volatile uint32_t * ) 0xe000eda0 ) )
#define portMPU_RBAR_A1_REG ( * ( ( volatile uint32_t * ) 0xe000eda4 ) ) #define portMPU_RBAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda4 ) )
#define portMPU_RLAR_A1_REG ( * ( ( volatile uint32_t * ) 0xe000eda8 ) ) #define portMPU_RLAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda8 ) )
#define portMPU_RBAR_A2_REG ( * ( ( volatile uint32_t * ) 0xe000edac ) ) #define portMPU_RBAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edac ) )
#define portMPU_RLAR_A2_REG ( * ( ( volatile uint32_t * ) 0xe000edb0 ) ) #define portMPU_RLAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edb0 ) )
#define portMPU_RBAR_A3_REG ( * ( ( volatile uint32_t * ) 0xe000edb4 ) ) #define portMPU_RBAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb4 ) )
#define portMPU_RLAR_A3_REG ( * ( ( volatile uint32_t * ) 0xe000edb8 ) ) #define portMPU_RLAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb8 ) )
#define portMPU_MAIR0_REG ( * ( ( volatile uint32_t * ) 0xe000edc0 ) ) #define portMPU_MAIR0_REG ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
#define portMPU_MAIR1_REG ( * ( ( volatile uint32_t * ) 0xe000edc4 ) ) #define portMPU_MAIR1_REG ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */ #define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */ #define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
@ -204,8 +205,9 @@
*/ */
#define portINITIAL_XPSR ( 0x01000000 ) #define portINITIAL_XPSR ( 0x01000000 )
#if( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/**
/**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -221,7 +223,8 @@
*/ */
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/**
/**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -284,15 +287,17 @@
*/ */
static void prvTaskExitError( void ); static void prvTaskExitError( void );
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/**
/**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/**
/**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -337,7 +342,7 @@ void SysTick_Handler( void ) PRIVILEGED_FUNCTION;
/** /**
* @brief C part of SVC handler. * @brief C part of SVC handler.
*/ */
portDONT_DISCARD void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) PRIVILEGED_FUNCTION; portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIVILEGED_FUNCTION;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -346,27 +351,29 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) PRIVI
*/ */
static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/**
/**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
/**
/**
* @brief The number of SysTick increments that make up one tick period. * @brief The number of SysTick increments that make up one tick period.
*/ */
static uint32_t ulTimerCountsForOneTick = 0; static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
static uint32_t xMaximumPossibleSuppressedTicks = 0; static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -374,8 +381,8 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
__attribute__(( weak )) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{ {
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
TickType_t xModifiableIdleTime; TickType_t xModifiableIdleTime;
@ -396,6 +403,7 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
* tick periods. -1 is used because this code will execute part way * tick periods. -1 is used because this code will execute part way
* through one of the tick periods. */ * through one of the tick periods. */
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
if( ulReloadValue > ulStoppedTimerCompensation ) if( ulReloadValue > ulStoppedTimerCompensation )
{ {
ulReloadValue -= ulStoppedTimerCompensation; ulReloadValue -= ulStoppedTimerCompensation;
@ -403,9 +411,9 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
/* Enter a critical section but don't use the taskENTER_CRITICAL() /* Enter a critical section but don't use the taskENTER_CRITICAL()
* method as that will mask interrupts that should exit sleep mode. */ * method as that will mask interrupts that should exit sleep mode. */
__asm volatile( "cpsid i" ::: "memory" ); __asm volatile ( "cpsid i" ::: "memory" );
__asm volatile( "dsb" ); __asm volatile ( "dsb" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
/* If a context switch is pending or a task is waiting for the scheduler /* If a context switch is pending or a task is waiting for the scheduler
* to be un-suspended then abandon the low power entry. */ * to be un-suspended then abandon the low power entry. */
@ -424,7 +432,7 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
/* Re-enable interrupts - see comments above the cpsid instruction() /* Re-enable interrupts - see comments above the cpsid instruction()
* above. */ * above. */
__asm volatile( "cpsie i" ::: "memory" ); __asm volatile ( "cpsie i" ::: "memory" );
} }
else else
{ {
@ -446,28 +454,30 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
* so a copy is taken. */ * so a copy is taken. */
xModifiableIdleTime = xExpectedIdleTime; xModifiableIdleTime = xExpectedIdleTime;
configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
if( xModifiableIdleTime > 0 ) if( xModifiableIdleTime > 0 )
{ {
__asm volatile( "dsb" ::: "memory" ); __asm volatile ( "dsb" ::: "memory" );
__asm volatile( "wfi" ); __asm volatile ( "wfi" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
} }
configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
/* Re-enable interrupts to allow the interrupt that brought the MCU /* Re-enable interrupts to allow the interrupt that brought the MCU
* out of sleep mode to execute immediately. See comments above * out of sleep mode to execute immediately. See comments above
* the cpsid instruction above. */ * the cpsid instruction above. */
__asm volatile( "cpsie i" ::: "memory" ); __asm volatile ( "cpsie i" ::: "memory" );
__asm volatile( "dsb" ); __asm volatile ( "dsb" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
/* Disable interrupts again because the clock is about to be stopped /* Disable interrupts again because the clock is about to be stopped
* and interrupts that execute while the clock is stopped will * and interrupts that execute while the clock is stopped will
* increase any slippage between the time maintained by the RTOS and * increase any slippage between the time maintained by the RTOS and
* calendar time. */ * calendar time. */
__asm volatile( "cpsid i" ::: "memory" ); __asm volatile ( "cpsid i" ::: "memory" );
__asm volatile( "dsb" ); __asm volatile ( "dsb" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
/* Disable the SysTick clock without reading the /* Disable the SysTick clock without reading the
* portNVIC_SYSTICK_CTRL_REG register to ensure the * portNVIC_SYSTICK_CTRL_REG register to ensure the
@ -534,16 +544,16 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrupts enabled. */ /* Exit with interrupts enabled. */
__asm volatile( "cpsie i" ::: "memory" ); __asm volatile ( "cpsie i" ::: "memory" );
} }
} }
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
{ {
/* Calculate the constants required to configure the tick interrupt. */ /* Calculate the constants required to configure the tick interrupt. */
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
{ {
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
@ -563,7 +573,7 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNC
static void prvTaskExitError( void ) static void prvTaskExitError( void )
{ {
volatile uint32_t ulDummy = 0UL; volatile uint32_t ulDummy = 0UL;
/* A function that implements a task must not exit or attempt to return to /* 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 * its caller as there is nothing to return to. If a task wants to exit it
@ -586,10 +596,11 @@ volatile uint32_t ulDummy = 0UL;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */ static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */
{ {
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -600,7 +611,7 @@ volatile uint32_t ulDummy = 0UL;
extern uint32_t * __unprivileged_flash_end__; extern uint32_t * __unprivileged_flash_end__;
extern uint32_t * __privileged_sram_start__; extern uint32_t * __privileged_sram_start__;
extern uint32_t * __privileged_sram_end__; extern uint32_t * __privileged_sram_end__;
#else #else /* if defined( __ARMCC_VERSION ) */
/* Declaration when these variable are exported from linker scripts. */ /* Declaration when these variable are exported from linker scripts. */
extern uint32_t __privileged_functions_start__[]; extern uint32_t __privileged_functions_start__[];
extern uint32_t __privileged_functions_end__[]; extern uint32_t __privileged_functions_end__[];
@ -671,10 +682,10 @@ volatile uint32_t ulDummy = 0UL;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */ static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */
{ {
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
{ {
/* Enable non-secure access to the FPU. */ /* Enable non-secure access to the FPU. */
SecureInit_EnableNSFPUAccess(); SecureInit_EnableNSFPUAccess();
@ -703,8 +714,8 @@ void vPortYield( void ) /* PRIVILEGED_FUNCTION */
/* Barriers are normally not required but do ensure the code is /* Barriers are normally not required but do ensure the code is
* completely within the specified behaviour for the architecture. */ * completely within the specified behaviour for the architecture. */
__asm volatile( "dsb" ::: "memory" ); __asm volatile ( "dsb" ::: "memory" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -715,8 +726,8 @@ void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
/* Barriers are normally not required but do ensure the code is /* Barriers are normally not required but do ensure the code is
* completely within the specified behaviour for the architecture. */ * completely within the specified behaviour for the architecture. */
__asm volatile( "dsb" ::: "memory" ); __asm volatile ( "dsb" ::: "memory" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -734,7 +745,7 @@ void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */ void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
{ {
uint32_t ulPreviousMask; uint32_t ulPreviousMask;
ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
{ {
@ -749,10 +760,11 @@ uint32_t ulPreviousMask;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */
{ {
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -762,33 +774,33 @@ void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) /* PRIVILEGED_FUNCTION
extern uint32_t __syscalls_flash_start__[]; extern uint32_t __syscalls_flash_start__[];
extern uint32_t __syscalls_flash_end__[]; extern uint32_t __syscalls_flash_end__[];
#endif /* defined( __ARMCC_VERSION ) */ #endif /* defined( __ARMCC_VERSION ) */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
uint32_t ulPC; uint32_t ulPC;
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
uint32_t ulR0; uint32_t ulR0;
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
uint32_t ulControl, ulIsTaskPrivileged; uint32_t ulControl, ulIsTaskPrivileged;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
uint8_t ucSVCNumber; uint8_t ucSVCNumber;
/* Register are stored on the stack in the following order - R0, R1, R2, R3, /* Register are stored on the stack in the following order - R0, R1, R2, R3,
* R12, LR, PC, xPSR. */ * R12, LR, PC, xPSR. */
ulPC = pulCallerStackAddress[ 6 ]; ulPC = pulCallerStackAddress[ 6 ];
ucSVCNumber = ( ( uint8_t *) ulPC )[ -2 ]; ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ];
switch( ucSVCNumber ) switch( ucSVCNumber )
{ {
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
case portSVC_ALLOCATE_SECURE_CONTEXT: case portSVC_ALLOCATE_SECURE_CONTEXT:
{
/* R0 contains the stack size passed as parameter to the /* R0 contains the stack size passed as parameter to the
* vPortAllocateSecureContext function. */ * vPortAllocateSecureContext function. */
ulR0 = pulCallerStackAddress[ 0 ]; ulR0 = pulCallerStackAddress[ 0 ];
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
/* Read the CONTROL register value. */ /* Read the CONTROL register value. */
__asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
@ -800,7 +812,7 @@ uint8_t ucSVCNumber;
/* Allocate and load a context for the secure task. */ /* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged ); xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
} }
#else #else /* if ( configENABLE_MPU == 1 ) */
{ {
/* Allocate and load a context for the secure task. */ /* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0 ); xSecureContext = SecureContext_AllocateContext( ulR0 );
@ -809,23 +821,19 @@ uint8_t ucSVCNumber;
configASSERT( xSecureContext != NULL ); configASSERT( xSecureContext != NULL );
SecureContext_LoadContext( xSecureContext ); SecureContext_LoadContext( xSecureContext );
}
break; break;
case portSVC_FREE_SECURE_CONTEXT: case portSVC_FREE_SECURE_CONTEXT:
{
/* R0 contains the secure context handle to be freed. */ /* R0 contains the secure context handle to be freed. */
ulR0 = pulCallerStackAddress[ 0 ]; ulR0 = pulCallerStackAddress[ 0 ];
/* Free the secure context. */ /* Free the secure context. */
SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 ); SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 );
}
break; break;
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
case portSVC_START_SCHEDULER: case portSVC_START_SCHEDULER:
{ #if ( configENABLE_TRUSTZONE == 1 )
#if( configENABLE_TRUSTZONE == 1 )
{ {
/* De-prioritize the non-secure exceptions so that the /* De-prioritize the non-secure exceptions so that the
* non-secure pendSV runs at the lowest priority. */ * non-secure pendSV runs at the lowest priority. */
@ -836,7 +844,7 @@ uint8_t ucSVCNumber;
} }
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
#if( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
{ {
/* Setup the Floating Point Unit (FPU). */ /* Setup the Floating Point Unit (FPU). */
prvSetupFPU(); prvSetupFPU();
@ -846,41 +854,44 @@ uint8_t ucSVCNumber;
/* Setup the context of the first task so that the first task starts /* Setup the context of the first task so that the first task starts
* executing. */ * executing. */
vRestoreContextOfFirstTask(); vRestoreContextOfFirstTask();
}
break; break;
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
case portSVC_RAISE_PRIVILEGE: case portSVC_RAISE_PRIVILEGE:
{
/* Only raise the privilege, if the svc was raised from any of /* Only raise the privilege, if the svc was raised from any of
* the system calls. */ * the system calls. */
if( ulPC >= ( uint32_t ) __syscalls_flash_start__ && if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
ulPC <= ( uint32_t ) __syscalls_flash_end__ ) ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
{ {
vRaisePrivilege(); vRaisePrivilege();
} }
}
break; break;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
default: default:
{
/* Incorrect SVC call. */ /* Incorrect SVC call. */
configASSERT( pdFALSE ); configASSERT( pdFALSE );
} }
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
#else #else
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters ) /* PRIVILEGED_FUNCTION */ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters ) /* PRIVILEGED_FUNCTION */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
{ {
/* Simulate the stack frame as it would be created by a context switch /* Simulate the stack frame as it would be created by a context switch
* interrupt. */ * interrupt. */
#if( portPRELOAD_REGISTERS == 0 ) #if ( portPRELOAD_REGISTERS == 0 )
{ {
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */ *pxTopOfStack = portINITIAL_XPSR; /* xPSR */
@ -893,9 +904,10 @@ uint8_t ucSVCNumber;
pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */ pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
*pxTopOfStack = portINITIAL_EXC_RETURN; *pxTopOfStack = portINITIAL_EXC_RETURN;
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
pxTopOfStack--; pxTopOfStack--;
if( xRunPrivileged == pdTRUE ) if( xRunPrivileged == pdTRUE )
{ {
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */ *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
@ -910,7 +922,7 @@ uint8_t ucSVCNumber;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
{ {
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
@ -954,9 +966,10 @@ uint8_t ucSVCNumber;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */ *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
pxTopOfStack--; pxTopOfStack--;
if( xRunPrivileged == pdTRUE ) if( xRunPrivileged == pdTRUE )
{ {
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */ *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
@ -971,7 +984,7 @@ uint8_t ucSVCNumber;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
{ {
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
@ -990,7 +1003,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
/* Setup the Memory Protection Unit (MPU). */ /* Setup the Memory Protection Unit (MPU). */
prvSetupMPU(); prvSetupMPU();
@ -1029,8 +1042,11 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth ) void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
const struct xMEMORY_REGION * const xRegions,
StackType_t * pxBottomOfStack,
uint32_t ulStackDepth )
{ {
uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber; uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber;
int32_t lIndex = 0; int32_t lIndex = 0;
@ -1126,13 +1142,13 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xPortIsInsideInterrupt( void ) BaseType_t xPortIsInsideInterrupt( void )
{ {
uint32_t ulCurrentInterrupt; uint32_t ulCurrentInterrupt;
BaseType_t xReturn; BaseType_t xReturn;
/* Obtain the number of the currently executing interrupt. Interrupt Program /* Obtain the number of the currently executing interrupt. Interrupt Program
* Status Register (IPSR) holds the exception number of the currently-executing * Status Register (IPSR) holds the exception number of the currently-executing
* exception or zero for Thread mode.*/ * exception or zero for Thread mode.*/
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" ); __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" );
if( ulCurrentInterrupt == 0 ) if( ulCurrentInterrupt == 0 )
{ {

View file

@ -38,7 +38,7 @@
* header files. */ * header files. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#if( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0. #error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
#endif #endif
@ -48,80 +48,80 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst2 \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r3, [r2] \n" /* Read 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. */ " ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n" /* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r5, #1 \n" /* r5 = 1. */ " movs r5, #1 \n"/* r5 = 1. */
" bics r4, r5 \n" /* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */ " bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n" /* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ " 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 r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const2 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n" /* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n" /* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
" movs r5, #4 \n" /* r5 = 4. */ " movs r5, #4 \n"/* r5 = 4. */
" str r5, [r2] \n" /* Program RNR = 4. */ " str r5, [r2] \n"/* Program RNR = 4. */
" ldmia r3!, {r6,r7} \n" /* Read first set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst2 \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n" /* Write first set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
" movs r5, #5 \n" /* r5 = 5. */ " movs r5, #5 \n"/* r5 = 5. */
" str r5, [r2] \n" /* Program RNR = 5. */ " str r5, [r2] \n"/* Program RNR = 5. */
" ldmia r3!, {r6,r7} \n" /* Read second set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst2 \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n" /* Write second set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
" movs r5, #6 \n" /* r5 = 6. */ " movs r5, #6 \n"/* r5 = 6. */
" str r5, [r2] \n" /* Program RNR = 6. */ " str r5, [r2] \n"/* Program RNR = 6. */
" ldmia r3!, {r6,r7} \n" /* Read third set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst2 \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n" /* Write third set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
" movs r5, #7 \n" /* r5 = 7. */ " movs r5, #7 \n"/* r5 = 7. */
" str r5, [r2] \n" /* Program RNR = 7. */ " str r5, [r2] \n"/* Program RNR = 7. */
" ldmia r3!, {r6,r7} \n" /* Read fourth set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst2 \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n" /* Write fourth set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
" \n" " \n"
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r5, #1 \n" /* r5 = 1. */ " movs r5, #1 \n"/* r5 = 1. */
" orrs r4, r5 \n" /* r4 = r4 | r5 i.e. Set the bit 0 in r4. */ " orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n" /* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n" /* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r4} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */ " ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
" ldr r5, xSecureContextConst2 \n" " ldr r5, xSecureContextConst2 \n"
" str r1, [r5] \n" /* Set xSecureContext to this task's value for the same. */ " 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 psplim, r2 \n"/* Set this task's PSPLIM value. */
" msr control, r3 \n" /* Set this task's CONTROL value. */ " msr control, r3 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n" /* Discard everything up to r0. */ " 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. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r4 \n" /* Finally, branch to EXC_RETURN. */ " bx r4 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
" ldr r4, xSecureContextConst2 \n" " ldr r4, xSecureContextConst2 \n"
" str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */ " str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */
" msr psplim, r2 \n" /* Set this task's PSPLIM value. */ " msr psplim, r2 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n" /* r1 = 2. */ " movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */ " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n" /* Discard everything up to r0. */ " 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. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r3 \n" /* Finally, branch to EXC_RETURN. */ " bx r3 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
"xSecureContextConst2: .word xSecureContext \n" "xSecureContextConst2: .word xSecureContext \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n" "xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n" "xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n" "xRNRConst2: .word 0xe000ed98 \n"
@ -135,15 +135,15 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n" /* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" movs r1, #1 \n" /* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" tst r0, r1 \n" /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */ " tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
" beq running_privileged \n" /* If the result of previous AND operation was 0, branch. */ " beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */
" movs r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
" running_privileged: \n" " running_privileged: \n"
" movs r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ " movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
@ -155,11 +155,11 @@ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n" /* Read the CONTROL register. */ " mrs r0, control \n"/* Read the CONTROL register. */
" movs r1, #1 \n" /* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" bics r0, r1 \n" /* Clear the bit 0. */ " bics r0, r1 \n"/* Clear the bit 0. */
" msr control, r0 \n" /* Write back the new CONTROL value. */ " msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n" /* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
@ -169,12 +169,12 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n" /* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" movs r1, #1 \n" /* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" orrs r0, r1 \n" /* r0 = r0 | r1. */ " orrs r0, r1 \n"/* r0 = r0 | r1. */
" msr control, r0 \n" /* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n" /* Return to the caller. */ " bx lr \n"/* Return to the caller. */
:::"r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -183,19 +183,19 @@ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" ldr r0, xVTORConst \n" /* Use the NVIC offset register to locate the stack. */ " 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"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */ " 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. */ " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n" /* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n" /* System call to start the first task. */ " svc %0 \n"/* System call to start the first task. */
" nop \n" " nop \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n" "xVTORConst: .word 0xe000ed08 \n"
:: "i" ( portSVC_START_SCHEDULER ) : "memory" ::"i" ( portSVC_START_SCHEDULER ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -231,64 +231,64 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
" .extern SecureContext_SaveContext \n" " .extern SecureContext_SaveContext \n"
" .extern SecureContext_LoadContext \n" " .extern SecureContext_LoadContext \n"
" \n" " \n"
" mrs r1, psp \n" /* Read PSP in r1. */ " mrs r1, psp \n"/* Read PSP in r1. */
" ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ " 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. */ " ldr r0, [r2] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
" \n" " \n"
" cbz r0, save_ns_context \n" /* No secure context to save. */ " cbz r0, save_ns_context \n"/* No secure context to save. */
" push {r0-r2, r14} \n" " push {r0-r2, r14} \n"
" bl SecureContext_SaveContext \n" " bl SecureContext_SaveContext \n"
" pop {r0-r3} \n" /* LR is now in r3. */ " pop {r0-r3} \n"/* LR is now in r3. */
" mov lr, r3 \n" /* LR = 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. */ " 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. */ " 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 r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r2, [r3] \n" /* Read pxCurrentTCB. */ " ldr r2, [r3] \n"/* Read pxCurrentTCB. */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r1, r1, #16 \n" /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " 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. */ " str r1, [r2] \n"/* Save the new top of stack in TCB. */
" mrs r2, psplim \n" /* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mrs r3, control \n" /* r3 = CONTROL. */ " mrs r3, control \n"/* r3 = CONTROL. */
" mov r4, lr \n" /* r4 = LR/EXC_RETURN. */ " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
" stmia r1!, {r0, r2-r4} \n" /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " stmia r1!, {r0, r2-r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r1, r1, #12 \n" /* Make space for xSecureContext, PSPLIM and LR on the stack. */ " 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. */ " str r1, [r2] \n"/* Save the new top of stack in TCB. */
" mrs r2, psplim \n" /* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r1!, {r0, r2-r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */ " stmia r1!, {r0, r2-r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" b select_next_task \n" " b select_next_task \n"
" \n" " \n"
" save_ns_context: \n" " save_ns_context: \n"
" ldr r3, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r2, [r3] \n" /* Read pxCurrentTCB. */ " ldr r2, [r3] \n"/* Read pxCurrentTCB. */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r1, r1, #48 \n" /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */ " 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. */ " str r1, [r2] \n"/* Save the new top of stack in TCB. */
" adds r1, r1, #16 \n" /* r1 = r1 + 16. */ " adds r1, r1, #16 \n"/* r1 = r1 + 16. */
" stmia r1!, {r4-r7} \n" /* Store the low registers that are not saved automatically. */ " stmia r1!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */
" mov r4, r8 \n" /* r4 = r8. */ " mov r4, r8 \n"/* r4 = r8. */
" mov r5, r9 \n" /* r5 = r9. */ " mov r5, r9 \n"/* r5 = r9. */
" mov r6, r10 \n" /* r6 = r10. */ " mov r6, r10 \n"/* r6 = r10. */
" mov r7, r11 \n" /* r7 = r11. */ " mov r7, r11 \n"/* r7 = r11. */
" stmia r1!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */ " stmia r1!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
" mrs r2, psplim \n" /* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mrs r3, control \n" /* r3 = CONTROL. */ " mrs r3, control \n"/* r3 = CONTROL. */
" mov r4, lr \n" /* r4 = LR/EXC_RETURN. */ " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
" subs r1, r1, #48 \n" /* r1 = r1 - 48. */ " subs r1, r1, #48 \n"/* r1 = r1 - 48. */
" stmia r1!, {r0, r2-r4} \n" /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " stmia r1!, {r0, r2-r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r1, r1, #44 \n" /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ " 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. */ " str r1, [r2] \n"/* Save the new top of stack in TCB. */
" mrs r2, psplim \n" /* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r1!, {r0, r2-r7} \n" /* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */ " stmia r1!, {r0, r2-r7} \n"/* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */
" mov r4, r8 \n" /* r4 = r8. */ " mov r4, r8 \n"/* r4 = r8. */
" mov r5, r9 \n" /* r5 = r9. */ " mov r5, r9 \n"/* r5 = r9. */
" mov r6, r10 \n" /* r6 = r10. */ " mov r6, r10 \n"/* r6 = r10. */
" mov r7, r11 \n" /* r7 = r11. */ " mov r7, r11 \n"/* r7 = r11. */
" stmia r1!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */ " stmia r1!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
@ -296,102 +296,102 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" cpsie i \n" " cpsie i \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r3, [r2] \n" /* Read 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. */ " ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. r1 now points to the top of stack. */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n" /* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r5, #1 \n" /* r5 = 1. */ " movs r5, #1 \n"/* r5 = 1. */
" bics r4, r5 \n" /* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */ " bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n" /* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ " 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 r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n" /* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst \n" /* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
" movs r5, #4 \n" /* r5 = 4. */ " movs r5, #4 \n"/* r5 = 4. */
" str r5, [r2] \n" /* Program RNR = 4. */ " str r5, [r2] \n"/* Program RNR = 4. */
" ldmia r3!, {r6,r7} \n" /* Read first set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n" /* Write first set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
" movs r5, #5 \n" /* r5 = 5. */ " movs r5, #5 \n"/* r5 = 5. */
" str r5, [r2] \n" /* Program RNR = 5. */ " str r5, [r2] \n"/* Program RNR = 5. */
" ldmia r3!, {r6,r7} \n" /* Read second set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n" /* Write second set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
" movs r5, #6 \n" /* r5 = 6. */ " movs r5, #6 \n"/* r5 = 6. */
" str r5, [r2] \n" /* Program RNR = 6. */ " str r5, [r2] \n"/* Program RNR = 6. */
" ldmia r3!, {r6,r7} \n" /* Read third set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n" /* Write third set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
" movs r5, #7 \n" /* r5 = 7. */ " movs r5, #7 \n"/* r5 = 7. */
" str r5, [r2] \n" /* Program RNR = 7. */ " str r5, [r2] \n"/* Program RNR = 7. */
" ldmia r3!, {r6,r7} \n" /* Read fourth set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n" /* Write fourth set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
" \n" " \n"
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r5, #1 \n" /* r5 = 1. */ " movs r5, #1 \n"/* r5 = 1. */
" orrs r4, r5 \n" /* r4 = r4 | r5 i.e. Set the bit 0 in r4. */ " orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n" /* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n" /* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldmia r1!, {r0, r2-r4} \n" /* Read from stack - r0 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = LR. */ " 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 psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r3 \n" /* Restore the CONTROL register value for the task. */ " msr control, r3 \n"/* Restore the CONTROL register value for the task. */
" mov lr, r4 \n" /* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r2] \n" /* Restore the task's 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. */ " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
" push {r1,r4} \n" " push {r1,r4} \n"
" bl SecureContext_LoadContext \n" /* Restore the secure context. */ " bl SecureContext_LoadContext \n"/* Restore the secure context. */
" pop {r1,r4} \n" " pop {r1,r4} \n"
" mov lr, r4 \n" /* LR = r4. */ " 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. */ " 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. */ " 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. */ " msr psp, r1 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldmia r1!, {r0, r2-r3} \n" /* Read from stack - r0 = xSecureContext, r2 = PSPLIM and r3 = LR. */ " 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. */ " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
" mov lr, r3 \n" /* LR = r3. */ " mov lr, r3 \n"/* LR = r3. */
" ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r2] \n" /* Restore the task's 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. */ " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
" push {r1,r3} \n" " push {r1,r3} \n"
" bl SecureContext_LoadContext \n" /* Restore the secure context. */ " bl SecureContext_LoadContext \n"/* Restore the secure context. */
" pop {r1,r3} \n" " pop {r1,r3} \n"
" mov lr, r3 \n" /* LR = 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. */ " 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. */ " 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. */ " msr psp, r1 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" restore_ns_context: \n" " restore_ns_context: \n"
" adds r1, r1, #16 \n" /* Move to the high registers. */ " adds r1, r1, #16 \n"/* Move to the high registers. */
" ldmia r1!, {r4-r7} \n" /* Restore the high registers that are not automatically restored. */ " ldmia r1!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
" mov r8, r4 \n" /* r8 = r4. */ " mov r8, r4 \n"/* r8 = r4. */
" mov r9, r5 \n" /* r9 = r5. */ " mov r9, r5 \n"/* r9 = r5. */
" mov r10, r6 \n" /* r10 = r6. */ " mov r10, r6 \n"/* r10 = r6. */
" mov r11, r7 \n" /* r11 = r7. */ " mov r11, r7 \n"/* r11 = r7. */
" msr psp, r1 \n" /* Remember the new top of stack for the task. */ " msr psp, r1 \n"/* Remember the new top of stack for the task. */
" subs r1, r1, #32 \n" /* Go back to the low registers. */ " subs r1, r1, #32 \n"/* Go back to the low registers. */
" ldmia r1!, {r4-r7} \n" /* Restore the low registers that are not automatically restored. */ " ldmia r1!, {r4-r7} \n"/* Restore the low registers that are not automatically restored. */
" bx lr \n" " bx lr \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
"xSecureContextConst: .word xSecureContext \n" "xSecureContextConst: .word xSecureContext \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n" "xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n" "xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n" "xRNRConst: .word 0xe000ed98 \n"
@ -427,26 +427,26 @@ void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (
{ {
__asm volatile __asm volatile
( (
" svc %0 \n" /* Secure context is allocated in the supervisor call. */ " svc %0 \n"/* Secure context is allocated in the supervisor call. */
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
:: "i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory" ::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" ldr r1, [r0] \n" /* The first item in the TCB is the top of the stack. */ " 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. */ " 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. */ " cmp r0, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */
" beq free_secure_context \n" " beq free_secure_context \n"
" bx lr \n" /* There is no secure context (xSecureContext is NULL). */ " bx lr \n"/* There is no secure context (xSecureContext is NULL). */
" free_secure_context: \n" " free_secure_context: \n"
" svc %0 \n" /* Secure context is freed in the supervisor call. */ " svc %0 \n"/* Secure context is freed in the supervisor call. */
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
:: "i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory" ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -25,11 +25,11 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -41,109 +41,109 @@ extern "C" {
*------------------------------------------------------------------------------ *------------------------------------------------------------------------------
*/ */
#ifndef configENABLE_FPU #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. #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 */ #endif /* configENABLE_FPU */
#ifndef configENABLE_MPU #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. #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 */ #endif /* configENABLE_MPU */
#ifndef configENABLE_TRUSTZONE #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. #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 */ #endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Type definitions. * @brief Type definitions.
*/ */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 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. */ * not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* Architecture specifics. * Architecture specifics.
*/ */
#define portARCH_NAME "Cortex-M23" #define portARCH_NAME "Cortex-M23"
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portNOP() #define portNOP()
#define portINLINE __inline #define portINLINE __inline
#ifndef portFORCE_INLINE #ifndef portFORCE_INLINE
#define portFORCE_INLINE inline __attribute__(( always_inline )) #define portFORCE_INLINE inline __attribute__( ( always_inline ) )
#endif #endif
#define portHAS_STACK_OVERFLOW_CHECKING 1 #define portHAS_STACK_OVERFLOW_CHECKING 1
#define portDONT_DISCARD __attribute__(( used )) #define portDONT_DISCARD __attribute__( ( used ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Extern declarations. * @brief Extern declarations.
*/ */
extern BaseType_t xPortIsInsideInterrupt( void ); extern BaseType_t xPortIsInsideInterrupt( void );
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief MPU specific constants. * @brief MPU specific constants.
*/ */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
#define portUSING_MPU_WRAPPERS 1 #define portUSING_MPU_WRAPPERS 1
#define portPRIVILEGE_BIT ( 0x80000000UL ) #define portPRIVILEGE_BIT ( 0x80000000UL )
#else #else
#define portPRIVILEGE_BIT ( 0x0UL ) #define portPRIVILEGE_BIT ( 0x0UL )
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/* MPU regions. */ /* MPU regions. */
#define portPRIVILEGED_FLASH_REGION ( 0UL ) #define portPRIVILEGED_FLASH_REGION ( 0UL )
#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) #define portUNPRIVILEGED_FLASH_REGION ( 1UL )
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
#define portPRIVILEGED_RAM_REGION ( 3UL ) #define portPRIVILEGED_RAM_REGION ( 3UL )
#define portSTACK_REGION ( 4UL ) #define portSTACK_REGION ( 4UL )
#define portFIRST_CONFIGURABLE_REGION ( 5UL ) #define portFIRST_CONFIGURABLE_REGION ( 5UL )
#define portLAST_CONFIGURABLE_REGION ( 7UL ) #define portLAST_CONFIGURABLE_REGION ( 7UL )
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) #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 portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
/* Device memory attributes used in MPU_MAIR registers. /* Device memory attributes used in MPU_MAIR registers.
* *
@ -155,95 +155,96 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
* 11 --> Device-GRE * 11 --> Device-GRE
* Bit[1:0] - 00, Reserved. * Bit[1:0] - 00, Reserved.
*/ */
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
/* Normal memory attributes used in MPU_MAIR registers. */ /* Normal memory attributes used in MPU_MAIR registers. */
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ #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. */ #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
/* Attributes used in MPU_RBAR registers. */ /* Attributes used in MPU_RBAR registers. */
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) #define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) #define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) #define portMPU_REGION_EXECUTE_NEVER ( 1UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Settings to define an MPU region. * @brief Settings to define an MPU region.
*/ */
typedef struct MPURegionSettings typedef struct MPURegionSettings
{ {
uint32_t ulRBAR; /**< RBAR for the region. */ uint32_t ulRBAR; /**< RBAR for the region. */
uint32_t ulRLAR; /**< RLAR for the region. */ uint32_t ulRLAR; /**< RLAR for the region. */
} MPURegionSettings_t; } MPURegionSettings_t;
/** /**
* @brief MPU settings as stored in the TCB. * @brief MPU settings as stored in the TCB.
*/ */
typedef struct MPU_SETTINGS typedef struct MPU_SETTINGS
{ {
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ 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. */ MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
} xMPU_SETTINGS; } xMPU_SETTINGS;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief SVC numbers. * @brief SVC numbers.
*/ */
#define portSVC_ALLOCATE_SECURE_CONTEXT 0 #define portSVC_ALLOCATE_SECURE_CONTEXT 0
#define portSVC_FREE_SECURE_CONTEXT 1 #define portSVC_FREE_SECURE_CONTEXT 1
#define portSVC_START_SCHEDULER 2 #define portSVC_START_SCHEDULER 2
#define portSVC_RAISE_PRIVILEGE 3 #define portSVC_RAISE_PRIVILEGE 3
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Scheduler utilities. * @brief Scheduler utilities.
*/ */
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Critical section management. * @brief Critical section management.
*/ */
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMask( x ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) #define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) #define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Tickless idle/low power functionality. * @brief Tickless idle/low power functionality.
*/ */
#ifndef portSUPPRESS_TICKS_AND_SLEEP #ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Task function macros as described on the FreeRTOS.org WEB site. * @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_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/**
/**
* @brief Allocate a secure context for the task. * @brief Allocate a secure context for the task.
* *
* Tasks are not created with a secure context. Any task that is going to call * Tasks are not created with a secure context. Any task that is going to call
@ -254,56 +255,57 @@ typedef struct MPU_SETTINGS
*/ */
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
/** /**
* @brief Called when a task is deleted to delete the task's secure context, * @brief Called when a task is deleted to delete the task's secure context,
* if it has one. * if it has one.
* *
* @param[in] pxTCB The TCB of the task being deleted. * @param[in] pxTCB The TCB of the task being deleted.
*/ */
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
#else #else
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
#define portCLEAN_UP_TCB( pxTCB ) #define portCLEAN_UP_TCB( pxTCB )
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/**
/**
* @brief Checks whether or not the processor is privileged. * @brief Checks whether or not the processor is privileged.
* *
* @return 1 if the processor is already privileged, 0 otherwise. * @return 1 if the processor is already privileged, 0 otherwise.
*/ */
#define portIS_PRIVILEGED() xIsPrivileged() #define portIS_PRIVILEGED() xIsPrivileged()
/** /**
* @brief Raise an SVC request to raise privilege. * @brief Raise an SVC request to raise privilege.
* *
* The SVC handler checks that the SVC was raised from a system call and only * 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, * then it raises the privilege. If this is called from any other place,
* the privilege is not raised. * the privilege is not raised.
*/ */
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); #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 * @brief Lowers the privilege level by setting the bit 0 of the CONTROL
* register. * register.
*/ */
#define portRESET_PRIVILEGE() vResetPrivilege() #define portRESET_PRIVILEGE() vResetPrivilege()
#else #else
#define portIS_PRIVILEGED() #define portIS_PRIVILEGED()
#define portRAISE_PRIVILEGE() #define portRAISE_PRIVILEGE()
#define portRESET_PRIVILEGE() #define portRESET_PRIVILEGE()
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Barriers. * @brief Barriers.
*/ */
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -38,7 +38,7 @@
* header files. */ * header files. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#if( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0. #error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
#endif #endif
@ -48,75 +48,75 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst2 \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n" /* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r4, #1 \n" /* r4 = 1. */ " movs r4, #1 \n"/* r4 = 1. */
" bics r3, r4 \n" /* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */ " bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
" str r3, [r2] \n" /* Disable MPU. */ " str r3, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r4, [r1] \n" /* r4 = *r1 i.e. r4 = MAIR0. */ " ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const2 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n" /* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n" /* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" movs r4, #4 \n" /* r4 = 4. */ " movs r4, #4 \n"/* r4 = 4. */
" str r4, [r2] \n" /* Program RNR = 4. */ " str r4, [r2] \n"/* Program RNR = 4. */
" ldmia r1!, {r5,r6} \n" /* Read first set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst2 \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n" /* Write first set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */
" movs r4, #5 \n" /* r4 = 5. */ " movs r4, #5 \n"/* r4 = 5. */
" str r4, [r2] \n" /* Program RNR = 5. */ " str r4, [r2] \n"/* Program RNR = 5. */
" ldmia r1!, {r5,r6} \n" /* Read second set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst2 \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n" /* Write second set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */
" movs r4, #6 \n" /* r4 = 6. */ " movs r4, #6 \n"/* r4 = 6. */
" str r4, [r2] \n" /* Program RNR = 6. */ " str r4, [r2] \n"/* Program RNR = 6. */
" ldmia r1!, {r5,r6} \n" /* Read third set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst2 \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n" /* Write third set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */
" movs r4, #7 \n" /* r4 = 7. */ " movs r4, #7 \n"/* r4 = 7. */
" str r4, [r2] \n" /* Program RNR = 7. */ " str r4, [r2] \n"/* Program RNR = 7. */
" ldmia r1!, {r5,r6} \n" /* Read fourth set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst2 \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n" /* Write fourth set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */
" \n" " \n"
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r4, #1 \n" /* r4 = 1. */ " movs r4, #1 \n"/* r4 = 1. */
" orrs r3, r4 \n" /* r3 = r3 | r4 i.e. Set the bit 0 in r3. */ " orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
" str r3, [r2] \n" /* Enable MPU. */ " str r3, [r2] \n"/* Enable MPU. */
" dsb \n" /* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */ " msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" msr control, r2 \n" /* Set this task's CONTROL value. */ " msr control, r2 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n" /* Discard everything up to r0. */ " 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. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r3 \n" /* Finally, branch to EXC_RETURN. */ " bx r3 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ " ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */ " msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n" /* r1 = 2. */ " movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */ " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n" /* Discard everything up to r0. */ " 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. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r2 \n" /* Finally, branch to EXC_RETURN. */ " bx r2 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n" "xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n" "xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n" "xRNRConst2: .word 0xe000ed98 \n"
@ -130,15 +130,15 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n" /* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" movs r1, #1 \n" /* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" tst r0, r1 \n" /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */ " tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
" beq running_privileged \n" /* If the result of previous AND operation was 0, branch. */ " beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */
" movs r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
" running_privileged: \n" " running_privileged: \n"
" movs r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ " movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
@ -150,11 +150,11 @@ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n" /* Read the CONTROL register. */ " mrs r0, control \n"/* Read the CONTROL register. */
" movs r1, #1 \n" /* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" bics r0, r1 \n" /* Clear the bit 0. */ " bics r0, r1 \n"/* Clear the bit 0. */
" msr control, r0 \n" /* Write back the new CONTROL value. */ " msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n" /* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
@ -164,12 +164,12 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n" /* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" movs r1, #1 \n" /* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" orrs r0, r1 \n" /* r0 = r0 | r1. */ " orrs r0, r1 \n"/* r0 = r0 | r1. */
" msr control, r0 \n" /* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n" /* Return to the caller. */ " bx lr \n"/* Return to the caller. */
:::"r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -178,19 +178,19 @@ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" ldr r0, xVTORConst \n" /* Use the NVIC offset register to locate the stack. */ " 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"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */ " 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. */ " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n" /* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n" /* System call to start the first task. */ " svc %0 \n"/* System call to start the first task. */
" nop \n" " nop \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n" "xVTORConst: .word 0xe000ed08 \n"
:: "i" ( portSVC_START_SCHEDULER ) : "memory" ::"i" ( portSVC_START_SCHEDULER ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -224,115 +224,115 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, psp \n" /* Read PSP in r0. */ " mrs r0, psp \n"/* Read PSP in r0. */
" ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r0, r0, #44 \n" /* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */ " subs r0, r0, #44 \n"/* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */
" str r0, [r1] \n" /* Save the new top of stack in TCB. */ " str r0, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r1, psplim \n" /* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r2, control \n" /* r2 = CONTROL. */ " mrs r2, control \n"/* r2 = CONTROL. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r0!, {r1-r7} \n" /* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */ " stmia r0!, {r1-r7} \n"/* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */
" mov r4, r8 \n" /* r4 = r8. */ " mov r4, r8 \n"/* r4 = r8. */
" mov r5, r9 \n" /* r5 = r9. */ " mov r5, r9 \n"/* r5 = r9. */
" mov r6, r10 \n" /* r6 = r10. */ " mov r6, r10 \n"/* r6 = r10. */
" mov r7, r11 \n" /* r7 = r11. */ " mov r7, r11 \n"/* r7 = r11. */
" stmia r0!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */ " stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r0, r0, #40 \n" /* Make space for PSPLIM, LR and the remaining registers on the stack. */ " subs r0, r0, #40 \n"/* Make space for PSPLIM, LR and the remaining registers on the stack. */
" str r0, [r1] \n" /* Save the new top of stack in TCB. */ " str r0, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r2, psplim \n" /* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r0!, {r2-r7} \n" /* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */ " stmia r0!, {r2-r7} \n"/* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */
" mov r4, r8 \n" /* r4 = r8. */ " mov r4, r8 \n"/* r4 = r8. */
" mov r5, r9 \n" /* r5 = r9. */ " mov r5, r9 \n"/* r5 = r9. */
" mov r6, r10 \n" /* r6 = r10. */ " mov r6, r10 \n"/* r6 = r10. */
" mov r7, r11 \n" /* r7 = r11. */ " mov r7, r11 \n"/* r7 = r11. */
" stmia r0!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */ " stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" cpsid i \n" " cpsid i \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" cpsie i \n" " cpsie i \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n" /* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r4, #1 \n" /* r4 = 1. */ " movs r4, #1 \n"/* r4 = 1. */
" bics r3, r4 \n" /* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */ " bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
" str r3, [r2] \n" /* Disable MPU. */ " str r3, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r4, [r1] \n" /* r4 = *r1 i.e. r4 = MAIR0. */ " ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n" /* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst \n" /* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" movs r4, #4 \n" /* r4 = 4. */ " movs r4, #4 \n"/* r4 = 4. */
" str r4, [r2] \n" /* Program RNR = 4. */ " str r4, [r2] \n"/* Program RNR = 4. */
" ldmia r1!, {r5,r6} \n" /* Read first set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n" /* Write first set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */
" movs r4, #5 \n" /* r4 = 5. */ " movs r4, #5 \n"/* r4 = 5. */
" str r4, [r2] \n" /* Program RNR = 5. */ " str r4, [r2] \n"/* Program RNR = 5. */
" ldmia r1!, {r5,r6} \n" /* Read second set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n" /* Write second set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */
" movs r4, #6 \n" /* r4 = 6. */ " movs r4, #6 \n"/* r4 = 6. */
" str r4, [r2] \n" /* Program RNR = 6. */ " str r4, [r2] \n"/* Program RNR = 6. */
" ldmia r1!, {r5,r6} \n" /* Read third set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n" /* Write third set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */
" movs r4, #7 \n" /* r4 = 7. */ " movs r4, #7 \n"/* r4 = 7. */
" str r4, [r2] \n" /* Program RNR = 7. */ " str r4, [r2] \n"/* Program RNR = 7. */
" ldmia r1!, {r5,r6} \n" /* Read fourth set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n" /* Write fourth set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */
" \n" " \n"
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r4, #1 \n" /* r4 = 1. */ " movs r4, #1 \n"/* r4 = 1. */
" orrs r3, r4 \n" /* r3 = r3 | r4 i.e. Set the bit 0 in r3. */ " orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
" str r3, [r2] \n" /* Enable MPU. */ " str r3, [r2] \n"/* Enable MPU. */
" dsb \n" /* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" adds r0, r0, #28 \n" /* Move to the high registers. */ " adds r0, r0, #28 \n"/* Move to the high registers. */
" ldmia r0!, {r4-r7} \n" /* Restore the high registers that are not automatically restored. */ " ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
" mov r8, r4 \n" /* r8 = r4. */ " mov r8, r4 \n"/* r8 = r4. */
" mov r9, r5 \n" /* r9 = r5. */ " mov r9, r5 \n"/* r9 = r5. */
" mov r10, r6 \n" /* r10 = r6. */ " mov r10, r6 \n"/* r10 = r6. */
" mov r11, r7 \n" /* r11 = r7. */ " mov r11, r7 \n"/* r11 = r7. */
" msr psp, r0 \n" /* Remember the new top of stack for the task. */ " msr psp, r0 \n"/* Remember the new top of stack for the task. */
" subs r0, r0, #44 \n" /* Move to the starting of the saved context. */ " subs r0, r0, #44 \n"/* Move to the starting of the saved context. */
" ldmia r0!, {r1-r7} \n" /* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */ " ldmia r0!, {r1-r7} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */
" msr psplim, r1 \n" /* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r2 \n" /* Restore the CONTROL register value for the task. */ " msr control, r2 \n"/* Restore the CONTROL register value for the task. */
" bx r3 \n" " bx r3 \n"
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" adds r0, r0, #24 \n" /* Move to the high registers. */ " adds r0, r0, #24 \n"/* Move to the high registers. */
" ldmia r0!, {r4-r7} \n" /* Restore the high registers that are not automatically restored. */ " ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
" mov r8, r4 \n" /* r8 = r4. */ " mov r8, r4 \n"/* r8 = r4. */
" mov r9, r5 \n" /* r9 = r5. */ " mov r9, r5 \n"/* r9 = r5. */
" mov r10, r6 \n" /* r10 = r6. */ " mov r10, r6 \n"/* r10 = r6. */
" mov r11, r7 \n" /* r11 = r7. */ " mov r11, r7 \n"/* r11 = r7. */
" msr psp, r0 \n" /* Remember the new top of stack for the task. */ " msr psp, r0 \n"/* Remember the new top of stack for the task. */
" subs r0, r0, #40 \n" /* Move to the starting of the saved context. */ " subs r0, r0, #40 \n"/* Move to the starting of the saved context. */
" ldmia r0!, {r2-r7} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */ " ldmia r0!, {r2-r7} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */
" msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */ " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
" bx r3 \n" " bx r3 \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n" "xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n" "xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n" "xRNRConst: .word 0xe000ed98 \n"

View file

@ -25,11 +25,11 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -41,109 +41,109 @@ extern "C" {
*------------------------------------------------------------------------------ *------------------------------------------------------------------------------
*/ */
#ifndef configENABLE_FPU #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. #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 */ #endif /* configENABLE_FPU */
#ifndef configENABLE_MPU #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. #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 */ #endif /* configENABLE_MPU */
#ifndef configENABLE_TRUSTZONE #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. #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 */ #endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Type definitions. * @brief Type definitions.
*/ */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 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. */ * not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* Architecture specifics. * Architecture specifics.
*/ */
#define portARCH_NAME "Cortex-M23" #define portARCH_NAME "Cortex-M23"
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portNOP() #define portNOP()
#define portINLINE __inline #define portINLINE __inline
#ifndef portFORCE_INLINE #ifndef portFORCE_INLINE
#define portFORCE_INLINE inline __attribute__(( always_inline )) #define portFORCE_INLINE inline __attribute__( ( always_inline ) )
#endif #endif
#define portHAS_STACK_OVERFLOW_CHECKING 1 #define portHAS_STACK_OVERFLOW_CHECKING 1
#define portDONT_DISCARD __attribute__(( used )) #define portDONT_DISCARD __attribute__( ( used ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Extern declarations. * @brief Extern declarations.
*/ */
extern BaseType_t xPortIsInsideInterrupt( void ); extern BaseType_t xPortIsInsideInterrupt( void );
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief MPU specific constants. * @brief MPU specific constants.
*/ */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
#define portUSING_MPU_WRAPPERS 1 #define portUSING_MPU_WRAPPERS 1
#define portPRIVILEGE_BIT ( 0x80000000UL ) #define portPRIVILEGE_BIT ( 0x80000000UL )
#else #else
#define portPRIVILEGE_BIT ( 0x0UL ) #define portPRIVILEGE_BIT ( 0x0UL )
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/* MPU regions. */ /* MPU regions. */
#define portPRIVILEGED_FLASH_REGION ( 0UL ) #define portPRIVILEGED_FLASH_REGION ( 0UL )
#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) #define portUNPRIVILEGED_FLASH_REGION ( 1UL )
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
#define portPRIVILEGED_RAM_REGION ( 3UL ) #define portPRIVILEGED_RAM_REGION ( 3UL )
#define portSTACK_REGION ( 4UL ) #define portSTACK_REGION ( 4UL )
#define portFIRST_CONFIGURABLE_REGION ( 5UL ) #define portFIRST_CONFIGURABLE_REGION ( 5UL )
#define portLAST_CONFIGURABLE_REGION ( 7UL ) #define portLAST_CONFIGURABLE_REGION ( 7UL )
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) #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 portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
/* Device memory attributes used in MPU_MAIR registers. /* Device memory attributes used in MPU_MAIR registers.
* *
@ -155,95 +155,96 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
* 11 --> Device-GRE * 11 --> Device-GRE
* Bit[1:0] - 00, Reserved. * Bit[1:0] - 00, Reserved.
*/ */
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
/* Normal memory attributes used in MPU_MAIR registers. */ /* Normal memory attributes used in MPU_MAIR registers. */
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ #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. */ #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
/* Attributes used in MPU_RBAR registers. */ /* Attributes used in MPU_RBAR registers. */
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) #define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) #define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) #define portMPU_REGION_EXECUTE_NEVER ( 1UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Settings to define an MPU region. * @brief Settings to define an MPU region.
*/ */
typedef struct MPURegionSettings typedef struct MPURegionSettings
{ {
uint32_t ulRBAR; /**< RBAR for the region. */ uint32_t ulRBAR; /**< RBAR for the region. */
uint32_t ulRLAR; /**< RLAR for the region. */ uint32_t ulRLAR; /**< RLAR for the region. */
} MPURegionSettings_t; } MPURegionSettings_t;
/** /**
* @brief MPU settings as stored in the TCB. * @brief MPU settings as stored in the TCB.
*/ */
typedef struct MPU_SETTINGS typedef struct MPU_SETTINGS
{ {
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ 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. */ MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
} xMPU_SETTINGS; } xMPU_SETTINGS;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief SVC numbers. * @brief SVC numbers.
*/ */
#define portSVC_ALLOCATE_SECURE_CONTEXT 0 #define portSVC_ALLOCATE_SECURE_CONTEXT 0
#define portSVC_FREE_SECURE_CONTEXT 1 #define portSVC_FREE_SECURE_CONTEXT 1
#define portSVC_START_SCHEDULER 2 #define portSVC_START_SCHEDULER 2
#define portSVC_RAISE_PRIVILEGE 3 #define portSVC_RAISE_PRIVILEGE 3
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Scheduler utilities. * @brief Scheduler utilities.
*/ */
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Critical section management. * @brief Critical section management.
*/ */
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMask( x ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) #define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) #define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Tickless idle/low power functionality. * @brief Tickless idle/low power functionality.
*/ */
#ifndef portSUPPRESS_TICKS_AND_SLEEP #ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Task function macros as described on the FreeRTOS.org WEB site. * @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_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/**
/**
* @brief Allocate a secure context for the task. * @brief Allocate a secure context for the task.
* *
* Tasks are not created with a secure context. Any task that is going to call * Tasks are not created with a secure context. Any task that is going to call
@ -254,56 +255,57 @@ typedef struct MPU_SETTINGS
*/ */
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
/** /**
* @brief Called when a task is deleted to delete the task's secure context, * @brief Called when a task is deleted to delete the task's secure context,
* if it has one. * if it has one.
* *
* @param[in] pxTCB The TCB of the task being deleted. * @param[in] pxTCB The TCB of the task being deleted.
*/ */
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
#else #else
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
#define portCLEAN_UP_TCB( pxTCB ) #define portCLEAN_UP_TCB( pxTCB )
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/**
/**
* @brief Checks whether or not the processor is privileged. * @brief Checks whether or not the processor is privileged.
* *
* @return 1 if the processor is already privileged, 0 otherwise. * @return 1 if the processor is already privileged, 0 otherwise.
*/ */
#define portIS_PRIVILEGED() xIsPrivileged() #define portIS_PRIVILEGED() xIsPrivileged()
/** /**
* @brief Raise an SVC request to raise privilege. * @brief Raise an SVC request to raise privilege.
* *
* The SVC handler checks that the SVC was raised from a system call and only * 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, * then it raises the privilege. If this is called from any other place,
* the privilege is not raised. * the privilege is not raised.
*/ */
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); #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 * @brief Lowers the privilege level by setting the bit 0 of the CONTROL
* register. * register.
*/ */
#define portRESET_PRIVILEGE() vResetPrivilege() #define portRESET_PRIVILEGE() vResetPrivilege()
#else #else
#define portIS_PRIVILEGED() #define portIS_PRIVILEGED()
#define portRAISE_PRIVILEGE() #define portRAISE_PRIVILEGE()
#define portRESET_PRIVILEGE() #define portRESET_PRIVILEGE()
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Barriers. * @brief Barriers.
*/ */
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -44,63 +44,63 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst2 \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r3, [r2] \n" /* Read 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. */ " ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n" /* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n" /* Read the value 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. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n" /* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ " 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 r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const2 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n" /* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n" /* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r4, #4 \n" /* r4 = 4. */ " movs r4, #4 \n"/* r4 = 4. */
" str r4, [r2] \n" /* Program RNR = 4. */ " str r4, [r2] \n"/* Program RNR = 4. */
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
" ldr r2, xRBARConst2 \n" /* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r3!, {r4-r11} \n" /* Read 4 set of RBAR/RLAR registers from TCB. */ " 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. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n" /* Read the value 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. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n" /* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n" /* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r4} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */ " ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
" ldr r5, xSecureContextConst2 \n" " ldr r5, xSecureContextConst2 \n"
" str r1, [r5] \n" /* Set xSecureContext to this task's value for the same. */ " 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 psplim, r2 \n"/* Set this task's PSPLIM value. */
" msr control, r3 \n" /* Set this task's CONTROL value. */ " msr control, r3 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n" /* Discard everything up to r0. */ " 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. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r4 \n" /* Finally, branch to EXC_RETURN. */ " bx r4 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
" ldr r4, xSecureContextConst2 \n" " ldr r4, xSecureContextConst2 \n"
" str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */ " str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */
" msr psplim, r2 \n" /* Set this task's PSPLIM value. */ " msr psplim, r2 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n" /* r1 = 2. */ " movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */ " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n" /* Discard everything up to r0. */ " 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. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r3 \n" /* Finally, branch to EXC_RETURN. */ " bx r3 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
"xSecureContextConst2: .word xSecureContext \n" "xSecureContextConst2: .word xSecureContext \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n" "xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n" "xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n" "xRNRConst2: .word 0xe000ed98 \n"
@ -114,12 +114,12 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n" /* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" tst r0, #1 \n" /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
" ite ne \n" " ite ne \n"
" movne r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " 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. */ " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "memory" ::: "r0", "memory"
@ -131,10 +131,10 @@ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n" /* Read the CONTROL register. */ " mrs r0, control \n"/* Read the CONTROL register. */
" bic r0, #1 \n" /* Clear the bit 0. */ " bic r0, #1 \n"/* Clear the bit 0. */
" msr control, r0 \n" /* Write back the new CONTROL value. */ " msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n" /* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -144,11 +144,11 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n" /* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" orr r0, #1 \n" /* r0 = r0 | 1. */ " orr r0, #1 \n"/* r0 = r0 | 1. */
" msr control, r0 \n" /* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n" /* Return to the caller. */ " bx lr \n"/* Return to the caller. */
:::"r0", "memory" ::: "r0", "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -157,20 +157,20 @@ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" ldr r0, xVTORConst \n" /* Use the NVIC offset register to locate the stack. */ " 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"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */ " 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. */ " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n" /* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" cpsie f \n" " cpsie f \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n" /* System call to start the first task. */ " svc %0 \n"/* System call to start the first task. */
" nop \n" " nop \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n" "xVTORConst: .word 0xe000ed08 \n"
:: "i" ( portSVC_START_SCHEDULER ) : "memory" ::"i" ( portSVC_START_SCHEDULER ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -179,13 +179,13 @@ uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCT
{ {
__asm volatile __asm volatile
( (
" mrs r0, basepri \n" /* r0 = basepri. Return original basepri value. */ " mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */
" mov r1, %0 \n" /* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" msr basepri, r1 \n" /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
:: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -194,10 +194,10 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
{ {
__asm volatile __asm volatile
( (
" msr basepri, r0 \n" /* basepri = ulMask. */ " msr basepri, r0 \n"/* basepri = ulMask. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
::: "memory" ::: "memory"
); );
} }
@ -211,156 +211,156 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
" .extern SecureContext_SaveContext \n" " .extern SecureContext_SaveContext \n"
" .extern SecureContext_LoadContext \n" " .extern SecureContext_LoadContext \n"
" \n" " \n"
" mrs r1, psp \n" /* Read PSP in r1. */ " mrs r1, psp \n"/* Read PSP in r1. */
" ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ " 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. */ " ldr r0, [r2] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
" \n" " \n"
" cbz r0, save_ns_context \n" /* No secure context to save. */ " cbz r0, save_ns_context \n"/* No secure context to save. */
" push {r0-r2, r14} \n" " push {r0-r2, r14} \n"
" bl SecureContext_SaveContext \n" " bl SecureContext_SaveContext \n"
" pop {r0-r3} \n" /* LR is now in r3. */ " pop {r0-r3} \n"/* LR is now in r3. */
" mov lr, r3 \n" /* LR = 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. */ " 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. */ " 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 r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r2, [r3] \n" /* Read pxCurrentTCB. */ " ldr r2, [r3] \n"/* Read pxCurrentTCB. */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r1, r1, #16 \n" /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " 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. */ " str r1, [r2] \n"/* Save the new top of stack in TCB. */
" mrs r2, psplim \n" /* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mrs r3, control \n" /* r3 = CONTROL. */ " mrs r3, control \n"/* r3 = CONTROL. */
" mov r4, lr \n" /* r4 = LR/EXC_RETURN. */ " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
" stmia r1!, {r0, r2-r4} \n" /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " stmia r1!, {r0, r2-r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r1, r1, #12 \n" /* Make space for xSecureContext, PSPLIM and LR on the stack. */ " 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. */ " str r1, [r2] \n"/* Save the new top of stack in TCB. */
" mrs r2, psplim \n" /* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r1!, {r0, r2-r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */ " stmia r1!, {r0, r2-r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" b select_next_task \n" " b select_next_task \n"
" \n" " \n"
" save_ns_context: \n" " save_ns_context: \n"
" ldr r3, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r2, [r3] \n" /* Read pxCurrentTCB. */ " ldr r2, [r3] \n"/* Read pxCurrentTCB. */
#if( configENABLE_FPU == 1 ) #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. */ " 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" " it eq \n"
" vstmdbeq r1!, {s16-s31} \n" /* Store the FPU registers which are not saved automatically. */ " vstmdbeq r1!, {s16-s31} \n"/* Store the FPU registers which are not saved automatically. */
#endif /* configENABLE_FPU */ #endif /* configENABLE_FPU */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r1, r1, #48 \n" /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */ " 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. */ " str r1, [r2] \n"/* Save the new top of stack in TCB. */
" adds r1, r1, #16 \n" /* r1 = r1 + 16. */ " adds r1, r1, #16 \n"/* r1 = r1 + 16. */
" stm r1, {r4-r11} \n" /* Store the registers that are not saved automatically. */ " stm r1, {r4-r11} \n"/* Store the registers that are not saved automatically. */
" mrs r2, psplim \n" /* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mrs r3, control \n" /* r3 = CONTROL. */ " mrs r3, control \n"/* r3 = CONTROL. */
" mov r4, lr \n" /* r4 = LR/EXC_RETURN. */ " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
" subs r1, r1, #16 \n" /* r1 = r1 - 16. */ " subs r1, r1, #16 \n"/* r1 = r1 - 16. */
" stm r1, {r0, r2-r4} \n" /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " stm r1, {r0, r2-r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r1, r1, #44 \n" /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ " 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. */ " str r1, [r2] \n"/* Save the new top of stack in TCB. */
" adds r1, r1, #12 \n" /* r1 = r1 + 12. */ " adds r1, r1, #12 \n"/* r1 = r1 + 12. */
" stm r1, {r4-r11} \n" /* Store the registers that are not saved automatically. */ " stm r1, {r4-r11} \n"/* Store the registers that are not saved automatically. */
" mrs r2, psplim \n" /* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" subs r1, r1, #12 \n" /* r1 = r1 - 12. */ " subs r1, r1, #12 \n"/* r1 = r1 - 12. */
" stmia r1!, {r0, r2-r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */ " stmia r1!, {r0, r2-r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
" mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ " mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
" msr basepri, r0 \n" /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" mov r0, #0 \n" /* r0 = 0. */ " mov r0, #0 \n"/* r0 = 0. */
" msr basepri, r0 \n" /* Enable interrupts. */ " msr basepri, r0 \n"/* Enable interrupts. */
" \n" " \n"
" ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r3, [r2] \n" /* Read 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. */ " ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. r1 now points to the top of stack. */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n" /* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n" /* Read the value 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. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n" /* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ " 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 r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n" /* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst \n" /* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r4, #4 \n" /* r4 = 4. */ " movs r4, #4 \n"/* r4 = 4. */
" str r4, [r2] \n" /* Program RNR = 4. */ " str r4, [r2] \n"/* Program RNR = 4. */
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
" ldr r2, xRBARConst \n" /* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r3!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */ " 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. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n" /* Read the value 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. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n" /* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n" /* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldmia r1!, {r0, r2-r4} \n" /* Read from stack - r0 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = LR. */ " 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 psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r3 \n" /* Restore the CONTROL register value for the task. */ " msr control, r3 \n"/* Restore the CONTROL register value for the task. */
" mov lr, r4 \n" /* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r2] \n" /* Restore the task's 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. */ " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
" push {r1,r4} \n" " push {r1,r4} \n"
" bl SecureContext_LoadContext \n" /* Restore the secure context. */ " bl SecureContext_LoadContext \n"/* Restore the secure context. */
" pop {r1,r4} \n" " pop {r1,r4} \n"
" mov lr, r4 \n" /* LR = r4. */ " 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. */ " 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. */ " 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. */ " msr psp, r1 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldmia r1!, {r0, r2-r3} \n" /* Read from stack - r0 = xSecureContext, r2 = PSPLIM and r3 = LR. */ " 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. */ " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
" mov lr, r3 \n" /* LR = r3. */ " mov lr, r3 \n"/* LR = r3. */
" ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r2] \n" /* Restore the task's 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. */ " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
" push {r1,r3} \n" " push {r1,r3} \n"
" bl SecureContext_LoadContext \n" /* Restore the secure context. */ " bl SecureContext_LoadContext \n"/* Restore the secure context. */
" pop {r1,r3} \n" " pop {r1,r3} \n"
" mov lr, r3 \n" /* LR = 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. */ " 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. */ " 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. */ " msr psp, r1 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" restore_ns_context: \n" " restore_ns_context: \n"
" ldmia r1!, {r4-r11} \n" /* Restore the registers that are not automatically restored. */ " ldmia r1!, {r4-r11} \n"/* Restore the registers that are not automatically restored. */
#if( configENABLE_FPU == 1 ) #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. */ " 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" " it eq \n"
" vldmiaeq r1!, {s16-s31} \n" /* Restore the FPU registers which are not restored automatically. */ " vldmiaeq r1!, {s16-s31} \n"/* Restore the FPU registers which are not restored automatically. */
#endif /* configENABLE_FPU */ #endif /* configENABLE_FPU */
" msr psp, r1 \n" /* Remember the new top of stack for the task. */ " msr psp, r1 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
"xSecureContextConst: .word xSecureContext \n" "xSecureContextConst: .word xSecureContext \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n" "xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n" "xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n" "xRNRConst: .word 0xe000ed98 \n"
"xRBARConst: .word 0xe000ed9c \n" "xRBARConst: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
:: "i"( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -386,24 +386,24 @@ void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (
{ {
__asm volatile __asm volatile
( (
" svc %0 \n" /* Secure context is allocated in the supervisor call. */ " svc %0 \n"/* Secure context is allocated in the supervisor call. */
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
:: "i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory" ::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" ldr r1, [r0] \n" /* The first item in the TCB is the top of the stack. */ " 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. */ " 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. */ " cmp r0, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */
" it ne \n" " it ne \n"
" svcne %0 \n" /* Secure context is freed in the supervisor call. */ " svcne %0 \n"/* Secure context is freed in the supervisor call. */
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
:: "i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory" ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -25,11 +25,11 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -41,109 +41,109 @@ extern "C" {
*------------------------------------------------------------------------------ *------------------------------------------------------------------------------
*/ */
#ifndef configENABLE_FPU #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. #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 */ #endif /* configENABLE_FPU */
#ifndef configENABLE_MPU #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. #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 */ #endif /* configENABLE_MPU */
#ifndef configENABLE_TRUSTZONE #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. #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 */ #endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Type definitions. * @brief Type definitions.
*/ */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 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. */ * not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* Architecture specifics. * Architecture specifics.
*/ */
#define portARCH_NAME "Cortex-M33" #define portARCH_NAME "Cortex-M33"
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portNOP() #define portNOP()
#define portINLINE __inline #define portINLINE __inline
#ifndef portFORCE_INLINE #ifndef portFORCE_INLINE
#define portFORCE_INLINE inline __attribute__(( always_inline )) #define portFORCE_INLINE inline __attribute__( ( always_inline ) )
#endif #endif
#define portHAS_STACK_OVERFLOW_CHECKING 1 #define portHAS_STACK_OVERFLOW_CHECKING 1
#define portDONT_DISCARD __attribute__(( used )) #define portDONT_DISCARD __attribute__( ( used ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Extern declarations. * @brief Extern declarations.
*/ */
extern BaseType_t xPortIsInsideInterrupt( void ); extern BaseType_t xPortIsInsideInterrupt( void );
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief MPU specific constants. * @brief MPU specific constants.
*/ */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
#define portUSING_MPU_WRAPPERS 1 #define portUSING_MPU_WRAPPERS 1
#define portPRIVILEGE_BIT ( 0x80000000UL ) #define portPRIVILEGE_BIT ( 0x80000000UL )
#else #else
#define portPRIVILEGE_BIT ( 0x0UL ) #define portPRIVILEGE_BIT ( 0x0UL )
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/* MPU regions. */ /* MPU regions. */
#define portPRIVILEGED_FLASH_REGION ( 0UL ) #define portPRIVILEGED_FLASH_REGION ( 0UL )
#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) #define portUNPRIVILEGED_FLASH_REGION ( 1UL )
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
#define portPRIVILEGED_RAM_REGION ( 3UL ) #define portPRIVILEGED_RAM_REGION ( 3UL )
#define portSTACK_REGION ( 4UL ) #define portSTACK_REGION ( 4UL )
#define portFIRST_CONFIGURABLE_REGION ( 5UL ) #define portFIRST_CONFIGURABLE_REGION ( 5UL )
#define portLAST_CONFIGURABLE_REGION ( 7UL ) #define portLAST_CONFIGURABLE_REGION ( 7UL )
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) #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 portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
/* Device memory attributes used in MPU_MAIR registers. /* Device memory attributes used in MPU_MAIR registers.
* *
@ -155,95 +155,96 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
* 11 --> Device-GRE * 11 --> Device-GRE
* Bit[1:0] - 00, Reserved. * Bit[1:0] - 00, Reserved.
*/ */
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
/* Normal memory attributes used in MPU_MAIR registers. */ /* Normal memory attributes used in MPU_MAIR registers. */
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ #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. */ #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
/* Attributes used in MPU_RBAR registers. */ /* Attributes used in MPU_RBAR registers. */
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) #define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) #define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) #define portMPU_REGION_EXECUTE_NEVER ( 1UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Settings to define an MPU region. * @brief Settings to define an MPU region.
*/ */
typedef struct MPURegionSettings typedef struct MPURegionSettings
{ {
uint32_t ulRBAR; /**< RBAR for the region. */ uint32_t ulRBAR; /**< RBAR for the region. */
uint32_t ulRLAR; /**< RLAR for the region. */ uint32_t ulRLAR; /**< RLAR for the region. */
} MPURegionSettings_t; } MPURegionSettings_t;
/** /**
* @brief MPU settings as stored in the TCB. * @brief MPU settings as stored in the TCB.
*/ */
typedef struct MPU_SETTINGS typedef struct MPU_SETTINGS
{ {
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ 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. */ MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
} xMPU_SETTINGS; } xMPU_SETTINGS;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief SVC numbers. * @brief SVC numbers.
*/ */
#define portSVC_ALLOCATE_SECURE_CONTEXT 0 #define portSVC_ALLOCATE_SECURE_CONTEXT 0
#define portSVC_FREE_SECURE_CONTEXT 1 #define portSVC_FREE_SECURE_CONTEXT 1
#define portSVC_START_SCHEDULER 2 #define portSVC_START_SCHEDULER 2
#define portSVC_RAISE_PRIVILEGE 3 #define portSVC_RAISE_PRIVILEGE 3
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Scheduler utilities. * @brief Scheduler utilities.
*/ */
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Critical section management. * @brief Critical section management.
*/ */
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
#define portDISABLE_INTERRUPTS() ulSetInterruptMask() #define portDISABLE_INTERRUPTS() ulSetInterruptMask()
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 ) #define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Tickless idle/low power functionality. * @brief Tickless idle/low power functionality.
*/ */
#ifndef portSUPPRESS_TICKS_AND_SLEEP #ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Task function macros as described on the FreeRTOS.org WEB site. * @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_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/**
/**
* @brief Allocate a secure context for the task. * @brief Allocate a secure context for the task.
* *
* Tasks are not created with a secure context. Any task that is going to call * Tasks are not created with a secure context. Any task that is going to call
@ -254,56 +255,57 @@ typedef struct MPU_SETTINGS
*/ */
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
/** /**
* @brief Called when a task is deleted to delete the task's secure context, * @brief Called when a task is deleted to delete the task's secure context,
* if it has one. * if it has one.
* *
* @param[in] pxTCB The TCB of the task being deleted. * @param[in] pxTCB The TCB of the task being deleted.
*/ */
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
#else #else
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
#define portCLEAN_UP_TCB( pxTCB ) #define portCLEAN_UP_TCB( pxTCB )
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/**
/**
* @brief Checks whether or not the processor is privileged. * @brief Checks whether or not the processor is privileged.
* *
* @return 1 if the processor is already privileged, 0 otherwise. * @return 1 if the processor is already privileged, 0 otherwise.
*/ */
#define portIS_PRIVILEGED() xIsPrivileged() #define portIS_PRIVILEGED() xIsPrivileged()
/** /**
* @brief Raise an SVC request to raise privilege. * @brief Raise an SVC request to raise privilege.
* *
* The SVC handler checks that the SVC was raised from a system call and only * 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, * then it raises the privilege. If this is called from any other place,
* the privilege is not raised. * the privilege is not raised.
*/ */
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); #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 * @brief Lowers the privilege level by setting the bit 0 of the CONTROL
* register. * register.
*/ */
#define portRESET_PRIVILEGE() vResetPrivilege() #define portRESET_PRIVILEGE() vResetPrivilege()
#else #else
#define portIS_PRIVILEGED() #define portIS_PRIVILEGED()
#define portRAISE_PRIVILEGE() #define portRAISE_PRIVILEGE()
#define portRESET_PRIVILEGE() #define portRESET_PRIVILEGE()
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Barriers. * @brief Barriers.
*/ */
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -44,58 +44,58 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst2 \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n" /* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n" /* Read the value 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. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n" /* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r3, [r1] \n" /* r3 = *r1 i.e. r3 = MAIR0. */ " ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */
" ldr r2, xMAIR0Const2 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r3, [r2] \n" /* Program MAIR0. */ " str r3, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n" /* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #4 \n" /* r3 = 4. */ " movs r3, #4 \n"/* r3 = 4. */
" str r3, [r2] \n" /* Program RNR = 4. */ " str r3, [r2] \n"/* Program RNR = 4. */
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" ldr r2, xRBARConst2 \n" /* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n" /* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r1!, {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. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n" /* Read the value 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. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n" /* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n" /* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */ " msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" msr control, r2 \n" /* Set this task's CONTROL value. */ " msr control, r2 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n" /* Discard everything up to r0. */ " 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. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r3 \n" /* Finally, branch to EXC_RETURN. */ " bx r3 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ " ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */ " msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n" /* r1 = 2. */ " movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */ " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n" /* Discard everything up to r0. */ " 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. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r2 \n" /* Finally, branch to EXC_RETURN. */ " bx r2 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n" "xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n" "xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n" "xRNRConst2: .word 0xe000ed98 \n"
@ -109,12 +109,12 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n" /* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" tst r0, #1 \n" /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
" ite ne \n" " ite ne \n"
" movne r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " 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. */ " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "memory" ::: "r0", "memory"
@ -126,10 +126,10 @@ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n" /* Read the CONTROL register. */ " mrs r0, control \n"/* Read the CONTROL register. */
" bic r0, #1 \n" /* Clear the bit 0. */ " bic r0, #1 \n"/* Clear the bit 0. */
" msr control, r0 \n" /* Write back the new CONTROL value. */ " msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n" /* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -139,11 +139,11 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n" /* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" orr r0, #1 \n" /* r0 = r0 | 1. */ " orr r0, #1 \n"/* r0 = r0 | 1. */
" msr control, r0 \n" /* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n" /* Return to the caller. */ " bx lr \n"/* Return to the caller. */
:::"r0", "memory" ::: "r0", "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -152,20 +152,20 @@ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" ldr r0, xVTORConst \n" /* Use the NVIC offset register to locate the stack. */ " 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"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */ " 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. */ " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n" /* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" cpsie f \n" " cpsie f \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n" /* System call to start the first task. */ " svc %0 \n"/* System call to start the first task. */
" nop \n" " nop \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n" "xVTORConst: .word 0xe000ed08 \n"
:: "i" ( portSVC_START_SCHEDULER ) : "memory" ::"i" ( portSVC_START_SCHEDULER ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -174,13 +174,13 @@ uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCT
{ {
__asm volatile __asm volatile
( (
" mrs r0, basepri \n" /* r0 = basepri. Return original basepri value. */ " mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */
" mov r1, %0 \n" /* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" msr basepri, r1 \n" /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
:: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -189,10 +189,10 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
{ {
__asm volatile __asm volatile
( (
" msr basepri, r0 \n" /* basepri = ulMask. */ " msr basepri, r0 \n"/* basepri = ulMask. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
::: "memory" ::: "memory"
); );
} }
@ -204,95 +204,95 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, psp \n" /* Read PSP in r0. */ " mrs r0, psp \n"/* Read PSP in r0. */
#if( configENABLE_FPU == 1 ) #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. */ " 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" " it eq \n"
" vstmdbeq r0!, {s16-s31} \n" /* Store the FPU registers which are not saved automatically. */ " vstmdbeq r0!, {s16-s31} \n"/* Store the FPU registers which are not saved automatically. */
#endif /* configENABLE_FPU */ #endif /* configENABLE_FPU */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" mrs r1, psplim \n" /* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r2, control \n" /* r2 = CONTROL. */ " mrs r2, control \n"/* r2 = CONTROL. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmdb r0!, {r1-r11} \n" /* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */ " stmdb r0!, {r1-r11} \n"/* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" mrs r2, psplim \n" /* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmdb r0!, {r2-r11} \n" /* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */ " stmdb r0!, {r2-r11} \n"/* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" str r0, [r1] \n" /* Save the new top of stack in TCB. */ " str r0, [r1] \n"/* Save the new top of stack in TCB. */
" \n" " \n"
" mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ " mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
" msr basepri, r0 \n" /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" mov r0, #0 \n" /* r0 = 0. */ " mov r0, #0 \n"/* r0 = 0. */
" msr basepri, r0 \n" /* Enable interrupts. */ " msr basepri, r0 \n"/* Enable interrupts. */
" \n" " \n"
" ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n" /* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n" /* Read the value 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. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n" /* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r3, [r1] \n" /* r3 = *r1 i.e. r3 = MAIR0. */ " ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */
" ldr r2, xMAIR0Const \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r3, [r2] \n" /* Program MAIR0. */ " str r3, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst \n" /* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #4 \n" /* r3 = 4. */ " movs r3, #4 \n"/* r3 = 4. */
" str r3, [r2] \n" /* Program RNR = 4. */ " str r3, [r2] \n"/* Program RNR = 4. */
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" ldr r2, xRBARConst \n" /* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {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. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n" /* Read the value 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. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n" /* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n" /* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldmia r0!, {r1-r11} \n" /* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */ " ldmia r0!, {r1-r11} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldmia r0!, {r2-r11} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */ " ldmia r0!, {r2-r11} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
" tst r3, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */ " tst r3, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
" it eq \n" " it eq \n"
" vldmiaeq r0!, {s16-s31} \n" /* Restore the FPU registers which are not restored automatically. */ " vldmiaeq r0!, {s16-s31} \n"/* Restore the FPU registers which are not restored automatically. */
#endif /* configENABLE_FPU */ #endif /* configENABLE_FPU */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" msr psplim, r1 \n" /* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r2 \n" /* Restore the CONTROL register value for the task. */ " msr control, r2 \n"/* Restore the CONTROL register value for the task. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */ " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" msr psp, r0 \n" /* Remember the new top of stack for the task. */ " msr psp, r0 \n"/* Remember the new top of stack for the task. */
" bx r3 \n" " bx r3 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n" "xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n" "xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n" "xRNRConst: .word 0xe000ed98 \n"
"xRBARConst: .word 0xe000ed9c \n" "xRBARConst: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
:: "i"( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -25,11 +25,11 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -41,109 +41,109 @@ extern "C" {
*------------------------------------------------------------------------------ *------------------------------------------------------------------------------
*/ */
#ifndef configENABLE_FPU #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. #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 */ #endif /* configENABLE_FPU */
#ifndef configENABLE_MPU #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. #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 */ #endif /* configENABLE_MPU */
#ifndef configENABLE_TRUSTZONE #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. #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 */ #endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Type definitions. * @brief Type definitions.
*/ */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 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. */ * not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* Architecture specifics. * Architecture specifics.
*/ */
#define portARCH_NAME "Cortex-M33" #define portARCH_NAME "Cortex-M33"
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portNOP() #define portNOP()
#define portINLINE __inline #define portINLINE __inline
#ifndef portFORCE_INLINE #ifndef portFORCE_INLINE
#define portFORCE_INLINE inline __attribute__(( always_inline )) #define portFORCE_INLINE inline __attribute__( ( always_inline ) )
#endif #endif
#define portHAS_STACK_OVERFLOW_CHECKING 1 #define portHAS_STACK_OVERFLOW_CHECKING 1
#define portDONT_DISCARD __attribute__(( used )) #define portDONT_DISCARD __attribute__( ( used ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Extern declarations. * @brief Extern declarations.
*/ */
extern BaseType_t xPortIsInsideInterrupt( void ); extern BaseType_t xPortIsInsideInterrupt( void );
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief MPU specific constants. * @brief MPU specific constants.
*/ */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
#define portUSING_MPU_WRAPPERS 1 #define portUSING_MPU_WRAPPERS 1
#define portPRIVILEGE_BIT ( 0x80000000UL ) #define portPRIVILEGE_BIT ( 0x80000000UL )
#else #else
#define portPRIVILEGE_BIT ( 0x0UL ) #define portPRIVILEGE_BIT ( 0x0UL )
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/* MPU regions. */ /* MPU regions. */
#define portPRIVILEGED_FLASH_REGION ( 0UL ) #define portPRIVILEGED_FLASH_REGION ( 0UL )
#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) #define portUNPRIVILEGED_FLASH_REGION ( 1UL )
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
#define portPRIVILEGED_RAM_REGION ( 3UL ) #define portPRIVILEGED_RAM_REGION ( 3UL )
#define portSTACK_REGION ( 4UL ) #define portSTACK_REGION ( 4UL )
#define portFIRST_CONFIGURABLE_REGION ( 5UL ) #define portFIRST_CONFIGURABLE_REGION ( 5UL )
#define portLAST_CONFIGURABLE_REGION ( 7UL ) #define portLAST_CONFIGURABLE_REGION ( 7UL )
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) #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 portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
/* Device memory attributes used in MPU_MAIR registers. /* Device memory attributes used in MPU_MAIR registers.
* *
@ -155,95 +155,96 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
* 11 --> Device-GRE * 11 --> Device-GRE
* Bit[1:0] - 00, Reserved. * Bit[1:0] - 00, Reserved.
*/ */
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
/* Normal memory attributes used in MPU_MAIR registers. */ /* Normal memory attributes used in MPU_MAIR registers. */
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ #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. */ #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
/* Attributes used in MPU_RBAR registers. */ /* Attributes used in MPU_RBAR registers. */
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) #define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) #define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) #define portMPU_REGION_EXECUTE_NEVER ( 1UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Settings to define an MPU region. * @brief Settings to define an MPU region.
*/ */
typedef struct MPURegionSettings typedef struct MPURegionSettings
{ {
uint32_t ulRBAR; /**< RBAR for the region. */ uint32_t ulRBAR; /**< RBAR for the region. */
uint32_t ulRLAR; /**< RLAR for the region. */ uint32_t ulRLAR; /**< RLAR for the region. */
} MPURegionSettings_t; } MPURegionSettings_t;
/** /**
* @brief MPU settings as stored in the TCB. * @brief MPU settings as stored in the TCB.
*/ */
typedef struct MPU_SETTINGS typedef struct MPU_SETTINGS
{ {
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ 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. */ MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
} xMPU_SETTINGS; } xMPU_SETTINGS;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief SVC numbers. * @brief SVC numbers.
*/ */
#define portSVC_ALLOCATE_SECURE_CONTEXT 0 #define portSVC_ALLOCATE_SECURE_CONTEXT 0
#define portSVC_FREE_SECURE_CONTEXT 1 #define portSVC_FREE_SECURE_CONTEXT 1
#define portSVC_START_SCHEDULER 2 #define portSVC_START_SCHEDULER 2
#define portSVC_RAISE_PRIVILEGE 3 #define portSVC_RAISE_PRIVILEGE 3
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Scheduler utilities. * @brief Scheduler utilities.
*/ */
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Critical section management. * @brief Critical section management.
*/ */
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMask( x ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
#define portDISABLE_INTERRUPTS() ulSetInterruptMask() #define portDISABLE_INTERRUPTS() ulSetInterruptMask()
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 ) #define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Tickless idle/low power functionality. * @brief Tickless idle/low power functionality.
*/ */
#ifndef portSUPPRESS_TICKS_AND_SLEEP #ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Task function macros as described on the FreeRTOS.org WEB site. * @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_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/**
/**
* @brief Allocate a secure context for the task. * @brief Allocate a secure context for the task.
* *
* Tasks are not created with a secure context. Any task that is going to call * Tasks are not created with a secure context. Any task that is going to call
@ -254,56 +255,57 @@ typedef struct MPU_SETTINGS
*/ */
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
/** /**
* @brief Called when a task is deleted to delete the task's secure context, * @brief Called when a task is deleted to delete the task's secure context,
* if it has one. * if it has one.
* *
* @param[in] pxTCB The TCB of the task being deleted. * @param[in] pxTCB The TCB of the task being deleted.
*/ */
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
#else #else
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
#define portCLEAN_UP_TCB( pxTCB ) #define portCLEAN_UP_TCB( pxTCB )
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/**
/**
* @brief Checks whether or not the processor is privileged. * @brief Checks whether or not the processor is privileged.
* *
* @return 1 if the processor is already privileged, 0 otherwise. * @return 1 if the processor is already privileged, 0 otherwise.
*/ */
#define portIS_PRIVILEGED() xIsPrivileged() #define portIS_PRIVILEGED() xIsPrivileged()
/** /**
* @brief Raise an SVC request to raise privilege. * @brief Raise an SVC request to raise privilege.
* *
* The SVC handler checks that the SVC was raised from a system call and only * 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, * then it raises the privilege. If this is called from any other place,
* the privilege is not raised. * the privilege is not raised.
*/ */
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); #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 * @brief Lowers the privilege level by setting the bit 0 of the CONTROL
* register. * register.
*/ */
#define portRESET_PRIVILEGE() vResetPrivilege() #define portRESET_PRIVILEGE() vResetPrivilege()
#else #else
#define portIS_PRIVILEGED() #define portIS_PRIVILEGED()
#define portRAISE_PRIVILEGE() #define portRAISE_PRIVILEGE()
#define portRESET_PRIVILEGE() #define portRESET_PRIVILEGE()
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Barriers. * @brief Barriers.
*/ */
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -25,11 +25,11 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -41,109 +41,109 @@ extern "C" {
*------------------------------------------------------------------------------ *------------------------------------------------------------------------------
*/ */
#ifndef configENABLE_FPU #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. #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 */ #endif /* configENABLE_FPU */
#ifndef configENABLE_MPU #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. #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 */ #endif /* configENABLE_MPU */
#ifndef configENABLE_TRUSTZONE #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. #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 */ #endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Type definitions. * @brief Type definitions.
*/ */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 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. */ * not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* Architecture specifics. * Architecture specifics.
*/ */
#define portARCH_NAME "Cortex-M23" #define portARCH_NAME "Cortex-M23"
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portNOP() #define portNOP()
#define portINLINE __inline #define portINLINE __inline
#ifndef portFORCE_INLINE #ifndef portFORCE_INLINE
#define portFORCE_INLINE inline __attribute__(( always_inline )) #define portFORCE_INLINE inline __attribute__( ( always_inline ) )
#endif #endif
#define portHAS_STACK_OVERFLOW_CHECKING 1 #define portHAS_STACK_OVERFLOW_CHECKING 1
#define portDONT_DISCARD __root #define portDONT_DISCARD __root
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Extern declarations. * @brief Extern declarations.
*/ */
extern BaseType_t xPortIsInsideInterrupt( void ); extern BaseType_t xPortIsInsideInterrupt( void );
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief MPU specific constants. * @brief MPU specific constants.
*/ */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
#define portUSING_MPU_WRAPPERS 1 #define portUSING_MPU_WRAPPERS 1
#define portPRIVILEGE_BIT ( 0x80000000UL ) #define portPRIVILEGE_BIT ( 0x80000000UL )
#else #else
#define portPRIVILEGE_BIT ( 0x0UL ) #define portPRIVILEGE_BIT ( 0x0UL )
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/* MPU regions. */ /* MPU regions. */
#define portPRIVILEGED_FLASH_REGION ( 0UL ) #define portPRIVILEGED_FLASH_REGION ( 0UL )
#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) #define portUNPRIVILEGED_FLASH_REGION ( 1UL )
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
#define portPRIVILEGED_RAM_REGION ( 3UL ) #define portPRIVILEGED_RAM_REGION ( 3UL )
#define portSTACK_REGION ( 4UL ) #define portSTACK_REGION ( 4UL )
#define portFIRST_CONFIGURABLE_REGION ( 5UL ) #define portFIRST_CONFIGURABLE_REGION ( 5UL )
#define portLAST_CONFIGURABLE_REGION ( 7UL ) #define portLAST_CONFIGURABLE_REGION ( 7UL )
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) #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 portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
/* Device memory attributes used in MPU_MAIR registers. /* Device memory attributes used in MPU_MAIR registers.
* *
@ -155,95 +155,96 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
* 11 --> Device-GRE * 11 --> Device-GRE
* Bit[1:0] - 00, Reserved. * Bit[1:0] - 00, Reserved.
*/ */
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
/* Normal memory attributes used in MPU_MAIR registers. */ /* Normal memory attributes used in MPU_MAIR registers. */
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ #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. */ #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
/* Attributes used in MPU_RBAR registers. */ /* Attributes used in MPU_RBAR registers. */
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) #define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) #define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) #define portMPU_REGION_EXECUTE_NEVER ( 1UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Settings to define an MPU region. * @brief Settings to define an MPU region.
*/ */
typedef struct MPURegionSettings typedef struct MPURegionSettings
{ {
uint32_t ulRBAR; /**< RBAR for the region. */ uint32_t ulRBAR; /**< RBAR for the region. */
uint32_t ulRLAR; /**< RLAR for the region. */ uint32_t ulRLAR; /**< RLAR for the region. */
} MPURegionSettings_t; } MPURegionSettings_t;
/** /**
* @brief MPU settings as stored in the TCB. * @brief MPU settings as stored in the TCB.
*/ */
typedef struct MPU_SETTINGS typedef struct MPU_SETTINGS
{ {
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ 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. */ MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
} xMPU_SETTINGS; } xMPU_SETTINGS;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief SVC numbers. * @brief SVC numbers.
*/ */
#define portSVC_ALLOCATE_SECURE_CONTEXT 0 #define portSVC_ALLOCATE_SECURE_CONTEXT 0
#define portSVC_FREE_SECURE_CONTEXT 1 #define portSVC_FREE_SECURE_CONTEXT 1
#define portSVC_START_SCHEDULER 2 #define portSVC_START_SCHEDULER 2
#define portSVC_RAISE_PRIVILEGE 3 #define portSVC_RAISE_PRIVILEGE 3
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Scheduler utilities. * @brief Scheduler utilities.
*/ */
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Tickless idle/low power functionality. * @brief Tickless idle/low power functionality.
*/ */
#ifndef portSUPPRESS_TICKS_AND_SLEEP #ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Critical section management. * @brief Critical section management.
*/ */
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMask( x ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) #define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) #define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Task function macros as described on the FreeRTOS.org WEB site. * @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_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/**
/**
* @brief Allocate a secure context for the task. * @brief Allocate a secure context for the task.
* *
* Tasks are not created with a secure context. Any task that is going to call * Tasks are not created with a secure context. Any task that is going to call
@ -254,63 +255,64 @@ typedef struct MPU_SETTINGS
*/ */
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
/** /**
* @brief Called when a task is deleted to delete the task's secure context, * @brief Called when a task is deleted to delete the task's secure context,
* if it has one. * if it has one.
* *
* @param[in] pxTCB The TCB of the task being deleted. * @param[in] pxTCB The TCB of the task being deleted.
*/ */
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
#else #else
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
#define portCLEAN_UP_TCB( pxTCB ) #define portCLEAN_UP_TCB( pxTCB )
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/**
/**
* @brief Checks whether or not the processor is privileged. * @brief Checks whether or not the processor is privileged.
* *
* @return 1 if the processor is already privileged, 0 otherwise. * @return 1 if the processor is already privileged, 0 otherwise.
*/ */
#define portIS_PRIVILEGED() xIsPrivileged() #define portIS_PRIVILEGED() xIsPrivileged()
/** /**
* @brief Raise an SVC request to raise privilege. * @brief Raise an SVC request to raise privilege.
* *
* The SVC handler checks that the SVC was raised from a system call and only * 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, * then it raises the privilege. If this is called from any other place,
* the privilege is not raised. * the privilege is not raised.
*/ */
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); #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 * @brief Lowers the privilege level by setting the bit 0 of the CONTROL
* register. * register.
*/ */
#define portRESET_PRIVILEGE() vResetPrivilege() #define portRESET_PRIVILEGE() vResetPrivilege()
#else #else
#define portIS_PRIVILEGED() #define portIS_PRIVILEGED()
#define portRAISE_PRIVILEGE() #define portRAISE_PRIVILEGE()
#define portRESET_PRIVILEGE() #define portRESET_PRIVILEGE()
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Barriers. * @brief Barriers.
*/ */
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in /* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
* the source code because to do so would cause other compilers to generate * the source code because to do so would cause other compilers to generate
* warnings. */ * warnings. */
#pragma diag_suppress=Be006 #pragma diag_suppress=Be006
#pragma diag_suppress=Pa082 #pragma diag_suppress=Pa082
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -25,11 +25,11 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -41,109 +41,109 @@ extern "C" {
*------------------------------------------------------------------------------ *------------------------------------------------------------------------------
*/ */
#ifndef configENABLE_FPU #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. #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 */ #endif /* configENABLE_FPU */
#ifndef configENABLE_MPU #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. #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 */ #endif /* configENABLE_MPU */
#ifndef configENABLE_TRUSTZONE #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. #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 */ #endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Type definitions. * @brief Type definitions.
*/ */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 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. */ * not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* Architecture specifics. * Architecture specifics.
*/ */
#define portARCH_NAME "Cortex-M23" #define portARCH_NAME "Cortex-M23"
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portNOP() #define portNOP()
#define portINLINE __inline #define portINLINE __inline
#ifndef portFORCE_INLINE #ifndef portFORCE_INLINE
#define portFORCE_INLINE inline __attribute__(( always_inline )) #define portFORCE_INLINE inline __attribute__( ( always_inline ) )
#endif #endif
#define portHAS_STACK_OVERFLOW_CHECKING 1 #define portHAS_STACK_OVERFLOW_CHECKING 1
#define portDONT_DISCARD __root #define portDONT_DISCARD __root
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Extern declarations. * @brief Extern declarations.
*/ */
extern BaseType_t xPortIsInsideInterrupt( void ); extern BaseType_t xPortIsInsideInterrupt( void );
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief MPU specific constants. * @brief MPU specific constants.
*/ */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
#define portUSING_MPU_WRAPPERS 1 #define portUSING_MPU_WRAPPERS 1
#define portPRIVILEGE_BIT ( 0x80000000UL ) #define portPRIVILEGE_BIT ( 0x80000000UL )
#else #else
#define portPRIVILEGE_BIT ( 0x0UL ) #define portPRIVILEGE_BIT ( 0x0UL )
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/* MPU regions. */ /* MPU regions. */
#define portPRIVILEGED_FLASH_REGION ( 0UL ) #define portPRIVILEGED_FLASH_REGION ( 0UL )
#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) #define portUNPRIVILEGED_FLASH_REGION ( 1UL )
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
#define portPRIVILEGED_RAM_REGION ( 3UL ) #define portPRIVILEGED_RAM_REGION ( 3UL )
#define portSTACK_REGION ( 4UL ) #define portSTACK_REGION ( 4UL )
#define portFIRST_CONFIGURABLE_REGION ( 5UL ) #define portFIRST_CONFIGURABLE_REGION ( 5UL )
#define portLAST_CONFIGURABLE_REGION ( 7UL ) #define portLAST_CONFIGURABLE_REGION ( 7UL )
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) #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 portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
/* Device memory attributes used in MPU_MAIR registers. /* Device memory attributes used in MPU_MAIR registers.
* *
@ -155,95 +155,96 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
* 11 --> Device-GRE * 11 --> Device-GRE
* Bit[1:0] - 00, Reserved. * Bit[1:0] - 00, Reserved.
*/ */
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
/* Normal memory attributes used in MPU_MAIR registers. */ /* Normal memory attributes used in MPU_MAIR registers. */
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ #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. */ #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
/* Attributes used in MPU_RBAR registers. */ /* Attributes used in MPU_RBAR registers. */
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) #define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) #define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) #define portMPU_REGION_EXECUTE_NEVER ( 1UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Settings to define an MPU region. * @brief Settings to define an MPU region.
*/ */
typedef struct MPURegionSettings typedef struct MPURegionSettings
{ {
uint32_t ulRBAR; /**< RBAR for the region. */ uint32_t ulRBAR; /**< RBAR for the region. */
uint32_t ulRLAR; /**< RLAR for the region. */ uint32_t ulRLAR; /**< RLAR for the region. */
} MPURegionSettings_t; } MPURegionSettings_t;
/** /**
* @brief MPU settings as stored in the TCB. * @brief MPU settings as stored in the TCB.
*/ */
typedef struct MPU_SETTINGS typedef struct MPU_SETTINGS
{ {
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ 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. */ MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
} xMPU_SETTINGS; } xMPU_SETTINGS;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief SVC numbers. * @brief SVC numbers.
*/ */
#define portSVC_ALLOCATE_SECURE_CONTEXT 0 #define portSVC_ALLOCATE_SECURE_CONTEXT 0
#define portSVC_FREE_SECURE_CONTEXT 1 #define portSVC_FREE_SECURE_CONTEXT 1
#define portSVC_START_SCHEDULER 2 #define portSVC_START_SCHEDULER 2
#define portSVC_RAISE_PRIVILEGE 3 #define portSVC_RAISE_PRIVILEGE 3
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Scheduler utilities. * @brief Scheduler utilities.
*/ */
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Critical section management. * @brief Critical section management.
*/ */
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMask( x ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) #define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) #define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Tickless idle/low power functionality. * @brief Tickless idle/low power functionality.
*/ */
#ifndef portSUPPRESS_TICKS_AND_SLEEP #ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Task function macros as described on the FreeRTOS.org WEB site. * @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_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/**
/**
* @brief Allocate a secure context for the task. * @brief Allocate a secure context for the task.
* *
* Tasks are not created with a secure context. Any task that is going to call * Tasks are not created with a secure context. Any task that is going to call
@ -254,63 +255,64 @@ typedef struct MPU_SETTINGS
*/ */
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
/** /**
* @brief Called when a task is deleted to delete the task's secure context, * @brief Called when a task is deleted to delete the task's secure context,
* if it has one. * if it has one.
* *
* @param[in] pxTCB The TCB of the task being deleted. * @param[in] pxTCB The TCB of the task being deleted.
*/ */
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
#else #else
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
#define portCLEAN_UP_TCB( pxTCB ) #define portCLEAN_UP_TCB( pxTCB )
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/**
/**
* @brief Checks whether or not the processor is privileged. * @brief Checks whether or not the processor is privileged.
* *
* @return 1 if the processor is already privileged, 0 otherwise. * @return 1 if the processor is already privileged, 0 otherwise.
*/ */
#define portIS_PRIVILEGED() xIsPrivileged() #define portIS_PRIVILEGED() xIsPrivileged()
/** /**
* @brief Raise an SVC request to raise privilege. * @brief Raise an SVC request to raise privilege.
* *
* The SVC handler checks that the SVC was raised from a system call and only * 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, * then it raises the privilege. If this is called from any other place,
* the privilege is not raised. * the privilege is not raised.
*/ */
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); #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 * @brief Lowers the privilege level by setting the bit 0 of the CONTROL
* register. * register.
*/ */
#define portRESET_PRIVILEGE() vResetPrivilege() #define portRESET_PRIVILEGE() vResetPrivilege()
#else #else
#define portIS_PRIVILEGED() #define portIS_PRIVILEGED()
#define portRAISE_PRIVILEGE() #define portRAISE_PRIVILEGE()
#define portRESET_PRIVILEGE() #define portRESET_PRIVILEGE()
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Barriers. * @brief Barriers.
*/ */
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in /* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
* the source code because to do so would cause other compilers to generate * the source code because to do so would cause other compilers to generate
* warnings. */ * warnings. */
#pragma diag_suppress=Be006 #pragma diag_suppress=Be006
#pragma diag_suppress=Pa082 #pragma diag_suppress=Pa082
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -25,11 +25,11 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -41,109 +41,109 @@ extern "C" {
*------------------------------------------------------------------------------ *------------------------------------------------------------------------------
*/ */
#ifndef configENABLE_FPU #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. #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 */ #endif /* configENABLE_FPU */
#ifndef configENABLE_MPU #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. #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 */ #endif /* configENABLE_MPU */
#ifndef configENABLE_TRUSTZONE #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. #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 */ #endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Type definitions. * @brief Type definitions.
*/ */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 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. */ * not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* Architecture specifics. * Architecture specifics.
*/ */
#define portARCH_NAME "Cortex-M33" #define portARCH_NAME "Cortex-M33"
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portNOP() #define portNOP()
#define portINLINE __inline #define portINLINE __inline
#ifndef portFORCE_INLINE #ifndef portFORCE_INLINE
#define portFORCE_INLINE inline __attribute__(( always_inline )) #define portFORCE_INLINE inline __attribute__( ( always_inline ) )
#endif #endif
#define portHAS_STACK_OVERFLOW_CHECKING 1 #define portHAS_STACK_OVERFLOW_CHECKING 1
#define portDONT_DISCARD __root #define portDONT_DISCARD __root
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Extern declarations. * @brief Extern declarations.
*/ */
extern BaseType_t xPortIsInsideInterrupt( void ); extern BaseType_t xPortIsInsideInterrupt( void );
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief MPU specific constants. * @brief MPU specific constants.
*/ */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
#define portUSING_MPU_WRAPPERS 1 #define portUSING_MPU_WRAPPERS 1
#define portPRIVILEGE_BIT ( 0x80000000UL ) #define portPRIVILEGE_BIT ( 0x80000000UL )
#else #else
#define portPRIVILEGE_BIT ( 0x0UL ) #define portPRIVILEGE_BIT ( 0x0UL )
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/* MPU regions. */ /* MPU regions. */
#define portPRIVILEGED_FLASH_REGION ( 0UL ) #define portPRIVILEGED_FLASH_REGION ( 0UL )
#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) #define portUNPRIVILEGED_FLASH_REGION ( 1UL )
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
#define portPRIVILEGED_RAM_REGION ( 3UL ) #define portPRIVILEGED_RAM_REGION ( 3UL )
#define portSTACK_REGION ( 4UL ) #define portSTACK_REGION ( 4UL )
#define portFIRST_CONFIGURABLE_REGION ( 5UL ) #define portFIRST_CONFIGURABLE_REGION ( 5UL )
#define portLAST_CONFIGURABLE_REGION ( 7UL ) #define portLAST_CONFIGURABLE_REGION ( 7UL )
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) #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 portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
/* Device memory attributes used in MPU_MAIR registers. /* Device memory attributes used in MPU_MAIR registers.
* *
@ -155,95 +155,96 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
* 11 --> Device-GRE * 11 --> Device-GRE
* Bit[1:0] - 00, Reserved. * Bit[1:0] - 00, Reserved.
*/ */
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
/* Normal memory attributes used in MPU_MAIR registers. */ /* Normal memory attributes used in MPU_MAIR registers. */
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ #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. */ #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
/* Attributes used in MPU_RBAR registers. */ /* Attributes used in MPU_RBAR registers. */
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) #define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) #define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) #define portMPU_REGION_EXECUTE_NEVER ( 1UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Settings to define an MPU region. * @brief Settings to define an MPU region.
*/ */
typedef struct MPURegionSettings typedef struct MPURegionSettings
{ {
uint32_t ulRBAR; /**< RBAR for the region. */ uint32_t ulRBAR; /**< RBAR for the region. */
uint32_t ulRLAR; /**< RLAR for the region. */ uint32_t ulRLAR; /**< RLAR for the region. */
} MPURegionSettings_t; } MPURegionSettings_t;
/** /**
* @brief MPU settings as stored in the TCB. * @brief MPU settings as stored in the TCB.
*/ */
typedef struct MPU_SETTINGS typedef struct MPU_SETTINGS
{ {
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ 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. */ MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
} xMPU_SETTINGS; } xMPU_SETTINGS;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief SVC numbers. * @brief SVC numbers.
*/ */
#define portSVC_ALLOCATE_SECURE_CONTEXT 0 #define portSVC_ALLOCATE_SECURE_CONTEXT 0
#define portSVC_FREE_SECURE_CONTEXT 1 #define portSVC_FREE_SECURE_CONTEXT 1
#define portSVC_START_SCHEDULER 2 #define portSVC_START_SCHEDULER 2
#define portSVC_RAISE_PRIVILEGE 3 #define portSVC_RAISE_PRIVILEGE 3
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Scheduler utilities. * @brief Scheduler utilities.
*/ */
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Critical section management. * @brief Critical section management.
*/ */
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMask( x ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
#define portDISABLE_INTERRUPTS() ulSetInterruptMask() #define portDISABLE_INTERRUPTS() ulSetInterruptMask()
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 ) #define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Tickless idle/low power functionality. * @brief Tickless idle/low power functionality.
*/ */
#ifndef portSUPPRESS_TICKS_AND_SLEEP #ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Task function macros as described on the FreeRTOS.org WEB site. * @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_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/**
/**
* @brief Allocate a secure context for the task. * @brief Allocate a secure context for the task.
* *
* Tasks are not created with a secure context. Any task that is going to call * Tasks are not created with a secure context. Any task that is going to call
@ -254,63 +255,64 @@ typedef struct MPU_SETTINGS
*/ */
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
/** /**
* @brief Called when a task is deleted to delete the task's secure context, * @brief Called when a task is deleted to delete the task's secure context,
* if it has one. * if it has one.
* *
* @param[in] pxTCB The TCB of the task being deleted. * @param[in] pxTCB The TCB of the task being deleted.
*/ */
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
#else #else
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
#define portCLEAN_UP_TCB( pxTCB ) #define portCLEAN_UP_TCB( pxTCB )
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/**
/**
* @brief Checks whether or not the processor is privileged. * @brief Checks whether or not the processor is privileged.
* *
* @return 1 if the processor is already privileged, 0 otherwise. * @return 1 if the processor is already privileged, 0 otherwise.
*/ */
#define portIS_PRIVILEGED() xIsPrivileged() #define portIS_PRIVILEGED() xIsPrivileged()
/** /**
* @brief Raise an SVC request to raise privilege. * @brief Raise an SVC request to raise privilege.
* *
* The SVC handler checks that the SVC was raised from a system call and only * 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, * then it raises the privilege. If this is called from any other place,
* the privilege is not raised. * the privilege is not raised.
*/ */
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); #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 * @brief Lowers the privilege level by setting the bit 0 of the CONTROL
* register. * register.
*/ */
#define portRESET_PRIVILEGE() vResetPrivilege() #define portRESET_PRIVILEGE() vResetPrivilege()
#else #else
#define portIS_PRIVILEGED() #define portIS_PRIVILEGED()
#define portRAISE_PRIVILEGE() #define portRAISE_PRIVILEGE()
#define portRESET_PRIVILEGE() #define portRESET_PRIVILEGE()
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Barriers. * @brief Barriers.
*/ */
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in /* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
* the source code because to do so would cause other compilers to generate * the source code because to do so would cause other compilers to generate
* warnings. */ * warnings. */
#pragma diag_suppress=Be006 #pragma diag_suppress=Be006
#pragma diag_suppress=Pa082 #pragma diag_suppress=Pa082
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -25,11 +25,11 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -41,109 +41,109 @@ extern "C" {
*------------------------------------------------------------------------------ *------------------------------------------------------------------------------
*/ */
#ifndef configENABLE_FPU #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. #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 */ #endif /* configENABLE_FPU */
#ifndef configENABLE_MPU #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. #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 */ #endif /* configENABLE_MPU */
#ifndef configENABLE_TRUSTZONE #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. #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 */ #endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Type definitions. * @brief Type definitions.
*/ */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 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. */ * not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* Architecture specifics. * Architecture specifics.
*/ */
#define portARCH_NAME "Cortex-M33" #define portARCH_NAME "Cortex-M33"
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portNOP() #define portNOP()
#define portINLINE __inline #define portINLINE __inline
#ifndef portFORCE_INLINE #ifndef portFORCE_INLINE
#define portFORCE_INLINE inline __attribute__(( always_inline )) #define portFORCE_INLINE inline __attribute__( ( always_inline ) )
#endif #endif
#define portHAS_STACK_OVERFLOW_CHECKING 1 #define portHAS_STACK_OVERFLOW_CHECKING 1
#define portDONT_DISCARD __root #define portDONT_DISCARD __root
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Extern declarations. * @brief Extern declarations.
*/ */
extern BaseType_t xPortIsInsideInterrupt( void ); extern BaseType_t xPortIsInsideInterrupt( void );
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief MPU specific constants. * @brief MPU specific constants.
*/ */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
#define portUSING_MPU_WRAPPERS 1 #define portUSING_MPU_WRAPPERS 1
#define portPRIVILEGE_BIT ( 0x80000000UL ) #define portPRIVILEGE_BIT ( 0x80000000UL )
#else #else
#define portPRIVILEGE_BIT ( 0x0UL ) #define portPRIVILEGE_BIT ( 0x0UL )
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/* MPU regions. */ /* MPU regions. */
#define portPRIVILEGED_FLASH_REGION ( 0UL ) #define portPRIVILEGED_FLASH_REGION ( 0UL )
#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) #define portUNPRIVILEGED_FLASH_REGION ( 1UL )
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
#define portPRIVILEGED_RAM_REGION ( 3UL ) #define portPRIVILEGED_RAM_REGION ( 3UL )
#define portSTACK_REGION ( 4UL ) #define portSTACK_REGION ( 4UL )
#define portFIRST_CONFIGURABLE_REGION ( 5UL ) #define portFIRST_CONFIGURABLE_REGION ( 5UL )
#define portLAST_CONFIGURABLE_REGION ( 7UL ) #define portLAST_CONFIGURABLE_REGION ( 7UL )
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) #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 portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
/* Device memory attributes used in MPU_MAIR registers. /* Device memory attributes used in MPU_MAIR registers.
* *
@ -155,95 +155,96 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
* 11 --> Device-GRE * 11 --> Device-GRE
* Bit[1:0] - 00, Reserved. * Bit[1:0] - 00, Reserved.
*/ */
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
/* Normal memory attributes used in MPU_MAIR registers. */ /* Normal memory attributes used in MPU_MAIR registers. */
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ #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. */ #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
/* Attributes used in MPU_RBAR registers. */ /* Attributes used in MPU_RBAR registers. */
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) #define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) #define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) #define portMPU_REGION_EXECUTE_NEVER ( 1UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Settings to define an MPU region. * @brief Settings to define an MPU region.
*/ */
typedef struct MPURegionSettings typedef struct MPURegionSettings
{ {
uint32_t ulRBAR; /**< RBAR for the region. */ uint32_t ulRBAR; /**< RBAR for the region. */
uint32_t ulRLAR; /**< RLAR for the region. */ uint32_t ulRLAR; /**< RLAR for the region. */
} MPURegionSettings_t; } MPURegionSettings_t;
/** /**
* @brief MPU settings as stored in the TCB. * @brief MPU settings as stored in the TCB.
*/ */
typedef struct MPU_SETTINGS typedef struct MPU_SETTINGS
{ {
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ 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. */ MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
} xMPU_SETTINGS; } xMPU_SETTINGS;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief SVC numbers. * @brief SVC numbers.
*/ */
#define portSVC_ALLOCATE_SECURE_CONTEXT 0 #define portSVC_ALLOCATE_SECURE_CONTEXT 0
#define portSVC_FREE_SECURE_CONTEXT 1 #define portSVC_FREE_SECURE_CONTEXT 1
#define portSVC_START_SCHEDULER 2 #define portSVC_START_SCHEDULER 2
#define portSVC_RAISE_PRIVILEGE 3 #define portSVC_RAISE_PRIVILEGE 3
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Scheduler utilities. * @brief Scheduler utilities.
*/ */
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Critical section management. * @brief Critical section management.
*/ */
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMask( x ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
#define portDISABLE_INTERRUPTS() ulSetInterruptMask() #define portDISABLE_INTERRUPTS() ulSetInterruptMask()
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 ) #define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Tickless idle/low power functionality. * @brief Tickless idle/low power functionality.
*/ */
#ifndef portSUPPRESS_TICKS_AND_SLEEP #ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Task function macros as described on the FreeRTOS.org WEB site. * @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_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/**
/**
* @brief Allocate a secure context for the task. * @brief Allocate a secure context for the task.
* *
* Tasks are not created with a secure context. Any task that is going to call * Tasks are not created with a secure context. Any task that is going to call
@ -254,63 +255,64 @@ typedef struct MPU_SETTINGS
*/ */
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
/** /**
* @brief Called when a task is deleted to delete the task's secure context, * @brief Called when a task is deleted to delete the task's secure context,
* if it has one. * if it has one.
* *
* @param[in] pxTCB The TCB of the task being deleted. * @param[in] pxTCB The TCB of the task being deleted.
*/ */
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
#else #else
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
#define portCLEAN_UP_TCB( pxTCB ) #define portCLEAN_UP_TCB( pxTCB )
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/**
/**
* @brief Checks whether or not the processor is privileged. * @brief Checks whether or not the processor is privileged.
* *
* @return 1 if the processor is already privileged, 0 otherwise. * @return 1 if the processor is already privileged, 0 otherwise.
*/ */
#define portIS_PRIVILEGED() xIsPrivileged() #define portIS_PRIVILEGED() xIsPrivileged()
/** /**
* @brief Raise an SVC request to raise privilege. * @brief Raise an SVC request to raise privilege.
* *
* The SVC handler checks that the SVC was raised from a system call and only * 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, * then it raises the privilege. If this is called from any other place,
* the privilege is not raised. * the privilege is not raised.
*/ */
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); #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 * @brief Lowers the privilege level by setting the bit 0 of the CONTROL
* register. * register.
*/ */
#define portRESET_PRIVILEGE() vResetPrivilege() #define portRESET_PRIVILEGE() vResetPrivilege()
#else #else
#define portIS_PRIVILEGED() #define portIS_PRIVILEGED()
#define portRAISE_PRIVILEGE() #define portRAISE_PRIVILEGE()
#define portRESET_PRIVILEGE() #define portRESET_PRIVILEGE()
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Barriers. * @brief Barriers.
*/ */
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in /* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
* the source code because to do so would cause other compilers to generate * the source code because to do so would cause other compilers to generate
* warnings. */ * warnings. */
#pragma diag_suppress=Be006 #pragma diag_suppress=Be006
#pragma diag_suppress=Pa082 #pragma diag_suppress=Pa082
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -37,14 +37,14 @@
* @brief Restore the context of the first task so that the first task starts * @brief Restore the context of the first task so that the first task starts
* executing. * executing.
*/ */
void vRestoreContextOfFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; void vRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/** /**
* @brief Checks whether or not the processor is privileged. * @brief Checks whether or not the processor is privileged.
* *
* @return 1 if the processor is already privileged, 0 otherwise. * @return 1 if the processor is already privileged, 0 otherwise.
*/ */
BaseType_t xIsPrivileged( void ) __attribute__ (( naked )); BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) );
/** /**
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL * @brief Raises the privilege level by clearing the bit 0 of the CONTROL
@ -57,7 +57,7 @@ BaseType_t xIsPrivileged( void ) __attribute__ (( naked ));
* Bit[0] = 0 --> The processor is running privileged * Bit[0] = 0 --> The processor is running privileged
* Bit[0] = 1 --> The processor is running unprivileged. * Bit[0] = 1 --> The processor is running unprivileged.
*/ */
void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/** /**
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL * @brief Lowers the privilege level by setting the bit 0 of the CONTROL
@ -67,32 +67,32 @@ void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
* Bit[0] = 0 --> The processor is running privileged * Bit[0] = 0 --> The processor is running privileged
* Bit[0] = 1 --> The processor is running unprivileged. * Bit[0] = 1 --> The processor is running unprivileged.
*/ */
void vResetPrivilege( void ) __attribute__ (( naked )); void vResetPrivilege( void ) __attribute__( ( naked ) );
/** /**
* @brief Starts the first task. * @brief Starts the first task.
*/ */
void vStartFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/** /**
* @brief Disables interrupts. * @brief Disables interrupts.
*/ */
uint32_t ulSetInterruptMask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION; uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/** /**
* @brief Enables interrupts. * @brief Enables interrupts.
*/ */
void vClearInterruptMask( uint32_t ulMask ) __attribute__(( naked )) PRIVILEGED_FUNCTION; void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/** /**
* @brief PendSV Exception handler. * @brief PendSV Exception handler.
*/ */
void PendSV_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/** /**
* @brief SVC Handler. * @brief SVC Handler.
*/ */
void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/** /**
* @brief Allocate a Secure context for the calling task. * @brief Allocate a Secure context for the calling task.
@ -100,13 +100,13 @@ void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
* @param[in] ulSecureStackSize The size of the stack to be allocated on the * @param[in] ulSecureStackSize The size of the stack to be allocated on the
* secure side for the calling task. * secure side for the calling task.
*/ */
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__ (( naked )); void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__( ( naked ) );
/** /**
* @brief Free the task's secure context. * @brief Free the task's secure context.
* *
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task. * @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
*/ */
void vPortFreeSecureContext( uint32_t *pulTCB ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
#endif /* __PORT_ASM_H__ */ #endif /* __PORT_ASM_H__ */

View file

@ -30,7 +30,7 @@
/* Secure port macros. */ /* Secure port macros. */
#include "secure_port_macros.h" #include "secure_port_macros.h"
#if( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0. #error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
#endif #endif
@ -41,20 +41,20 @@ secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandl
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r1, ipsr \n" /* r1 = IPSR. */ " mrs r1, ipsr \n"/* r1 = IPSR. */
" cbz r1, load_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */ " 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. */ " ldmia r0!, {r1, r2} \n"/* r1 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldmia r1!, {r3} \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */ " ldmia r1!, {r3} \n"/* Read CONTROL register value from task's stack. r3 = CONTROL. */
" msr control, r3 \n" /* CONTROL = r3. */ " msr control, r3 \n"/* CONTROL = r3. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" msr psplim, r2 \n" /* PSPLIM = r2. */ " msr psplim, r2 \n"/* PSPLIM = r2. */
" msr psp, r1 \n" /* PSP = r1. */ " msr psp, r1 \n"/* PSP = r1. */
" \n" " \n"
" load_ctx_therad_mode: \n" " load_ctx_therad_mode: \n"
" nop \n" " nop \n"
" \n" " \n"
:::"r0", "r1", "r2" ::: "r0", "r1", "r2"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -66,25 +66,25 @@ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandl
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r1, ipsr \n" /* r1 = IPSR. */ " mrs r1, ipsr \n"/* r1 = IPSR. */
" cbz r1, save_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */ " cbz r1, save_ctx_therad_mode \n"/* Do nothing if the processor is running in the Thread Mode. */
" mrs r1, psp \n" /* r1 = PSP. */ " mrs r1, psp \n"/* r1 = PSP. */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" mrs r2, control \n" /* r2 = CONTROL. */ " mrs r2, control \n"/* r2 = CONTROL. */
" subs r1, r1, #4 \n" /* Make space for the CONTROL value on the stack. */ " subs r1, r1, #4 \n"/* Make space for the CONTROL value on the stack. */
" str r1, [r0] \n" /* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */ " str r1, [r0] \n"/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */
" stmia r1!, {r2} \n" /* Store CONTROL value on the stack. */ " stmia r1!, {r2} \n"/* Store CONTROL value on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" str r1, [r0] \n" /* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */ " str r1, [r0] \n"/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" movs r1, %0 \n" /* r1 = securecontextNO_STACK. */ " movs r1, %0 \n"/* r1 = securecontextNO_STACK. */
" msr psplim, r1 \n" /* PSPLIM = 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. */ " msr psp, r1 \n"/* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
" \n" " \n"
" save_ctx_therad_mode: \n" " save_ctx_therad_mode: \n"
" nop \n" " nop \n"
" \n" " \n"
:: "i" ( securecontextNO_STACK ) : "r1", "memory" ::"i" ( securecontextNO_STACK ) : "r1", "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -37,20 +37,20 @@ secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandl
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r1, ipsr \n" /* r1 = IPSR. */ " mrs r1, ipsr \n"/* r1 = IPSR. */
" cbz r1, load_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */ " 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. */ " ldmia r0!, {r1, r2} \n"/* r1 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldmia r1!, {r3} \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */ " ldmia r1!, {r3} \n"/* Read CONTROL register value from task's stack. r3 = CONTROL. */
" msr control, r3 \n" /* CONTROL = r3. */ " msr control, r3 \n"/* CONTROL = r3. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" msr psplim, r2 \n" /* PSPLIM = r2. */ " msr psplim, r2 \n"/* PSPLIM = r2. */
" msr psp, r1 \n" /* PSP = r1. */ " msr psp, r1 \n"/* PSP = r1. */
" \n" " \n"
" load_ctx_therad_mode: \n" " load_ctx_therad_mode: \n"
" nop \n" " nop \n"
" \n" " \n"
:::"r0", "r1", "r2" ::: "r0", "r1", "r2"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -62,26 +62,26 @@ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandl
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r1, ipsr \n" /* r1 = IPSR. */ " mrs r1, ipsr \n"/* r1 = IPSR. */
" cbz r1, save_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */ " cbz r1, save_ctx_therad_mode \n"/* Do nothing if the processor is running in the Thread Mode. */
" mrs r1, psp \n" /* r1 = PSP. */ " mrs r1, psp \n"/* r1 = PSP. */
#if( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
" vstmdb r1!, {s0} \n" /* Trigger the defferred stacking of FPU registers. */ " vstmdb r1!, {s0} \n"/* Trigger the defferred stacking of FPU registers. */
" vldmia r1!, {s0} \n" /* Nullify the effect of the pervious statement. */ " vldmia r1!, {s0} \n"/* Nullify the effect of the pervious statement. */
#endif /* configENABLE_FPU */ #endif /* configENABLE_FPU */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" mrs r2, control \n" /* r2 = CONTROL. */ " mrs r2, control \n"/* r2 = CONTROL. */
" stmdb r1!, {r2} \n" /* Store CONTROL value on the stack. */ " stmdb r1!, {r2} \n"/* Store CONTROL value on the stack. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" str r1, [r0] \n" /* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */ " str r1, [r0] \n"/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */
" movs r1, %0 \n" /* r1 = securecontextNO_STACK. */ " movs r1, %0 \n"/* r1 = securecontextNO_STACK. */
" msr psplim, r1 \n" /* PSPLIM = 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. */ " msr psp, r1 \n"/* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
" \n" " \n"
" save_ctx_therad_mode: \n" " save_ctx_therad_mode: \n"
" nop \n" " nop \n"
" \n" " \n"
:: "i" ( securecontextNO_STACK ) : "r1", "memory" ::"i" ( securecontextNO_STACK ) : "r1", "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -58,9 +58,9 @@
*/ */
typedef struct SecureContext typedef struct SecureContext
{ {
uint8_t *pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */ uint8_t * pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
uint8_t *pucStackLimit; /**< Last location of the stack memory (PSPLIM). */ uint8_t * pucStackLimit; /**< Last location of the stack memory (PSPLIM). */
uint8_t *pucStackStart; /**< First location of the stack memory. */ uint8_t * pucStackStart; /**< First location of the stack memory. */
} SecureContext_t; } SecureContext_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -79,7 +79,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
secureportSET_PSPLIM( securecontextNO_STACK ); secureportSET_PSPLIM( securecontextNO_STACK );
secureportSET_PSP( securecontextNO_STACK ); secureportSET_PSP( securecontextNO_STACK );
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
/* Configure thread mode to use PSP and to be unprivileged. */ /* Configure thread mode to use PSP and to be unprivileged. */
secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED ); secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );
@ -94,17 +94,19 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged ) secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
uint32_t ulIsTaskPrivileged )
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize ) secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize )
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
{ {
uint8_t *pucStackMemory = NULL; uint8_t * pucStackMemory = NULL;
uint32_t ulIPSR; uint32_t ulIPSR;
SecureContextHandle_t xSecureContextHandle = NULL; SecureContextHandle_t xSecureContextHandle = NULL;
#if( configENABLE_MPU == 1 )
uint32_t *pulCurrentStackPointer = NULL; #if ( configENABLE_MPU == 1 )
uint32_t * pulCurrentStackPointer = NULL;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/* Read the Interrupt Program Status Register (IPSR) value. */ /* Read the Interrupt Program Status Register (IPSR) value. */
@ -136,13 +138,14 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
* programmed in the PSPLIM register on context switch.*/ * programmed in the PSPLIM register on context switch.*/
xSecureContextHandle->pucStackLimit = pucStackMemory; xSecureContextHandle->pucStackLimit = pucStackMemory;
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
/* Store the correct CONTROL value for the task on the stack. /* Store the correct CONTROL value for the task on the stack.
* This value is programmed in the CONTROL register on * This value is programmed in the CONTROL register on
* context switch. */ * context switch. */
pulCurrentStackPointer = ( uint32_t * ) xSecureContextHandle->pucStackStart; pulCurrentStackPointer = ( uint32_t * ) xSecureContextHandle->pucStackStart;
pulCurrentStackPointer--; pulCurrentStackPointer--;
if( ulIsTaskPrivileged ) if( ulIsTaskPrivileged )
{ {
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED; *( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
@ -161,7 +164,6 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
/* Current SP is set to the starting of the stack. This /* Current SP is set to the starting of the stack. This
* value programmed in the PSP register on context switch. */ * value programmed in the PSP register on context switch. */
xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart; xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart;
} }
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
} }

View file

@ -42,7 +42,7 @@
* @brief Opaque handle. * @brief Opaque handle.
*/ */
struct SecureContext; struct SecureContext;
typedef struct SecureContext* SecureContextHandle_t; typedef struct SecureContext * SecureContextHandle_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -68,8 +68,9 @@ void SecureContext_Init( void );
* @return Opaque context handle if context is successfully allocated, NULL * @return Opaque context handle if context is successfully allocated, NULL
* otherwise. * otherwise.
*/ */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged ); SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
uint32_t ulIsTaskPrivileged );
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize ); SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize );
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */

View file

@ -61,9 +61,10 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Allocate the memory for the heap. */ /* Allocate the memory for the heap. */
#if( configAPPLICATION_ALLOCATED_HEAP == 1 ) #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. */ /* 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 ]; extern uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
#else /* configAPPLICATION_ALLOCATED_HEAP */ #else /* configAPPLICATION_ALLOCATED_HEAP */
static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ]; static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
@ -76,7 +77,7 @@
*/ */
typedef struct A_BLOCK_LINK typedef struct A_BLOCK_LINK
{ {
struct A_BLOCK_LINK *pxNextFreeBlock; /**< The next free block in the list. */ struct A_BLOCK_LINK * pxNextFreeBlock; /**< The next free block in the list. */
size_t xBlockSize; /**< The size of the free block. */ size_t xBlockSize; /**< The size of the free block. */
} BlockLink_t; } BlockLink_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -96,7 +97,7 @@ static void prvHeapInit( void );
* *
* @param[in] pxBlockToInsert The block being freed. * @param[in] pxBlockToInsert The block being freed.
*/ */
static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ); static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -108,7 +109,7 @@ static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( s
/** /**
* @brief Create a couple of list links to mark the start and end of the list. * @brief Create a couple of list links to mark the start and end of the list.
*/ */
static BlockLink_t xStart, *pxEnd = NULL; static BlockLink_t xStart, * pxEnd = NULL;
/** /**
* @brief Keeps track of the number of free bytes remaining, but says nothing * @brief Keeps track of the number of free bytes remaining, but says nothing
@ -129,10 +130,10 @@ static size_t xBlockAllocatedBit = 0;
static void prvHeapInit( void ) static void prvHeapInit( void )
{ {
BlockLink_t *pxFirstFreeBlock; BlockLink_t * pxFirstFreeBlock;
uint8_t *pucAlignedHeap; uint8_t * pucAlignedHeap;
size_t uxAddress; size_t uxAddress;
size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE; size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
/* Ensure the heap starts on a correctly aligned boundary. */ /* Ensure the heap starts on a correctly aligned boundary. */
uxAddress = ( size_t ) ucHeap; uxAddress = ( size_t ) ucHeap;
@ -175,10 +176,10 @@ size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ) static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert )
{ {
BlockLink_t *pxIterator; BlockLink_t * pxIterator;
uint8_t *puc; uint8_t * puc;
/* Iterate through the list until a block is found that has a higher address /* Iterate through the list until a block is found that has a higher address
* than the block being inserted. */ * than the block being inserted. */
@ -190,6 +191,7 @@ uint8_t *puc;
/* Do the block being inserted, and the block it is being inserted after /* Do the block being inserted, and the block it is being inserted after
* make a contiguous block of memory? */ * make a contiguous block of memory? */
puc = ( uint8_t * ) pxIterator; puc = ( uint8_t * ) pxIterator;
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert ) if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
{ {
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize; pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
@ -203,6 +205,7 @@ uint8_t *puc;
/* Do the block being inserted, and the block it is being inserted before /* Do the block being inserted, and the block it is being inserted before
* make a contiguous block of memory? */ * make a contiguous block of memory? */
puc = ( uint8_t * ) pxBlockToInsert; puc = ( uint8_t * ) pxBlockToInsert;
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock ) if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
{ {
if( pxIterator->pxNextFreeBlock != pxEnd ) if( pxIterator->pxNextFreeBlock != pxEnd )
@ -236,10 +239,10 @@ uint8_t *puc;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void *pvPortMalloc( size_t xWantedSize ) void * pvPortMalloc( size_t xWantedSize )
{ {
BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; BlockLink_t * pxBlock, * pxPreviousBlock, * pxNewBlockLink;
void *pvReturn = NULL; void * pvReturn = NULL;
/* If this is the first call to malloc then the heap will require /* If this is the first call to malloc then the heap will require
* initialisation to setup the list of free blocks. */ * initialisation to setup the list of free blocks. */
@ -288,6 +291,7 @@ void *pvReturn = NULL;
* one of adequate size is found. */ * one of adequate size is found. */
pxPreviousBlock = &xStart; pxPreviousBlock = &xStart;
pxBlock = xStart.pxNextFreeBlock; pxBlock = xStart.pxNextFreeBlock;
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
{ {
pxPreviousBlock = pxBlock; pxPreviousBlock = pxBlock;
@ -363,7 +367,7 @@ void *pvReturn = NULL;
traceMALLOC( pvReturn, xWantedSize ); traceMALLOC( pvReturn, xWantedSize );
#if( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) #if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 )
{ {
if( pvReturn == NULL ) if( pvReturn == NULL )
{ {
@ -375,17 +379,17 @@ void *pvReturn = NULL;
mtCOVERAGE_TEST_MARKER(); mtCOVERAGE_TEST_MARKER();
} }
} }
#endif #endif /* if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) */
secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 ); secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
return pvReturn; return pvReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortFree( void *pv ) void vPortFree( void * pv )
{ {
uint8_t *puc = ( uint8_t * ) pv; uint8_t * puc = ( uint8_t * ) pv;
BlockLink_t *pxLink; BlockLink_t * pxLink;
if( pv != NULL ) if( pv != NULL )
{ {

View file

@ -38,13 +38,13 @@
* @return Pointer to the memory region if the allocation is successful, NULL * @return Pointer to the memory region if the allocation is successful, NULL
* otherwise. * otherwise.
*/ */
void *pvPortMalloc( size_t xWantedSize ); void * pvPortMalloc( size_t xWantedSize );
/** /**
* @brief Frees the previously allocated memory. * @brief Frees the previously allocated memory.
* *
* @param[in] pv Pointer to the memory to be freed. * @param[in] pv Pointer to the memory to be freed.
*/ */
void vPortFree( void *pv ); void vPortFree( void * pv );
#endif /* __SECURE_HEAP_H__ */ #endif /* __SECURE_HEAP_H__ */

View file

@ -93,7 +93,7 @@ secureportNON_SECURE_CALLABLE void SecureInit_EnableNSFPUAccess( void )
/* LSPENS = 0 ==> LSPEN is writable fron non-secure state. This ensures /* LSPENS = 0 ==> LSPEN is writable fron non-secure state. This ensures
* that we can enable/disable lazy stacking in port.c file. */ * that we can enable/disable lazy stacking in port.c file. */
*( secureinitFPCCR ) &= ~ ( secureinitFPCCR_LSPENS_MASK ); *( secureinitFPCCR ) &= ~( secureinitFPCCR_LSPENS_MASK );
/* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP /* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP
* registers (S16-S31) are also pushed to stack on exception entry and * registers (S16-S31) are also pushed to stack on exception entry and

View file

@ -39,7 +39,7 @@
#if defined( __IAR_SYSTEMS_ICC__ ) #if defined( __IAR_SYSTEMS_ICC__ )
#define secureportNON_SECURE_CALLABLE __cmse_nonsecure_entry __root #define secureportNON_SECURE_CALLABLE __cmse_nonsecure_entry __root
#else #else
#define secureportNON_SECURE_CALLABLE __attribute__((cmse_nonsecure_entry)) __attribute__((used)) #define secureportNON_SECURE_CALLABLE __attribute__( ( cmse_nonsecure_entry ) ) __attribute__( ( used ) )
#endif #endif
/** /**
@ -126,7 +126,7 @@
{ \ { \
secureportDISABLE_SECURE_INTERRUPTS(); \ secureportDISABLE_SECURE_INTERRUPTS(); \
secureportDISABLE_NON_SECURE_INTERRUPTS(); \ secureportDISABLE_NON_SECURE_INTERRUPTS(); \
for( ;; ); \ for( ; ; ) {; } \
} }
#endif /* __SECURE_PORT_MACROS_H__ */ #endif /* __SECURE_PORT_MACROS_H__ */

View file

@ -25,22 +25,22 @@
*/ */
/* /*
Changes from V1.00: * Changes from V1.00:
*
+ Call to taskYIELD() from within tick ISR has been replaced by the more + Call to taskYIELD() from within tick ISR has been replaced by the more
efficient portSWITCH_CONTEXT(). + efficient portSWITCH_CONTEXT().
+ ISR function definitions renamed to include the prv prefix. + ISR function definitions renamed to include the prv prefix.
+
Changes from V2.6.1 + Changes from V2.6.1
+
+ Replaced the sUsingPreemption variable with the configUSE_PREEMPTION + Replaced the sUsingPreemption variable with the configUSE_PREEMPTION
macro to be consistent with the later ports. + macro to be consistent with the later ports.
*/ */
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the Flashlite 186 * Implementation of functions defined in portable.h for the Flashlite 186
* port. * port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
#include <dos.h> #include <dos.h>
#include <stdlib.h> #include <stdlib.h>
@ -67,14 +67,16 @@ static void prvSetTickFrequency( uint32_t ulTickRateHz );
static void prvExitFunction( void ); static void prvExitFunction( void );
/* The ISR used depends on whether the preemptive or cooperative scheduler /* The ISR used depends on whether the preemptive or cooperative scheduler
is being used. */ * is being used. */
#if( configUSE_PREEMPTION == 1 ) #if ( configUSE_PREEMPTION == 1 )
/* Tick service routine used by the scheduler when preemptive scheduling is
being used. */ /* Tick service routine used by the scheduler when preemptive scheduling is
* being used. */
static void __interrupt __far prvPreemptiveTick( void ); static void __interrupt __far prvPreemptiveTick( void );
#else #else
/* Tick service routine used by the scheduler when cooperative scheduling is
being used. */ /* Tick service routine used by the scheduler when cooperative scheduling is
* being used. */
static void __interrupt __far prvNonPreemptiveTick( void ); static void __interrupt __far prvNonPreemptiveTick( void );
#endif #endif
@ -87,9 +89,9 @@ static void __interrupt __far prvYieldProcessor( void );
static BaseType_t xSchedulerRunning = pdFALSE; static BaseType_t xSchedulerRunning = pdFALSE;
/* Points to the original routine installed on the vector we use for manual /* Points to the original routine installed on the vector we use for manual
context switches. This is then used to restore the original routine during * context switches. This is then used to restore the original routine during
prvExitFunction(). */ * prvExitFunction(). */
static void ( __interrupt __far *pxOldSwitchISR )(); static void( __interrupt __far * pxOldSwitchISR )();
/* Used to restore the original DOS context when the scheduler is ended. */ /* Used to restore the original DOS context when the scheduler is ended. */
static jmp_buf xJumpBuf; static jmp_buf xJumpBuf;
@ -102,14 +104,14 @@ BaseType_t xPortStartScheduler( void )
/* This is called with interrupts already disabled. */ /* This is called with interrupts already disabled. */
/* Remember what was on the interrupts we are going to use /* Remember what was on the interrupts we are going to use
so we can put them back later if required. */ * so we can put them back later if required. */
pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER ); pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER );
/* Put our manual switch (yield) function on a known /* Put our manual switch (yield) function on a known
vector. */ * vector. */
_dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor ); _dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
#if( configUSE_PREEMPTION == 1 ) #if ( configUSE_PREEMPTION == 1 )
{ {
/* Put our tick switch function on the timer interrupt. */ /* Put our tick switch function on the timer interrupt. */
_dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick ); _dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick );
@ -142,8 +144,8 @@ BaseType_t xPortStartScheduler( void )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* The ISR used depends on whether the preemptive or cooperative scheduler /* The ISR used depends on whether the preemptive or cooperative scheduler
is being used. */ * is being used. */
#if( configUSE_PREEMPTION == 1 ) #if ( configUSE_PREEMPTION == 1 )
static void __interrupt __far prvPreemptiveTick( void ) static void __interrupt __far prvPreemptiveTick( void )
{ {
/* Get the scheduler to update the task states following the tick. */ /* Get the scheduler to update the task states following the tick. */
@ -156,15 +158,15 @@ is being used. */
/* Reset the PIC ready for the next time. */ /* Reset the PIC ready for the next time. */
portRESET_PIC(); portRESET_PIC();
} }
#else #else /* if ( configUSE_PREEMPTION == 1 ) */
static void __interrupt __far prvNonPreemptiveTick( void ) static void __interrupt __far prvNonPreemptiveTick( void )
{ {
/* Same as preemptive tick, but the cooperative scheduler is being used /* Same as preemptive tick, but the cooperative scheduler is being used
so we don't have to switch in the context of the next task. */ * so we don't have to switch in the context of the next task. */
xTaskIncrementTick(); xTaskIncrementTick();
portRESET_PIC(); portRESET_PIC();
} }
#endif #endif /* if ( configUSE_PREEMPTION == 1 ) */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void __interrupt __far prvYieldProcessor( void ) static void __interrupt __far prvYieldProcessor( void )
@ -177,30 +179,31 @@ static void __interrupt __far prvYieldProcessor( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Jump back to the processor state prior to starting the /* Jump back to the processor state prior to starting the
scheduler. This means we are not going to be using a * scheduler. This means we are not going to be using a
task stack frame so the task can be deleted. */ * task stack frame so the task can be deleted. */
longjmp( xJumpBuf, 1 ); longjmp( xJumpBuf, 1 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvExitFunction( void ) static void prvExitFunction( void )
{ {
const uint16_t usTimerDisable = 0x0000; const uint16_t usTimerDisable = 0x0000;
uint16_t usTimer0Control; uint16_t usTimer0Control;
/* Interrupts should be disabled here anyway - but no /* Interrupts should be disabled here anyway - but no
harm in making sure. */ * harm in making sure. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
if( xSchedulerRunning == pdTRUE ) if( xSchedulerRunning == pdTRUE )
{ {
/* Put back the switch interrupt routines that was in place /* Put back the switch interrupt routines that was in place
before the scheduler started. */ * before the scheduler started. */
_dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR ); _dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR );
} }
/* Disable the timer used for the tick to ensure the scheduler is /* Disable the timer used for the tick to ensure the scheduler is
not called before restoring interrupts. There was previously nothing * not called before restoring interrupts. There was previously nothing
on this timer so there is no old ISR to restore. */ * on this timer so there is no old ISR to restore. */
portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerDisable ); portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerDisable );
/* Restart the DOS tick. */ /* Restart the DOS tick. */
@ -215,18 +218,18 @@ uint16_t usTimer0Control;
static void prvSetTickFrequency( uint32_t ulTickRateHz ) static void prvSetTickFrequency( uint32_t ulTickRateHz )
{ {
const uint16_t usMaxCountRegister = 0xff5a; const uint16_t usMaxCountRegister = 0xff5a;
const uint16_t usTimerPriorityRegister = 0xff32; const uint16_t usTimerPriorityRegister = 0xff32;
const uint16_t usTimerEnable = 0xC000; const uint16_t usTimerEnable = 0xC000;
const uint16_t usRetrigger = 0x0001; const uint16_t usRetrigger = 0x0001;
const uint16_t usTimerHighPriority = 0x0000; const uint16_t usTimerHighPriority = 0x0000;
uint16_t usTimer0Control; uint16_t usTimer0Control;
/* ( CPU frequency / 4 ) / clock 2 max count [inpw( 0xff62 ) = 7] */ /* ( CPU frequency / 4 ) / clock 2 max count [inpw( 0xff62 ) = 7] */
const uint32_t ulClockFrequency = ( uint32_t ) 0x7f31a0UL; const uint32_t ulClockFrequency = ( uint32_t ) 0x7f31a0UL;
uint32_t ulTimerCount = ulClockFrequency / ulTickRateHz; uint32_t ulTimerCount = ulClockFrequency / ulTickRateHz;
portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerEnable | portTIMER_INTERRUPT_ENABLE | usRetrigger ); portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerEnable | portTIMER_INTERRUPT_ENABLE | usRetrigger );
portOUTPUT_WORD( usMaxCountRegister, ( uint16_t ) ulTimerCount ); portOUTPUT_WORD( usMaxCountRegister, ( uint16_t ) ulTimerCount );
@ -240,4 +243,3 @@ uint32_t ulTimerCount = ulClockFrequency / ulTickRateHz;
/*lint +e950 */ /*lint +e950 */

View file

@ -50,7 +50,7 @@ typedef portSTACK_TYPE StackType_t;
typedef short BaseType_t; typedef short BaseType_t;
typedef unsigned short UBaseType_t; typedef unsigned short UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
@ -60,7 +60,8 @@ typedef unsigned short UBaseType_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section handling. */ /* Critical section handling. */
#define portENTER_CRITICAL() __asm{ pushf } \ #define portENTER_CRITICAL() \
__asm{ pushf } \
__asm{ cli } \ __asm{ cli } \
#define portEXIT_CRITICAL() __asm{ popf } #define portEXIT_CRITICAL() __asm{ popf }
@ -89,8 +90,7 @@ typedef unsigned short UBaseType_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vTaskFunction, vParameters ) void vTaskFunction( void * pvParameters )
#define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters ) #define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void * pvParameters )
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -25,16 +25,16 @@
*/ */
/* /*
Changes from V2.6.1 * Changes from V2.6.1
*
+ Replaced the sUsingPreemption variable with the configUSE_PREEMPTION + Replaced the sUsingPreemption variable with the configUSE_PREEMPTION
macro to be consistent with the later ports. + macro to be consistent with the later ports.
+
Changes from V4.0.1 + Changes from V4.0.1
+
+ Add function prvSetTickFrequencyDefault() to set the DOS tick back to + Add function prvSetTickFrequencyDefault() to set the DOS tick back to
its proper value when the scheduler exits. + its proper value when the scheduler exits.
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <dos.h> #include <dos.h>
@ -45,9 +45,9 @@ Changes from V4.0.1
#include "portasm.h" #include "portasm.h"
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the industrial * Implementation of functions defined in portable.h for the industrial
* PC port. * PC port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/*lint -e950 Non ANSI reserved words okay in this file only. */ /*lint -e950 Non ANSI reserved words okay in this file only. */
@ -60,19 +60,21 @@ static void prvSetTickFrequency( uint32_t ulTickRateHz );
static void prvExitFunction( void ); static void prvExitFunction( void );
/* Either chain to the DOS tick (which itself clears the PIC) or clear the PIC /* Either chain to the DOS tick (which itself clears the PIC) or clear the PIC
directly. We chain to the DOS tick as close as possible to the standard DOS * directly. We chain to the DOS tick as close as possible to the standard DOS
tick rate. */ * tick rate. */
static void prvPortResetPIC( void ); static void prvPortResetPIC( void );
/* The ISR used depends on whether the preemptive or cooperative /* The ISR used depends on whether the preemptive or cooperative
scheduler is being used. */ * scheduler is being used. */
#if( configUSE_PREEMPTION == 1 ) #if ( configUSE_PREEMPTION == 1 )
/* Tick service routine used by the scheduler when preemptive scheduling is
being used. */ /* Tick service routine used by the scheduler when preemptive scheduling is
* being used. */
static void __interrupt __far prvPreemptiveTick( void ); static void __interrupt __far prvPreemptiveTick( void );
#else #else
/* Tick service routine used by the scheduler when cooperative scheduling is
being used. */ /* Tick service routine used by the scheduler when cooperative scheduling is
* being used. */
static void __interrupt __far prvNonPreemptiveTick( void ); static void __interrupt __far prvNonPreemptiveTick( void );
#endif #endif
@ -80,7 +82,7 @@ scheduler is being used. */
static void __interrupt __far prvYieldProcessor( void ); static void __interrupt __far prvYieldProcessor( void );
/* Set the tick frequency back so the floppy drive works correctly when the /* Set the tick frequency back so the floppy drive works correctly when the
scheduler exits. */ * scheduler exits. */
static void prvSetTickFrequencyDefault( void ); static void prvSetTickFrequencyDefault( void );
/*lint -e956 File scopes necessary here. */ /*lint -e956 File scopes necessary here. */
@ -92,10 +94,10 @@ static int16_t sDOSTickCounter;
static BaseType_t xSchedulerRunning = pdFALSE; static BaseType_t xSchedulerRunning = pdFALSE;
/* Points to the original routine installed on the vector we use for manual context switches. This is then used to restore the original routine during prvExitFunction(). */ /* Points to the original routine installed on the vector we use for manual context switches. This is then used to restore the original routine during prvExitFunction(). */
static void ( __interrupt __far *pxOldSwitchISR )(); static void( __interrupt __far * pxOldSwitchISR )();
/* Points to the original routine installed on the vector we use to chain to the DOS tick. This is then used to restore the original routine during prvExitFunction(). */ /* Points to the original routine installed on the vector we use to chain to the DOS tick. This is then used to restore the original routine during prvExitFunction(). */
static void ( __interrupt __far *pxOldSwitchISRPlus1 )(); static void( __interrupt __far * pxOldSwitchISRPlus1 )();
/* Used to restore the original DOS context when the scheduler is ended. */ /* Used to restore the original DOS context when the scheduler is ended. */
static jmp_buf xJumpBuf; static jmp_buf xJumpBuf;
@ -105,12 +107,12 @@ static jmp_buf xJumpBuf;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
pxISR pxOriginalTickISR; pxISR pxOriginalTickISR;
/* This is called with interrupts already disabled. */ /* This is called with interrupts already disabled. */
/* Remember what was on the interrupts we are going to use /* Remember what was on the interrupts we are going to use
so we can put them back later if required. */ * so we can put them back later if required. */
pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER ); pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER );
pxOriginalTickISR = _dos_getvect( portTIMER_INT_NUMBER ); pxOriginalTickISR = _dos_getvect( portTIMER_INT_NUMBER );
pxOldSwitchISRPlus1 = _dos_getvect( portSWITCH_INT_NUMBER + 1 ); pxOldSwitchISRPlus1 = _dos_getvect( portSWITCH_INT_NUMBER + 1 );
@ -118,16 +120,16 @@ pxISR pxOriginalTickISR;
prvSetTickFrequency( configTICK_RATE_HZ ); prvSetTickFrequency( configTICK_RATE_HZ );
/* Put our manual switch (yield) function on a known /* Put our manual switch (yield) function on a known
vector. */ * vector. */
_dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor ); _dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
/* Put the old tick on a different interrupt number so we can /* Put the old tick on a different interrupt number so we can
call it when we want. */ * call it when we want. */
_dos_setvect( portSWITCH_INT_NUMBER + 1, pxOriginalTickISR ); _dos_setvect( portSWITCH_INT_NUMBER + 1, pxOriginalTickISR );
/* The ISR used depends on whether the preemptive or cooperative /* The ISR used depends on whether the preemptive or cooperative
scheduler is being used. */ * scheduler is being used. */
#if( configUSE_PREEMPTION == 1 ) #if ( configUSE_PREEMPTION == 1 )
{ {
/* Put our tick switch function on the timer interrupt. */ /* Put our tick switch function on the timer interrupt. */
_dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick ); _dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick );
@ -140,8 +142,8 @@ pxISR pxOriginalTickISR;
#endif #endif
/* Setup a counter that is used to call the DOS interrupt as close /* Setup a counter that is used to call the DOS interrupt as close
to it's original frequency as can be achieved given our chosen tick * to it's original frequency as can be achieved given our chosen tick
frequency. */ * frequency. */
sDOSTickCounter = portTICKS_PER_DOS_TICK; sDOSTickCounter = portTICKS_PER_DOS_TICK;
/* Clean up function if we want to return to DOS. */ /* Clean up function if we want to return to DOS. */
@ -163,8 +165,8 @@ pxISR pxOriginalTickISR;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* The ISR used depends on whether the preemptive or cooperative /* The ISR used depends on whether the preemptive or cooperative
scheduler is being used. */ * scheduler is being used. */
#if( configUSE_PREEMPTION == 1 ) #if ( configUSE_PREEMPTION == 1 )
static void __interrupt __far prvPreemptiveTick( void ) static void __interrupt __far prvPreemptiveTick( void )
{ {
/* Get the scheduler to update the task states following the tick. */ /* Get the scheduler to update the task states following the tick. */
@ -177,15 +179,15 @@ scheduler is being used. */
/* Reset the PIC ready for the next time. */ /* Reset the PIC ready for the next time. */
prvPortResetPIC(); prvPortResetPIC();
} }
#else #else /* if ( configUSE_PREEMPTION == 1 ) */
static void __interrupt __far prvNonPreemptiveTick( void ) static void __interrupt __far prvNonPreemptiveTick( void )
{ {
/* Same as preemptive tick, but the cooperative scheduler is being used /* Same as preemptive tick, but the cooperative scheduler is being used
so we don't have to switch in the context of the next task. */ * so we don't have to switch in the context of the next task. */
xTaskIncrementTick(); xTaskIncrementTick();
prvPortResetPIC(); prvPortResetPIC();
} }
#endif #endif /* if ( configUSE_PREEMPTION == 1 ) */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void __interrupt __far prvYieldProcessor( void ) static void __interrupt __far prvYieldProcessor( void )
@ -198,19 +200,22 @@ static void __interrupt __far prvYieldProcessor( void )
static void prvPortResetPIC( void ) static void prvPortResetPIC( void )
{ {
/* We are going to call the DOS tick interrupt at as close a /* We are going to call the DOS tick interrupt at as close a
frequency to the normal DOS tick as possible. */ * frequency to the normal DOS tick as possible. */
/* WE SHOULD NOT DO THIS IF YIELD WAS CALLED. */ /* WE SHOULD NOT DO THIS IF YIELD WAS CALLED. */
--sDOSTickCounter; --sDOSTickCounter;
if( sDOSTickCounter <= 0 ) if( sDOSTickCounter <= 0 )
{ {
sDOSTickCounter = ( int16_t ) portTICKS_PER_DOS_TICK; sDOSTickCounter = ( int16_t ) portTICKS_PER_DOS_TICK;
__asm{ int portSWITCH_INT_NUMBER + 1 }; __asm {
int portSWITCH_INT_NUMBER + 1
};
} }
else else
{ {
/* Reset the PIC as the DOS tick is not being called to /* Reset the PIC as the DOS tick is not being called to
do it. */ * do it. */
__asm __asm
{ {
mov al, 20H mov al, 20H
@ -223,19 +228,20 @@ static void prvPortResetPIC( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Jump back to the processor state prior to starting the /* Jump back to the processor state prior to starting the
scheduler. This means we are not going to be using a * scheduler. This means we are not going to be using a
task stack frame so the task can be deleted. */ * task stack frame so the task can be deleted. */
longjmp( xJumpBuf, 1 ); longjmp( xJumpBuf, 1 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvExitFunction( void ) static void prvExitFunction( void )
{ {
void ( __interrupt __far *pxOriginalTickISR )(); void( __interrupt __far * pxOriginalTickISR )();
/* Interrupts should be disabled here anyway - but no /* Interrupts should be disabled here anyway - but no
harm in making sure. */ * harm in making sure. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
if( xSchedulerRunning == pdTRUE ) if( xSchedulerRunning == pdTRUE )
{ {
/* Set the DOS tick back onto the timer ticker. */ /* Set the DOS tick back onto the timer ticker. */
@ -244,28 +250,29 @@ void ( __interrupt __far *pxOriginalTickISR )();
prvSetTickFrequencyDefault(); prvSetTickFrequencyDefault();
/* Put back the switch interrupt routines that was in place /* Put back the switch interrupt routines that was in place
before the scheduler started. */ * before the scheduler started. */
_dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR ); _dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR );
_dos_setvect( portSWITCH_INT_NUMBER + 1, pxOldSwitchISRPlus1 ); _dos_setvect( portSWITCH_INT_NUMBER + 1, pxOldSwitchISRPlus1 );
} }
/* The tick timer is back how DOS wants it. We can re-enable /* The tick timer is back how DOS wants it. We can re-enable
interrupts without the scheduler being called. */ * interrupts without the scheduler being called. */
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSetTickFrequency( uint32_t ulTickRateHz ) static void prvSetTickFrequency( uint32_t ulTickRateHz )
{ {
const uint16_t usPIT_MODE = ( uint16_t ) 0x43; const uint16_t usPIT_MODE = ( uint16_t ) 0x43;
const uint16_t usPIT0 = ( uint16_t ) 0x40; const uint16_t usPIT0 = ( uint16_t ) 0x40;
const uint32_t ulPIT_CONST = ( uint32_t ) 1193180UL; const uint32_t ulPIT_CONST = ( uint32_t ) 1193180UL;
const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36; const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36;
uint32_t ulOutput; uint32_t ulOutput;
/* Setup the 8245 to tick at the wanted frequency. */ /* Setup the 8245 to tick at the wanted frequency. */
portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 ); portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 );
ulOutput = ulPIT_CONST / ulTickRateHz; ulOutput = ulPIT_CONST / ulTickRateHz;
portOUTPUT_BYTE( usPIT0, ( uint16_t )( ulOutput & ( uint32_t ) 0xff ) ); portOUTPUT_BYTE( usPIT0, ( uint16_t ) ( ulOutput & ( uint32_t ) 0xff ) );
ulOutput >>= 8; ulOutput >>= 8;
portOUTPUT_BYTE( usPIT0, ( uint16_t ) ( ulOutput & ( uint32_t ) 0xff ) ); portOUTPUT_BYTE( usPIT0, ( uint16_t ) ( ulOutput & ( uint32_t ) 0xff ) );
} }
@ -273,15 +280,14 @@ uint32_t ulOutput;
static void prvSetTickFrequencyDefault( void ) static void prvSetTickFrequencyDefault( void )
{ {
const uint16_t usPIT_MODE = ( uint16_t ) 0x43; const uint16_t usPIT_MODE = ( uint16_t ) 0x43;
const uint16_t usPIT0 = ( uint16_t ) 0x40; const uint16_t usPIT0 = ( uint16_t ) 0x40;
const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36; const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36;
portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 ); portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 );
portOUTPUT_BYTE( usPIT0,0 ); portOUTPUT_BYTE( usPIT0, 0 );
portOUTPUT_BYTE( usPIT0,0 ); portOUTPUT_BYTE( usPIT0, 0 );
} }
/*lint +e950 */ /*lint +e950 */

View file

@ -50,7 +50,7 @@ typedef portSTACK_TYPE StackType_t;
typedef short BaseType_t; typedef short BaseType_t;
typedef unsigned short UBaseType_t; typedef unsigned short UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
@ -60,7 +60,8 @@ typedef unsigned short UBaseType_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section management. */ /* Critical section management. */
#define portENTER_CRITICAL() __asm{ pushf } \ #define portENTER_CRITICAL() \
__asm{ pushf } \
__asm{ cli } \ __asm{ cli } \
#define portEXIT_CRITICAL() __asm{ popf } #define portEXIT_CRITICAL() __asm{ popf }
@ -89,8 +90,7 @@ typedef unsigned short UBaseType_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vTaskFunction, pvParameters ) void vTaskFunction( void * pvParameters )
#define portTASK_FUNCTION( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters ) #define portTASK_FUNCTION( vTaskFunction, pvParameters ) void vTaskFunction( void * pvParameters )
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -46,16 +46,16 @@ void portSWITCH_CONTEXT( void );
void portFIRST_CONTEXT( void ); void portFIRST_CONTEXT( void );
/* There are slightly different versions depending on whether you are building /* There are slightly different versions depending on whether you are building
to include debugger information. If debugger information is used then there * to include debugger information. If debugger information is used then there
are a couple of extra bytes left of the ISR stack (presumably for use by the * are a couple of extra bytes left of the ISR stack (presumably for use by the
debugger). The true stack pointer is then stored in the bp register. We add * debugger). The true stack pointer is then stored in the bp register. We add
2 to the stack pointer to remove the extra bytes before we restore our context. */ * 2 to the stack pointer to remove the extra bytes before we restore our context. */
#define portSWITCH_CONTEXT() \ #define portSWITCH_CONTEXT() \
asm { mov ax, seg pxCurrentTCB } \ asm { mov ax, seg pxCurrentTCB } \
asm { mov ds, ax } \ asm { mov ds, ax } \
asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */ \ asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */ \
asm { mov es:0x2[ bx ], ss } \ asm { mov es : 0x2[ bx ], ss } \
asm { mov es:[ bx ], sp } \ asm { mov es:[ bx ], sp } \
asm { call far ptr vTaskSwitchContext } /* Perform the switch. */ \ asm { call far ptr vTaskSwitchContext } /* Perform the switch. */ \
asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */ \ asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */ \
@ -82,5 +82,4 @@ debugger). The true stack pointer is then stored in the bp register. We add
__asm { iret } __asm { iret }
#endif #endif /* ifndef PORT_ASM_H */

View file

@ -25,16 +25,16 @@
*/ */
/* /*
Changes from V1.00: * Changes from V1.00:
*
+ pxPortInitialiseStack() now initialises the stack of new tasks to the + pxPortInitialiseStack() now initialises the stack of new tasks to the
same format used by the compiler. This allows the compiler generated + same format used by the compiler. This allows the compiler generated
interrupt mechanism to be used for context switches. + interrupt mechanism to be used for context switches.
+
Changes from V2.6.1 + Changes from V2.6.1
+
+ Move usPortCheckFreeStackSpace() to tasks.c. + Move usPortCheckFreeStackSpace() to tasks.c.
*/ */
#include <dos.h> #include <dos.h>
@ -44,12 +44,14 @@ Changes from V2.6.1
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* See header file for description. */ /* See header file for description. */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{ {
StackType_t DS_Reg = 0; StackType_t DS_Reg = 0;
/* Place a few bytes of known values on the bottom of the stack. /* Place a few bytes of known values on the bottom of the stack.
This is just useful for debugging. */ * This is just useful for debugging. */
*pxTopOfStack = 0x1111; *pxTopOfStack = 0x1111;
pxTopOfStack--; pxTopOfStack--;
@ -66,8 +68,8 @@ StackType_t DS_Reg = 0;
/*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */ /*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */
/* We are going to start the scheduler using a return from interrupt /* We are going to start the scheduler using a return from interrupt
instruction to load the program counter, so first there would be the * instruction to load the program counter, so first there would be the
function call with parameters preamble. */ * function call with parameters preamble. */
*pxTopOfStack = FP_SEG( pvParameters ); *pxTopOfStack = FP_SEG( pvParameters );
pxTopOfStack--; pxTopOfStack--;
@ -87,8 +89,8 @@ StackType_t DS_Reg = 0;
pxTopOfStack--; pxTopOfStack--;
/* The remaining registers would be pushed on the stack by our context /* The remaining registers would be pushed on the stack by our context
switch function. These are loaded with values simply to make debugging * switch function. These are loaded with values simply to make debugging
easier. */ * easier. */
*pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */ *pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */ *pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */
@ -101,7 +103,9 @@ StackType_t DS_Reg = 0;
pxTopOfStack--; pxTopOfStack--;
/* We need the true data segment. */ /* We need the true data segment. */
__asm{ MOV DS_Reg, DS }; __asm {
MOV DS_Reg, DS
};
*pxTopOfStack = DS_Reg; /* DS */ *pxTopOfStack = DS_Reg; /* DS */
pxTopOfStack--; pxTopOfStack--;
@ -116,4 +120,3 @@ StackType_t DS_Reg = 0;
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -25,15 +25,15 @@
*/ */
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM CM4F port. * Implementation of functions defined in portable.h for the ARM CM4F port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Scheduler includes. */ /* Scheduler includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#if( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 ) #if ( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 )
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http: /*www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
#endif #endif
#ifndef configSYSTICK_CLOCK_HZ #ifndef configSYSTICK_CLOCK_HZ
@ -41,16 +41,17 @@
/* Ensure the SysTick is clocked at the same frequency as the core. */ /* Ensure the SysTick is clocked at the same frequency as the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#else #else
/* The way the SysTick is clocked is not modified in case it is not the same
as the core. */ /* The way the SysTick is clocked is not modified in case it is not the same
* as the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 0 ) #define portNVIC_SYSTICK_CLK_BIT ( 0 )
#endif #endif
/* Constants required to manipulate the core. Registers first... */ /* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) #define portNVIC_SYSPRI2_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
/* ...then bits in the registers. */ /* ...then bits in the registers. */
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) #define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) #define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
@ -64,7 +65,7 @@
/* Constants required to check the validity of an interrupt priority. */ /* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) ) #define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) )
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) #define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) #define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) #define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
@ -81,12 +82,12 @@
#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) #define portMAX_24_BIT_NUMBER ( 0xffffffUL )
/* A fiddle factor to estimate the number of SysTick counts that would have /* A fiddle factor to estimate the number of SysTick counts that would have
occurred while the SysTick counter is stopped during tickless idle * occurred while the SysTick counter is stopped during tickless idle
calculations. */ * calculations. */
#define portMISSED_COUNTS_FACTOR ( 45UL ) #define portMISSED_COUNTS_FACTOR ( 45UL )
/* For strict compliance with the Cortex-M spec the task start address should /* 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. */ * have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL ) #define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
/* /*
@ -114,17 +115,17 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Required to allow portasm.asm access the configMAX_SYSCALL_INTERRUPT_PRIORITY /* Required to allow portasm.asm access the configMAX_SYSCALL_INTERRUPT_PRIORITY
setting. */ * setting. */
const uint32_t ulMaxSyscallInterruptPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY; const uint32_t ulMaxSyscallInterruptPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY;
/* Each task maintains its own interrupt status in the critical nesting /* Each task maintains its own interrupt status in the critical nesting
variable. */ * variable. */
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
/* /*
* The number of SysTick increments that make up one tick period. * The number of SysTick increments that make up one tick period.
*/ */
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulTimerCountsForOneTick = 0; static uint32_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
@ -132,7 +133,7 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
* The maximum number of tick periods that can be suppressed is limited by the * The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer. * 24 bit resolution of the SysTick timer.
*/ */
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
static uint32_t xMaximumPossibleSuppressedTicks = 0; static uint32_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
@ -140,7 +141,7 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
* Compensate for the CPU cycles that pass while the SysTick is stopped (low * Compensate for the CPU cycles that pass while the SysTick is stopped (low
* power functionality only. * power functionality only.
*/ */
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulStoppedTimerCompensation = 0; static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
@ -165,10 +166,10 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
void * pvParameters ) void * pvParameters )
{ {
/* Simulate the stack frame as it would be created by a context switch /* Simulate the stack frame as it would be created by a context switch
interrupt. */ * interrupt. */
/* Offset added to account for the way the MCU uses the stack on entry/exit /* Offset added to account for the way the MCU uses the stack on entry/exit
of interrupts, and to ensure alignment. */ * of interrupts, and to ensure alignment. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */ *pxTopOfStack = portINITIAL_XPSR; /* xPSR */
@ -190,14 +191,17 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
static void prvTaskExitError( void ) static void prvTaskExitError( void )
{ {
/* A function that implements a task must not exit or attempt to return to /* 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 * its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ). * should instead call vTaskDelete( NULL ).
*
Artificially force an assert() to be triggered if configASSERT() is * Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */ * defined, then stop here so application writers can catch the error. */
configASSERT( uxCriticalNesting == ~0UL ); configASSERT( uxCriticalNesting == ~0UL );
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
for( ;; );
for( ; ; )
{
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -206,22 +210,22 @@ static void prvTaskExitError( void )
*/ */
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
#if( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
volatile uint32_t ulOriginalPriority; volatile uint32_t ulOriginalPriority;
volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
/* Determine the maximum priority from which ISR safe FreeRTOS API /* Determine the maximum priority from which ISR safe FreeRTOS API
functions can be called. ISR safe functions are those that end in * functions can be called. ISR safe functions are those that end in
"FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
*
Save the interrupt priority value that is about to be clobbered. */ * Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pucFirstUserPriorityRegister; ulOriginalPriority = *pucFirstUserPriorityRegister;
/* Determine the number of priority bits available. First write to all /* Determine the number of priority bits available. First write to all
possible bits. */ * possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -231,8 +235,9 @@ BaseType_t xPortStartScheduler( void )
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
of bits read back. */ * of bits read back. */
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulMaxPRIGROUPValue--; ulMaxPRIGROUPValue--;
@ -242,8 +247,8 @@ BaseType_t xPortStartScheduler( void )
#ifdef __NVIC_PRIO_BITS #ifdef __NVIC_PRIO_BITS
{ {
/* Check the CMSIS configuration that defines the number of /* Check the CMSIS configuration that defines the number of
priority bits matches the number of priority bits actually queried * priority bits matches the number of priority bits actually queried
from the hardware. */ * from the hardware. */
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
} }
#endif #endif
@ -251,19 +256,19 @@ BaseType_t xPortStartScheduler( void )
#ifdef configPRIO_BITS #ifdef configPRIO_BITS
{ {
/* Check the FreeRTOS configuration that defines the number of /* Check the FreeRTOS configuration that defines the number of
priority bits matches the number of priority bits actually queried * priority bits matches the number of priority bits actually queried
from the hardware. */ * from the hardware. */
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
} }
#endif #endif
/* Shift the priority group value back to its position within the AIRCR /* Shift the priority group value back to its position within the AIRCR
register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original /* Restore the clobbered interrupt priority register to its original
value. */ * value. */
*pucFirstUserPriorityRegister = ulOriginalPriority; *pucFirstUserPriorityRegister = ulOriginalPriority;
} }
#endif /* conifgASSERT_DEFINED */ #endif /* conifgASSERT_DEFINED */
@ -273,7 +278,7 @@ BaseType_t xPortStartScheduler( void )
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ * here already. */
vPortSetupTimerInterrupt(); vPortSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */ /* Initialise the critical nesting count ready for the first task. */
@ -290,7 +295,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented in ports where there is nothing to return to. /* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */ * Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL ); configASSERT( uxCriticalNesting == 1000UL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -301,10 +306,10 @@ void vPortEnterCritical( void )
uxCriticalNesting++; uxCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so /* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API * assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if * functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the * the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */ * assert function also uses a critical section. */
if( uxCriticalNesting == 1 ) if( uxCriticalNesting == 1 )
{ {
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
@ -316,6 +321,7 @@ void vPortExitCritical( void )
{ {
configASSERT( uxCriticalNesting ); configASSERT( uxCriticalNesting );
uxCriticalNesting--; uxCriticalNesting--;
if( uxCriticalNesting == 0 ) if( uxCriticalNesting == 0 )
{ {
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
@ -326,16 +332,16 @@ void vPortExitCritical( void )
void xPortSysTickHandler( void ) void xPortSysTickHandler( void )
{ {
/* The SysTick runs at the lowest interrupt priority, so when this interrupt /* The SysTick runs at the lowest interrupt priority, so when this interrupt
executes all interrupts must be unmasked. There is therefore no need to * executes all interrupts must be unmasked. There is therefore no need to
save and then restore the interrupt mask value as its value is already * save and then restore the interrupt mask value as its value is already
known. */ * known. */
( void ) portSET_INTERRUPT_MASK_FROM_ISR(); ( void ) portSET_INTERRUPT_MASK_FROM_ISR();
{ {
/* Increment the RTOS tick. */ /* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
/* A context switch is required. Context switching is performed in /* A context switch is required. Context switching is performed in
the PendSV interrupt. Pend the PendSV interrupt. */ * the PendSV interrupt. Pend the PendSV interrupt. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
} }
} }
@ -343,7 +349,7 @@ void xPortSysTickHandler( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
#pragma WEAK( vPortSuppressTicksAndSleep ) #pragma WEAK( vPortSuppressTicksAndSleep )
void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
@ -358,45 +364,45 @@ void xPortSysTickHandler( void )
} }
/* Stop the SysTick momentarily. The time the SysTick is stopped for /* Stop the SysTick momentarily. The time the SysTick is stopped for
is accounted for as best it can be, but using the tickless mode will * is accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the * inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */ * kernel with respect to calendar time. */
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
/* Calculate the reload value required to wait xExpectedIdleTime /* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way * tick periods. -1 is used because this code will execute part way
through one of the tick periods. */ * through one of the tick periods. */
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
if( ulReloadValue > ulStoppedTimerCompensation ) if( ulReloadValue > ulStoppedTimerCompensation )
{ {
ulReloadValue -= ulStoppedTimerCompensation; ulReloadValue -= ulStoppedTimerCompensation;
} }
/* Enter a critical section but don't use the taskENTER_CRITICAL() /* Enter a critical section but don't use the taskENTER_CRITICAL()
method as that will mask interrupts that should exit sleep mode. */ * method as that will mask interrupts that should exit sleep mode. */
__asm( " cpsid i" ); __asm( " cpsid i");
__asm( " dsb" ); __asm( " dsb");
__asm( " isb" ); __asm( " isb");
/* If a context switch is pending or a task is waiting for the scheduler /* If a context switch is pending or a task is waiting for the scheduler
to be unsuspended then abandon the low power entry. */ * to be unsuspended then abandon the low power entry. */
if( eTaskConfirmSleepModeStatus() == eAbortSleep ) if( eTaskConfirmSleepModeStatus() == eAbortSleep )
{ {
/* Restart from whatever is left in the count register to complete /* Restart from whatever is left in the count register to complete
this tick period. */ * this tick period. */
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* Restart SysTick. */ /* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Reset the reload register to the value required for normal tick /* Reset the reload register to the value required for normal tick
periods. */ * periods. */
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Re-enable interrupts - see comments above __disable_interrupt() /* Re-enable interrupts - see comments above __disable_interrupt()
call above. */ * call above. */
__asm( " cpsie i" ); __asm( " cpsie i");
} }
else else
{ {
@ -404,69 +410,71 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulReloadValue; portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
/* Clear the SysTick count flag and set the count value back to /* Clear the SysTick count flag and set the count value back to
zero. */ * zero. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */ /* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
set its parameter to 0 to indicate that its implementation contains * set its parameter to 0 to indicate that its implementation contains
its own wait for interrupt or wait for event instruction, and so wfi * its own wait for interrupt or wait for event instruction, and so wfi
should not be executed again. However, the original expected idle * should not be executed again. However, the original expected idle
time variable must remain unmodified, so a copy is taken. */ * time variable must remain unmodified, so a copy is taken. */
xModifiableIdleTime = xExpectedIdleTime; xModifiableIdleTime = xExpectedIdleTime;
configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
if( xModifiableIdleTime > 0 ) if( xModifiableIdleTime > 0 )
{ {
__asm( " dsb" ); __asm( " dsb");
__asm( " wfi" ); __asm( " wfi");
__asm( " isb" ); __asm( " isb");
} }
configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
/* Re-enable interrupts to allow the interrupt that brought the MCU /* Re-enable interrupts to allow the interrupt that brought the MCU
out of sleep mode to execute immediately. see comments above * out of sleep mode to execute immediately. see comments above
__disable_interrupt() call above. */ * __disable_interrupt() call above. */
__asm( " cpsie i" ); __asm( " cpsie i");
__asm( " dsb" ); __asm( " dsb");
__asm( " isb" ); __asm( " isb");
/* Disable interrupts again because the clock is about to be stopped /* Disable interrupts again because the clock is about to be stopped
and interrupts that execute while the clock is stopped will increase * and interrupts that execute while the clock is stopped will increase
any slippage between the time maintained by the RTOS and calendar * any slippage between the time maintained by the RTOS and calendar
time. */ * time. */
__asm( " cpsid i" ); __asm( " cpsid i");
__asm( " dsb" ); __asm( " dsb");
__asm( " isb" ); __asm( " isb");
/* Disable the SysTick clock without reading the /* Disable the SysTick clock without reading the
portNVIC_SYSTICK_CTRL_REG register to ensure the * portNVIC_SYSTICK_CTRL_REG register to ensure the
portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
the time the SysTick is stopped for is accounted for as best it can * the time the SysTick is stopped for is accounted for as best it can
be, but using the tickless mode will inevitably result in some tiny * be, but using the tickless mode will inevitably result in some tiny
drift of the time maintained by the kernel with respect to calendar * drift of the time maintained by the kernel with respect to calendar
time*/ * time*/
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT ); portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
/* Determine if the SysTick clock has already counted to zero and /* Determine if the SysTick clock has already counted to zero and
been set back to the current reload value (the reload back being * been set back to the current reload value (the reload back being
correct for the entire expected idle time) or if the SysTick is yet * correct for the entire expected idle time) or if the SysTick is yet
to count to zero (in which case an interrupt other than the SysTick * to count to zero (in which case an interrupt other than the SysTick
must have brought the system out of sleep mode). */ * must have brought the system out of sleep mode). */
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{ {
uint32_t ulCalculatedLoadValue; uint32_t ulCalculatedLoadValue;
/* The tick interrupt is already pending, and the SysTick count /* The tick interrupt is already pending, and the SysTick count
reloaded with ulReloadValue. Reset the * reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick * portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */ * period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
/* Don't allow a tiny value, or values that have somehow /* Don't allow a tiny value, or values that have somehow
underflowed because the post sleep hook did something * underflowed because the post sleep hook did something
that took too long. */ * that took too long. */
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
{ {
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
@ -475,37 +483,37 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
/* As the pending tick will be processed as soon as this /* As the pending tick will be processed as soon as this
function exits, the tick value maintained by the tick is stepped * function exits, the tick value maintained by the tick is stepped
forward by one less than the time spent waiting. */ * forward by one less than the time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL; ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
} }
else else
{ {
/* Something other than the tick interrupt ended the sleep. /* Something other than the tick interrupt ended the sleep.
Work out how long the sleep lasted rounded to complete tick * Work out how long the sleep lasted rounded to complete tick
periods (not the ulReload value which accounted for part * periods (not the ulReload value which accounted for part
ticks). */ * ticks). */
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* How many complete tick periods passed while the processor /* How many complete tick periods passed while the processor
was waiting? */ * was waiting? */
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
/* The reload value is set to whatever fraction of a single tick /* The reload value is set to whatever fraction of a single tick
period remains. */ * period remains. */
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
} }
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard * again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
value. */ * value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
vTaskStepTick( ulCompleteTickPeriods ); vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrupts enabled. */ /* Exit with interrupts enabled. */
__asm( " cpsie i" ); __asm( " cpsie i");
} }
} }
@ -520,7 +528,7 @@ void xPortSysTickHandler( void )
void vPortSetupTimerInterrupt( void ) void vPortSetupTimerInterrupt( void )
{ {
/* Calculate the constants required to configure the tick interrupt. */ /* Calculate the constants required to configure the tick interrupt. */
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
{ {
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
@ -538,7 +546,7 @@ void vPortSetupTimerInterrupt( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
void vPortValidateInterruptPriority( void ) void vPortValidateInterruptPriority( void )
{ {
@ -555,66 +563,45 @@ void vPortSetupTimerInterrupt( void )
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
/* The following assertion will fail if a service routine (ISR) for /* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above * an interrupt that has been assigned a priority above
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called * function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below * from interrupts that have been assigned a priority at or below
configMAX_SYSCALL_INTERRUPT_PRIORITY. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
Numerically low interrupt priority numbers represent logically high * Numerically low interrupt priority numbers represent logically high
interrupt priorities, therefore the priority of the interrupt must * interrupt priorities, therefore the priority of the interrupt must
be set to a value equal to or numerically *higher* than * be set to a value equal to or numerically *higher* than
configMAX_SYSCALL_INTERRUPT_PRIORITY. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
Interrupts that use the FreeRTOS API must not be left at their * Interrupts that use the FreeRTOS API must not be left at their
default priority of zero as that is the highest possible priority, * default priority of zero as that is the highest possible priority,
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
and therefore also guaranteed to be invalid. * and therefore also guaranteed to be invalid.
*
FreeRTOS maintains separate thread and ISR API functions to ensure * FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible. * interrupt entry is as fast and simple as possible.
*
The following links provide detailed information: * The following links provide detailed information:
http://www.freertos.org/RTOS-Cortex-M3-M4.html * http://www.freertos.org/RTOS-Cortex-M3-M4.html
http://www.freertos.org/FAQHelp.html */ * http://www.freertos.org/FAQHelp.html */
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
} }
/* Priority grouping: The interrupt controller (NVIC) allows the bits /* Priority grouping: The interrupt controller (NVIC) allows the bits
that define each interrupt's priority to be split between bits that * that define each interrupt's priority to be split between bits that
define the interrupt's pre-emption priority bits and bits that define * define the interrupt's pre-emption priority bits and bits that define
the interrupt's sub-priority. For simplicity all bits must be defined * the interrupt's sub-priority. For simplicity all bits must be defined
to be pre-emption priority bits. The following assertion will fail if * to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority). * this is not the case (if some bits represent a sub-priority).
*
If the application only uses CMSIS libraries for interrupt * If the application only uses CMSIS libraries for interrupt
configuration then the correct setting can be achieved on all Cortex-M * configuration then the correct setting can be achieved on all Cortex-M
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries * scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value * assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredictable behaviour. */ * of zero will result in unpredictable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */

View file

@ -26,11 +26,11 @@
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -43,128 +43,127 @@ extern "C" {
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 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. */ * not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specifics. */ /* Architecture specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Compiler directives. */ /* Compiler directives. */
#define portWEAK_SYMBOL __attribute__((weak)) #define portWEAK_SYMBOL __attribute__( ( weak ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Scheduler utilities. */ /* Scheduler utilities. */
#define portYIELD() \ #define portYIELD() \
{ \ { \
/* Set a PendSV to request a context switch. */ \ /* Set a PendSV to request a context switch. */ \
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
__asm( " dsb" ); \ __asm( " dsb"); \
__asm( " isb" ); \ __asm( " isb"); \
} }
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD() #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specific optimisations. */ /* Architecture specific optimisations. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif #endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */ /* Check the configuration. */
#if( configMAX_PRIORITIES > 32 ) #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. #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 #endif
/* Store/clear the ready priorities in a bit map. */ /* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section management. */ /* Critical section management. */
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portDISABLE_INTERRUPTS() \ #define portDISABLE_INTERRUPTS() \
{ \ { \
_set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \ _set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \
__asm( " dsb" ); \ __asm( " dsb"); \
__asm( " isb" ); \ __asm( " isb"); \
} }
#define portENABLE_INTERRUPTS() _set_interrupt_priority( 0 ) #define portENABLE_INTERRUPTS() _set_interrupt_priority( 0 )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
#define portSET_INTERRUPT_MASK_FROM_ISR() _set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); __asm( " dsb" ); __asm( " isb" ) #define portSET_INTERRUPT_MASK_FROM_ISR() _set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); __asm( " dsb" ); __asm( " isb")
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) _set_interrupt_priority( x ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) _set_interrupt_priority( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Tickless idle/low power functionality. */ /* Tickless idle/low power functionality. */
#ifndef portSUPPRESS_TICKS_AND_SLEEP #ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are /* 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 * not necessary for to use this port. They are defined so the common demo files
(which build with all the ports) will build. */ * (which build with all the ports) will build. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#ifdef configASSERT #ifdef configASSERT
void vPortValidateInterruptPriority( void ); void vPortValidateInterruptPriority( void );
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
#endif #endif
/* portNOP() is not required by this port. */ /* portNOP() is not required by this port. */
#define portNOP() #define portNOP()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -25,8 +25,8 @@
*/ */
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM CM4F port. * Implementation of functions defined in portable.h for the ARM CM4F port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Scheduler includes. */ /* Scheduler includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
@ -36,8 +36,8 @@
#error This port can only be used when the project options are configured to enable hardware floating point support. #error This port can only be used when the project options are configured to enable hardware floating point support.
#endif #endif
#if( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 ) #if ( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 )
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http: /*www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
#endif #endif
#ifndef configSYSTICK_CLOCK_HZ #ifndef configSYSTICK_CLOCK_HZ
@ -45,16 +45,17 @@
/* Ensure the SysTick is clocked at the same frequency as the core. */ /* Ensure the SysTick is clocked at the same frequency as the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#else #else
/* The way the SysTick is clocked is not modified in case it is not the same
as the core. */ /* The way the SysTick is clocked is not modified in case it is not the same
* as the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 0 ) #define portNVIC_SYSTICK_CLK_BIT ( 0 )
#endif #endif
/* Constants required to manipulate the core. Registers first... */ /* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) #define portNVIC_SYSPRI2_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
/* ...then bits in the registers. */ /* ...then bits in the registers. */
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) #define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) #define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
@ -68,7 +69,7 @@
/* Constants required to check the validity of an interrupt priority. */ /* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) ) #define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) )
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) #define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) #define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) #define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
@ -90,12 +91,12 @@
#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) #define portMAX_24_BIT_NUMBER ( 0xffffffUL )
/* A fiddle factor to estimate the number of SysTick counts that would have /* A fiddle factor to estimate the number of SysTick counts that would have
occurred while the SysTick counter is stopped during tickless idle * occurred while the SysTick counter is stopped during tickless idle
calculations. */ * calculations. */
#define portMISSED_COUNTS_FACTOR ( 45UL ) #define portMISSED_COUNTS_FACTOR ( 45UL )
/* For strict compliance with the Cortex-M spec the task start address should /* 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. */ * have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL ) #define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
/* /*
@ -128,17 +129,17 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Required to allow portasm.asm access the configMAX_SYSCALL_INTERRUPT_PRIORITY /* Required to allow portasm.asm access the configMAX_SYSCALL_INTERRUPT_PRIORITY
setting. */ * setting. */
const uint32_t ulMaxSyscallInterruptPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY; const uint32_t ulMaxSyscallInterruptPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY;
/* Each task maintains its own interrupt status in the critical nesting /* Each task maintains its own interrupt status in the critical nesting
variable. */ * variable. */
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
/* /*
* The number of SysTick increments that make up one tick period. * The number of SysTick increments that make up one tick period.
*/ */
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulTimerCountsForOneTick = 0; static uint32_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
@ -146,7 +147,7 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
* The maximum number of tick periods that can be suppressed is limited by the * The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer. * 24 bit resolution of the SysTick timer.
*/ */
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
static uint32_t xMaximumPossibleSuppressedTicks = 0; static uint32_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
@ -154,7 +155,7 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
* Compensate for the CPU cycles that pass while the SysTick is stopped (low * Compensate for the CPU cycles that pass while the SysTick is stopped (low
* power functionality only. * power functionality only.
*/ */
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulStoppedTimerCompensation = 0; static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
@ -174,13 +175,15 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
/* /*
* See header file for description. * See header file for description.
*/ */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{ {
/* Simulate the stack frame as it would be created by a context switch /* Simulate the stack frame as it would be created by a context switch
interrupt. */ * interrupt. */
/* Offset added to account for the way the MCU uses the stack on entry/exit /* Offset added to account for the way the MCU uses the stack on entry/exit
of interrupts, and to ensure alignment. */ * of interrupts, and to ensure alignment. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */ *pxTopOfStack = portINITIAL_XPSR; /* xPSR */
@ -194,7 +197,7 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
/* A save method is being used that requires each task to maintain its /* A save method is being used that requires each task to maintain its
own exec return value. */ * own exec return value. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portINITIAL_EXC_RETURN; *pxTopOfStack = portINITIAL_EXC_RETURN;
@ -207,14 +210,17 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
static void prvTaskExitError( void ) static void prvTaskExitError( void )
{ {
/* A function that implements a task must not exit or attempt to return to /* 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 * its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ). * should instead call vTaskDelete( NULL ).
*
Artificially force an assert() to be triggered if configASSERT() is * Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */ * defined, then stop here so application writers can catch the error. */
configASSERT( uxCriticalNesting == ~0UL ); configASSERT( uxCriticalNesting == ~0UL );
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
for( ;; );
for( ; ; )
{
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -223,22 +229,22 @@ static void prvTaskExitError( void )
*/ */
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
#if( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
volatile uint32_t ulOriginalPriority; volatile uint32_t ulOriginalPriority;
volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
/* Determine the maximum priority from which ISR safe FreeRTOS API /* Determine the maximum priority from which ISR safe FreeRTOS API
functions can be called. ISR safe functions are those that end in * functions can be called. ISR safe functions are those that end in
"FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
*
Save the interrupt priority value that is about to be clobbered. */ * Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pucFirstUserPriorityRegister; ulOriginalPriority = *pucFirstUserPriorityRegister;
/* Determine the number of priority bits available. First write to all /* Determine the number of priority bits available. First write to all
possible bits. */ * possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -248,8 +254,9 @@ BaseType_t xPortStartScheduler( void )
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
of bits read back. */ * of bits read back. */
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulMaxPRIGROUPValue--; ulMaxPRIGROUPValue--;
@ -259,8 +266,8 @@ BaseType_t xPortStartScheduler( void )
#ifdef __NVIC_PRIO_BITS #ifdef __NVIC_PRIO_BITS
{ {
/* Check the CMSIS configuration that defines the number of /* Check the CMSIS configuration that defines the number of
priority bits matches the number of priority bits actually queried * priority bits matches the number of priority bits actually queried
from the hardware. */ * from the hardware. */
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
} }
#endif #endif
@ -268,19 +275,19 @@ BaseType_t xPortStartScheduler( void )
#ifdef configPRIO_BITS #ifdef configPRIO_BITS
{ {
/* Check the FreeRTOS configuration that defines the number of /* Check the FreeRTOS configuration that defines the number of
priority bits matches the number of priority bits actually queried * priority bits matches the number of priority bits actually queried
from the hardware. */ * from the hardware. */
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
} }
#endif #endif
/* Shift the priority group value back to its position within the AIRCR /* Shift the priority group value back to its position within the AIRCR
register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original /* Restore the clobbered interrupt priority register to its original
value. */ * value. */
*pucFirstUserPriorityRegister = ulOriginalPriority; *pucFirstUserPriorityRegister = ulOriginalPriority;
} }
#endif /* conifgASSERT_DEFINED */ #endif /* conifgASSERT_DEFINED */
@ -290,7 +297,7 @@ BaseType_t xPortStartScheduler( void )
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ * here already. */
vPortSetupTimerInterrupt(); vPortSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */ /* Initialise the critical nesting count ready for the first task. */
@ -313,7 +320,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented in ports where there is nothing to return to. /* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */ * Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL ); configASSERT( uxCriticalNesting == 1000UL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -324,10 +331,10 @@ void vPortEnterCritical( void )
uxCriticalNesting++; uxCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so /* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API * assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if * functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the * the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */ * assert function also uses a critical section. */
if( uxCriticalNesting == 1 ) if( uxCriticalNesting == 1 )
{ {
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
@ -339,6 +346,7 @@ void vPortExitCritical( void )
{ {
configASSERT( uxCriticalNesting ); configASSERT( uxCriticalNesting );
uxCriticalNesting--; uxCriticalNesting--;
if( uxCriticalNesting == 0 ) if( uxCriticalNesting == 0 )
{ {
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
@ -349,16 +357,16 @@ void vPortExitCritical( void )
void xPortSysTickHandler( void ) void xPortSysTickHandler( void )
{ {
/* The SysTick runs at the lowest interrupt priority, so when this interrupt /* The SysTick runs at the lowest interrupt priority, so when this interrupt
executes all interrupts must be unmasked. There is therefore no need to * executes all interrupts must be unmasked. There is therefore no need to
save and then restore the interrupt mask value as its value is already * save and then restore the interrupt mask value as its value is already
known. */ * known. */
( void ) portSET_INTERRUPT_MASK_FROM_ISR(); ( void ) portSET_INTERRUPT_MASK_FROM_ISR();
{ {
/* Increment the RTOS tick. */ /* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
/* A context switch is required. Context switching is performed in /* A context switch is required. Context switching is performed in
the PendSV interrupt. Pend the PendSV interrupt. */ * the PendSV interrupt. Pend the PendSV interrupt. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
} }
} }
@ -366,7 +374,7 @@ void xPortSysTickHandler( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
#pragma WEAK( vPortSuppressTicksAndSleep ) #pragma WEAK( vPortSuppressTicksAndSleep )
void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
@ -381,45 +389,45 @@ void xPortSysTickHandler( void )
} }
/* Stop the SysTick momentarily. The time the SysTick is stopped for /* Stop the SysTick momentarily. The time the SysTick is stopped for
is accounted for as best it can be, but using the tickless mode will * is accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the * inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */ * kernel with respect to calendar time. */
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
/* Calculate the reload value required to wait xExpectedIdleTime /* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way * tick periods. -1 is used because this code will execute part way
through one of the tick periods. */ * through one of the tick periods. */
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
if( ulReloadValue > ulStoppedTimerCompensation ) if( ulReloadValue > ulStoppedTimerCompensation )
{ {
ulReloadValue -= ulStoppedTimerCompensation; ulReloadValue -= ulStoppedTimerCompensation;
} }
/* Enter a critical section but don't use the taskENTER_CRITICAL() /* Enter a critical section but don't use the taskENTER_CRITICAL()
method as that will mask interrupts that should exit sleep mode. */ * method as that will mask interrupts that should exit sleep mode. */
__asm( " cpsid i" ); __asm( " cpsid i");
__asm( " dsb" ); __asm( " dsb");
__asm( " isb" ); __asm( " isb");
/* If a context switch is pending or a task is waiting for the scheduler /* If a context switch is pending or a task is waiting for the scheduler
to be unsuspended then abandon the low power entry. */ * to be unsuspended then abandon the low power entry. */
if( eTaskConfirmSleepModeStatus() == eAbortSleep ) if( eTaskConfirmSleepModeStatus() == eAbortSleep )
{ {
/* Restart from whatever is left in the count register to complete /* Restart from whatever is left in the count register to complete
this tick period. */ * this tick period. */
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* Restart SysTick. */ /* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Reset the reload register to the value required for normal tick /* Reset the reload register to the value required for normal tick
periods. */ * periods. */
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Re-enable interrupts - see comments above __disable_interrupt() /* Re-enable interrupts - see comments above __disable_interrupt()
call above. */ * call above. */
__asm( " cpsie i" ); __asm( " cpsie i");
} }
else else
{ {
@ -427,69 +435,71 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulReloadValue; portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
/* Clear the SysTick count flag and set the count value back to /* Clear the SysTick count flag and set the count value back to
zero. */ * zero. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */ /* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
set its parameter to 0 to indicate that its implementation contains * set its parameter to 0 to indicate that its implementation contains
its own wait for interrupt or wait for event instruction, and so wfi * its own wait for interrupt or wait for event instruction, and so wfi
should not be executed again. However, the original expected idle * should not be executed again. However, the original expected idle
time variable must remain unmodified, so a copy is taken. */ * time variable must remain unmodified, so a copy is taken. */
xModifiableIdleTime = xExpectedIdleTime; xModifiableIdleTime = xExpectedIdleTime;
configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
if( xModifiableIdleTime > 0 ) if( xModifiableIdleTime > 0 )
{ {
__asm( " dsb" ); __asm( " dsb");
__asm( " wfi" ); __asm( " wfi");
__asm( " isb" ); __asm( " isb");
} }
configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
/* Re-enable interrupts to allow the interrupt that brought the MCU /* Re-enable interrupts to allow the interrupt that brought the MCU
out of sleep mode to execute immediately. see comments above * out of sleep mode to execute immediately. see comments above
__disable_interrupt() call above. */ * __disable_interrupt() call above. */
__asm( " cpsie i" ); __asm( " cpsie i");
__asm( " dsb" ); __asm( " dsb");
__asm( " isb" ); __asm( " isb");
/* Disable interrupts again because the clock is about to be stopped /* Disable interrupts again because the clock is about to be stopped
and interrupts that execute while the clock is stopped will increase * and interrupts that execute while the clock is stopped will increase
any slippage between the time maintained by the RTOS and calendar * any slippage between the time maintained by the RTOS and calendar
time. */ * time. */
__asm( " cpsid i" ); __asm( " cpsid i");
__asm( " dsb" ); __asm( " dsb");
__asm( " isb" ); __asm( " isb");
/* Disable the SysTick clock without reading the /* Disable the SysTick clock without reading the
portNVIC_SYSTICK_CTRL_REG register to ensure the * portNVIC_SYSTICK_CTRL_REG register to ensure the
portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
the time the SysTick is stopped for is accounted for as best it can * the time the SysTick is stopped for is accounted for as best it can
be, but using the tickless mode will inevitably result in some tiny * be, but using the tickless mode will inevitably result in some tiny
drift of the time maintained by the kernel with respect to calendar * drift of the time maintained by the kernel with respect to calendar
time*/ * time*/
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT ); portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
/* Determine if the SysTick clock has already counted to zero and /* Determine if the SysTick clock has already counted to zero and
been set back to the current reload value (the reload back being * been set back to the current reload value (the reload back being
correct for the entire expected idle time) or if the SysTick is yet * correct for the entire expected idle time) or if the SysTick is yet
to count to zero (in which case an interrupt other than the SysTick * to count to zero (in which case an interrupt other than the SysTick
must have brought the system out of sleep mode). */ * must have brought the system out of sleep mode). */
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{ {
uint32_t ulCalculatedLoadValue; uint32_t ulCalculatedLoadValue;
/* The tick interrupt is already pending, and the SysTick count /* The tick interrupt is already pending, and the SysTick count
reloaded with ulReloadValue. Reset the * reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick * portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */ * period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
/* Don't allow a tiny value, or values that have somehow /* Don't allow a tiny value, or values that have somehow
underflowed because the post sleep hook did something * underflowed because the post sleep hook did something
that took too long. */ * that took too long. */
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
{ {
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
@ -498,37 +508,37 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
/* As the pending tick will be processed as soon as this /* As the pending tick will be processed as soon as this
function exits, the tick value maintained by the tick is stepped * function exits, the tick value maintained by the tick is stepped
forward by one less than the time spent waiting. */ * forward by one less than the time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL; ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
} }
else else
{ {
/* Something other than the tick interrupt ended the sleep. /* Something other than the tick interrupt ended the sleep.
Work out how long the sleep lasted rounded to complete tick * Work out how long the sleep lasted rounded to complete tick
periods (not the ulReload value which accounted for part * periods (not the ulReload value which accounted for part
ticks). */ * ticks). */
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* How many complete tick periods passed while the processor /* How many complete tick periods passed while the processor
was waiting? */ * was waiting? */
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
/* The reload value is set to whatever fraction of a single tick /* The reload value is set to whatever fraction of a single tick
period remains. */ * period remains. */
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
} }
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard * again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
value. */ * value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
vTaskStepTick( ulCompleteTickPeriods ); vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrupts enabled. */ /* Exit with interrupts enabled. */
__asm( " cpsie i" ); __asm( " cpsie i");
} }
} }
@ -543,7 +553,7 @@ void xPortSysTickHandler( void )
void vPortSetupTimerInterrupt( void ) void vPortSetupTimerInterrupt( void )
{ {
/* Calculate the constants required to configure the tick interrupt. */ /* Calculate the constants required to configure the tick interrupt. */
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
{ {
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
@ -561,7 +571,7 @@ void vPortSetupTimerInterrupt( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
void vPortValidateInterruptPriority( void ) void vPortValidateInterruptPriority( void )
{ {
@ -578,66 +588,45 @@ void vPortSetupTimerInterrupt( void )
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
/* The following assertion will fail if a service routine (ISR) for /* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above * an interrupt that has been assigned a priority above
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called * function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below * from interrupts that have been assigned a priority at or below
configMAX_SYSCALL_INTERRUPT_PRIORITY. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
Numerically low interrupt priority numbers represent logically high * Numerically low interrupt priority numbers represent logically high
interrupt priorities, therefore the priority of the interrupt must * interrupt priorities, therefore the priority of the interrupt must
be set to a value equal to or numerically *higher* than * be set to a value equal to or numerically *higher* than
configMAX_SYSCALL_INTERRUPT_PRIORITY. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
Interrupts that use the FreeRTOS API must not be left at their * Interrupts that use the FreeRTOS API must not be left at their
default priority of zero as that is the highest possible priority, * default priority of zero as that is the highest possible priority,
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
and therefore also guaranteed to be invalid. * and therefore also guaranteed to be invalid.
*
FreeRTOS maintains separate thread and ISR API functions to ensure * FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible. * interrupt entry is as fast and simple as possible.
*
The following links provide detailed information: * The following links provide detailed information:
http://www.freertos.org/RTOS-Cortex-M3-M4.html * http://www.freertos.org/RTOS-Cortex-M3-M4.html
http://www.freertos.org/FAQHelp.html */ * http://www.freertos.org/FAQHelp.html */
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
} }
/* Priority grouping: The interrupt controller (NVIC) allows the bits /* Priority grouping: The interrupt controller (NVIC) allows the bits
that define each interrupt's priority to be split between bits that * that define each interrupt's priority to be split between bits that
define the interrupt's pre-emption priority bits and bits that define * define the interrupt's pre-emption priority bits and bits that define
the interrupt's sub-priority. For simplicity all bits must be defined * the interrupt's sub-priority. For simplicity all bits must be defined
to be pre-emption priority bits. The following assertion will fail if * to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority). * this is not the case (if some bits represent a sub-priority).
*
If the application only uses CMSIS libraries for interrupt * If the application only uses CMSIS libraries for interrupt
configuration then the correct setting can be achieved on all Cortex-M * configuration then the correct setting can be achieved on all Cortex-M
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries * scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value * assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredictable behaviour. */ * of zero will result in unpredictable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */

View file

@ -26,11 +26,11 @@
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -43,122 +43,121 @@ extern "C" {
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 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. */ * not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specifics. */ /* Architecture specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Scheduler utilities. */ /* Scheduler utilities. */
#define portYIELD() \ #define portYIELD() \
{ \ { \
/* Set a PendSV to request a context switch. */ \ /* Set a PendSV to request a context switch. */ \
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
__asm( " dsb" ); \ __asm( " dsb"); \
__asm( " isb" ); \ __asm( " isb"); \
} }
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD() #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specific optimisations. */ /* Architecture specific optimisations. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif #endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */ /* Check the configuration. */
#if( configMAX_PRIORITIES > 32 ) #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. #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 #endif
/* Store/clear the ready priorities in a bit map. */ /* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section management. */ /* Critical section management. */
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portDISABLE_INTERRUPTS() \ #define portDISABLE_INTERRUPTS() \
{ \ { \
_set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \ _set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \
__asm( " dsb" ); \ __asm( " dsb"); \
__asm( " isb" ); \ __asm( " isb"); \
} }
#define portENABLE_INTERRUPTS() _set_interrupt_priority( 0 ) #define portENABLE_INTERRUPTS() _set_interrupt_priority( 0 )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
#define portSET_INTERRUPT_MASK_FROM_ISR() _set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); __asm( " dsb" ); __asm( " isb" ) #define portSET_INTERRUPT_MASK_FROM_ISR() _set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); __asm( " dsb" ); __asm( " isb")
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) _set_interrupt_priority( x ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) _set_interrupt_priority( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Tickless idle/low power functionality. */ /* Tickless idle/low power functionality. */
#ifndef portSUPPRESS_TICKS_AND_SLEEP #ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are /* 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 * not necessary for to use this port. They are defined so the common demo files
(which build with all the ports) will build. */ * (which build with all the ports) will build. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#ifdef configASSERT #ifdef configASSERT
void vPortValidateInterruptPriority( void ); void vPortValidateInterruptPriority( void );
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
#endif #endif
/* portNOP() is not required by this port. */ /* portNOP() is not required by this port. */
#define portNOP() #define portNOP()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -36,17 +36,17 @@ uint32_t ulCriticalNesting = 9999;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Registers required to configure the RTI. */ /* Registers required to configure the RTI. */
#define portRTI_GCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC00 ) ) #define portRTI_GCTRL_REG ( *( ( volatile uint32_t * ) 0xFFFFFC00 ) )
#define portRTI_TBCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC04 ) ) #define portRTI_TBCTRL_REG ( *( ( volatile uint32_t * ) 0xFFFFFC04 ) )
#define portRTI_COMPCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC0C ) ) #define portRTI_COMPCTRL_REG ( *( ( volatile uint32_t * ) 0xFFFFFC0C ) )
#define portRTI_CNT0_FRC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC10 ) ) #define portRTI_CNT0_FRC0_REG ( *( ( volatile uint32_t * ) 0xFFFFFC10 ) )
#define portRTI_CNT0_UC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC14 ) ) #define portRTI_CNT0_UC0_REG ( *( ( volatile uint32_t * ) 0xFFFFFC14 ) )
#define portRTI_CNT0_CPUC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC18 ) ) #define portRTI_CNT0_CPUC0_REG ( *( ( volatile uint32_t * ) 0xFFFFFC18 ) )
#define portRTI_CNT0_COMP0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC50 ) ) #define portRTI_CNT0_COMP0_REG ( *( ( volatile uint32_t * ) 0xFFFFFC50 ) )
#define portRTI_CNT0_UDCP0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC54 ) ) #define portRTI_CNT0_UDCP0_REG ( *( ( volatile uint32_t * ) 0xFFFFFC54 ) )
#define portRTI_SETINTENA_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC80 ) ) #define portRTI_SETINTENA_REG ( *( ( volatile uint32_t * ) 0xFFFFFC80 ) )
#define portRTI_CLEARINTENA_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC84 ) ) #define portRTI_CLEARINTENA_REG ( *( ( volatile uint32_t * ) 0xFFFFFC84 ) )
#define portRTI_INTFLAG_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC88 ) ) #define portRTI_INTFLAG_REG ( *( ( volatile uint32_t * ) 0xFFFFFC88 ) )
/* Constants required to set up the initial stack of each task. */ /* Constants required to set up the initial stack of each task. */
@ -56,7 +56,7 @@ uint32_t ulCriticalNesting = 9999;
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 ) #define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
/* The number of words on the stack frame between the saved Top Of Stack and /* The number of words on the stack frame between the saved Top Of Stack and
R0 (in which the parameters are passed. */ * R0 (in which the parameters are passed. */
#define portSPACE_BETWEEN_TOS_AND_PARAMETERS ( 12 ) #define portSPACE_BETWEEN_TOS_AND_PARAMETERS ( 12 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -67,7 +67,7 @@ extern void vPortStartFirstTask( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Saved as part of the task context. Set to pdFALSE if the task does not /* Saved as part of the task context. Set to pdFALSE if the task does not
require an FPU context. */ * require an FPU context. */
uint32_t ulTaskHasFPUContext = 0; uint32_t ulTaskHasFPUContext = 0;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -76,9 +76,11 @@ uint32_t ulTaskHasFPUContext = 0;
/* /*
* See header file for description. * See header file for description.
*/ */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{ {
StackType_t *pxOriginalTOS; StackType_t * pxOriginalTOS;
pxOriginalTOS = pxTopOfStack; pxOriginalTOS = pxTopOfStack;
@ -90,11 +92,11 @@ StackType_t *pxOriginalTOS;
#endif #endif
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. */ * expected by the portRESTORE_CONTEXT() macro. */
/* First on the stack is the return address - which is the start of the as /* First on the stack is the return address - which is the start of the as
the task has not executed yet. The offset is added to make the return * the task has not executed yet. The offset is added to make the return
address appear as it would within an IRQ ISR. */ * address appear as it would within an IRQ ISR. */
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; *pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
pxTopOfStack--; pxTopOfStack--;
@ -130,11 +132,11 @@ StackType_t *pxOriginalTOS;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */ *pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
pxTopOfStack--; pxTopOfStack--;
} }
#else #else /* ifdef portPRELOAD_TASK_REGISTERS */
{ {
pxTopOfStack -= portSPACE_BETWEEN_TOS_AND_PARAMETERS; pxTopOfStack -= portSPACE_BETWEEN_TOS_AND_PARAMETERS;
} }
#endif #endif /* ifdef portPRELOAD_TASK_REGISTERS */
/* Function parameters are passed in R0. */ /* Function parameters are passed in R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
@ -154,8 +156,8 @@ StackType_t *pxOriginalTOS;
pxTopOfStack--; pxTopOfStack--;
/* The last thing on the stack is the tasks ulUsingFPU value, which by /* The last thing on the stack is the tasks ulUsingFPU value, which by
default is set to indicate that the stack frame does not include FPU * default is set to indicate that the stack frame does not include FPU
registers. */ * registers. */
*pxTopOfStack = pdFALSE; *pxTopOfStack = pdFALSE;
} }
#endif #endif
@ -164,7 +166,7 @@ StackType_t *pxOriginalTOS;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt(void) static void prvSetupTimerInterrupt( void )
{ {
/* Disable timer 0. */ /* Disable timer 0. */
portRTI_GCTRL_REG &= 0xFFFFFFFEUL; portRTI_GCTRL_REG &= 0xFFFFFFFEUL;
@ -197,7 +199,7 @@ static void prvSetupTimerInterrupt(void)
/* /*
* See header file for description. * See header file for description.
*/ */
BaseType_t xPortStartScheduler(void) BaseType_t xPortStartScheduler( void )
{ {
/* Start the timer that generates the tick ISR. */ /* Start the timer that generates the tick ISR. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
@ -206,7 +208,7 @@ BaseType_t xPortStartScheduler(void)
ulCriticalNesting = 0; ulCriticalNesting = 0;
/* Start the first task. This is done from portASM.asm as ARM mode must be /* Start the first task. This is done from portASM.asm as ARM mode must be
used. */ * used. */
vPortStartFirstTask(); vPortStartFirstTask();
/* Should not get here! */ /* Should not get here! */
@ -217,17 +219,17 @@ BaseType_t xPortStartScheduler(void)
/* /*
* See header file for description. * See header file for description.
*/ */
void vPortEndScheduler(void) void vPortEndScheduler( void )
{ {
/* Not implemented in ports where there is nothing to return to. /* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */ * Artificially force an assert. */
configASSERT( ulCriticalNesting == 1000UL ); configASSERT( ulCriticalNesting == 1000UL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if configUSE_PREEMPTION == 0 #if configUSE_PREEMPTION == 0
/* The cooperative scheduler requires a normal IRQ service routine to /* The cooperative scheduler requires a normal IRQ service routine to
* simply increment the system tick. */ * simply increment the system tick. */
__interrupt void vPortNonPreemptiveTick( void ) __interrupt void vPortNonPreemptiveTick( void )
{ {
@ -235,13 +237,13 @@ void vPortEndScheduler(void)
portRTI_INTFLAG_REG = 0x00000001; portRTI_INTFLAG_REG = 0x00000001;
/* Increment the tick count - this may make a delaying task ready /* Increment the tick count - this may make a delaying task ready
to run - but a context switch is not performed. */ * to run - but a context switch is not performed. */
xTaskIncrementTick(); xTaskIncrementTick();
} }
#else #else /* if configUSE_PREEMPTION == 0 */
/* /*
************************************************************************** **************************************************************************
* The preemptive scheduler ISR is written in assembler and can be found * The preemptive scheduler ISR is written in assembler and can be found
* in the portASM.asm file. This will only get used if portUSE_PREEMPTION * in the portASM.asm file. This will only get used if portUSE_PREEMPTION
@ -250,7 +252,7 @@ void vPortEndScheduler(void)
*/ */
void vPortPreemptiveTick( void ); void vPortPreemptiveTick( void );
#endif #endif /* if configUSE_PREEMPTION == 0 */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -263,8 +265,8 @@ void vPortEnterCritical( void )
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
directly. Increment ulCriticalNesting to keep a count of how many times * directly. Increment ulCriticalNesting to keep a count of how many times
portENTER_CRITICAL() has been called. */ * portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -281,7 +283,7 @@ void vPortExitCritical( void )
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be /* If the nesting level has reached zero then interrupts should be
re-enabled. */ * re-enabled. */
if( ulCriticalNesting == 0 ) if( ulCriticalNesting == 0 )
{ {
/* Enable interrupts as per portENABLE_INTERRUPTS(). */ /* Enable interrupts as per portENABLE_INTERRUPTS(). */
@ -298,7 +300,7 @@ void vPortExitCritical( void )
extern void vPortInitialiseFPSCR( void ); extern void vPortInitialiseFPSCR( void );
/* A task is registering the fact that it needs an FPU context. Set the /* A task is registering the fact that it needs an FPU context. Set the
FPU flag (saved as part of the task context. */ * FPU flag (saved as part of the task context. */
ulTaskHasFPUContext = pdTRUE; ulTaskHasFPUContext = pdTRUE;
/* Initialise the floating point status register. */ /* Initialise the floating point status register. */
@ -308,4 +310,3 @@ void vPortExitCritical( void )
#endif /* __TI_VFP_SUPPORT__ */ #endif /* __TI_VFP_SUPPORT__ */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -50,40 +50,40 @@ typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if (configUSE_16_BIT_TICKS == 1) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY (TickType_t) 0xFFFF #define portMAX_DELAY ( TickType_t ) 0xFFFF
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY (TickType_t) 0xFFFFFFFFF #define portMAX_DELAY ( TickType_t ) 0xFFFFFFFFF
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 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. */ * not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
#endif #endif
/* Architecture specifics. */ /* Architecture specifics. */
#define portSTACK_GROWTH (-1) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ((TickType_t) 1000 / configTICK_RATE_HZ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
/* Critical section handling. */ /* Critical section handling. */
extern void vPortEnterCritical(void); extern void vPortEnterCritical( void );
extern void vPortExitCritical(void); extern void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
#define portDISABLE_INTERRUPTS() asm( " CPSID I" ) #define portDISABLE_INTERRUPTS() asm ( " CPSID I" )
#define portENABLE_INTERRUPTS() asm( " CPSIE I" ) #define portENABLE_INTERRUPTS() asm ( " CPSIE I" )
/* Scheduler utilities. */ /* Scheduler utilities. */
#pragma SWI_ALIAS( vPortYield, 0 ) #pragma SWI_ALIAS( vPortYield, 0 )
extern void vPortYield( void ); extern void vPortYield( void );
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
#define portSYS_SSIR1_REG ( * ( ( volatile uint32_t * ) 0xFFFFFFB0 ) ) #define portSYS_SSIR1_REG ( *( ( volatile uint32_t * ) 0xFFFFFFB0 ) )
#define portSYS_SSIR1_SSKEY ( 0x7500UL ) #define portSYS_SSIR1_SSKEY ( 0x7500UL )
#define portYIELD_WITHIN_API() { portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; asm( " DSB " ); asm( " ISB " ); } #define portYIELD_WITHIN_API() { portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; asm ( " DSB " ); asm ( " ISB " ); }
#define portYIELD_FROM_ISR( x ) if( x != pdFALSE ){ portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; ( void ) portSYS_SSIR1_REG; } #define portYIELD_FROM_ISR( x ) if( x != pdFALSE ) { portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; ( void ) portSYS_SSIR1_REG; }
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
@ -92,16 +92,16 @@ extern void vPortYield( void );
/* Architecture specific optimisations. */ /* Architecture specific optimisations. */
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */ /* Check the configuration. */
#if( configMAX_PRIORITIES > 32 ) #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. #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 #endif
/* Store/clear the ready priorities in a bit map. */ /* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )
@ -109,8 +109,7 @@ extern void vPortYield( void );
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION(vFunction, pvParameters) void vFunction(void *pvParameters) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#endif /* __PORTMACRO_H__ */ #endif /* __PORTMACRO_H__ */

View file

@ -1,30 +1,30 @@
;/* ; /*
; * FreeRTOS Kernel V10.3.1 * ; * FreeRTOS Kernel V10.3.1
; * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * ; * 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 * ; * 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 * ; * this software and associated documentation files (the "Software"), to deal in
; * the Software without restriction, including without limitation the rights to * ; * the Software without restriction, including without limitation the rights to
; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * ; * 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, * ; * the Software, and to permit persons to whom the Software is furnished to do so,
; * subject to the following conditions: * ; * subject to the following conditions:
; * * ; *
; * The above copyright notice and this permission notice shall be included in all * ; * The above copyright notice and this permission notice shall be included in all
; * copies or substantial portions of the Software. * ; * copies or substantial portions of the Software.
; * * ; *
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * ; * 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 * ; * 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 * ; * 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. * ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
; * * ; *
; * http://www.FreeRTOS.org * ; * http://www.FreeRTOS.org
; * http://aws.amazon.com/freertos * ; * http://aws.amazon.com/freertos
; * * ; *
; */ * ; */
.if $DEFINED( __LARGE_DATA_MODEL__ ) .if $DEFINED( __LARGE_DATA_MODEL__ )
.define "pushm.a", pushm_x .define "pushm.a", pushm_x
.define "popm.a", popm_x .define "popm.a", popm_x
.define "push.a", push_x .define "push.a", push_x
@ -45,8 +45,3 @@
.define "call", call_x .define "call", call_x
.define "ret", ret_x .define "ret", ret_x
.endif .endif

View file

@ -29,28 +29,28 @@
#include "task.h" #include "task.h"
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the MSP430X port. * Implementation of functions defined in portable.h for the MSP430X port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Constants required for hardware setup. The tick ISR runs off the ACLK, /* Constants required for hardware setup. The tick ISR runs off the ACLK,
not the MCLK. */ * not the MCLK. */
#define portACLK_FREQUENCY_HZ ( ( TickType_t ) 32768 ) #define portACLK_FREQUENCY_HZ ( ( TickType_t ) 32768 )
#define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 ) #define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 )
#define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x08 ) #define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x08 )
/* We require the address of the pxCurrentTCB variable, but don't want to know /* We require the address of the pxCurrentTCB variable, but don't want to know
any details of its type. */ * any details of its type. */
typedef void TCB_t; typedef void TCB_t;
extern volatile TCB_t * volatile pxCurrentTCB; extern volatile TCB_t * volatile pxCurrentTCB;
/* Each task maintains a count of the critical section nesting depth. Each /* Each task maintains a count of the critical section nesting depth. Each
time a critical section is entered the count is incremented. Each time a * time a critical section is entered the count is incremented. Each time a
critical section is exited the count is decremented - with interrupts only * critical section is exited the count is decremented - with interrupts only
being re-enabled if the count is zero. * being re-enabled if the count is zero.
*
usCriticalNesting will get set to zero when the scheduler starts, but must * usCriticalNesting will get set to zero when the scheduler starts, but must
not be initialised to zero as this will cause problems during the startup * not be initialised to zero as this will cause problems during the startup
sequence. */ * sequence. */
volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING; volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -68,25 +68,27 @@ void vPortSetupTimerInterrupt( void );
* *
* See the header file portable.h. * See the header file portable.h.
*/ */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{ {
uint16_t *pusTopOfStack; uint16_t * pusTopOfStack;
uint32_t *pulTopOfStack, ulTemp; uint32_t * pulTopOfStack, ulTemp;
/* /*
Place a few bytes of known values on the bottom of the stack. * Place a few bytes of known values on the bottom of the stack.
This is just useful for debugging and can be included if required. * This is just useful for debugging and can be included if required.
*
*pxTopOfStack = ( StackType_t ) 0x1111; * pxTopOfStack = ( StackType_t ) 0x1111;
pxTopOfStack--; * pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x2222; * pxTopOfStack = ( StackType_t ) 0x2222;
pxTopOfStack--; * pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x3333; * pxTopOfStack = ( StackType_t ) 0x3333;
pxTopOfStack--; * pxTopOfStack--;
*/ */
/* Data types are need either 16 bits or 32 bits depending on the data /* Data types are need either 16 bits or 32 bits depending on the data
and code model used. */ * and code model used. */
if( sizeof( pxCode ) == sizeof( uint16_t ) ) if( sizeof( pxCode ) == sizeof( uint16_t ) )
{ {
pusTopOfStack = ( uint16_t * ) pxTopOfStack; pusTopOfStack = ( uint16_t * ) pxTopOfStack;
@ -135,19 +137,19 @@ uint32_t *pulTopOfStack, ulTemp;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x4444; *pxTopOfStack = ( StackType_t ) 0x4444;
pxTopOfStack--; pxTopOfStack--;
#else #else /* ifdef PRELOAD_REGISTER_VALUES */
pxTopOfStack -= 3; pxTopOfStack -= 3;
*pxTopOfStack = ( StackType_t ) pvParameters; *pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack -= 9; pxTopOfStack -= 9;
#endif #endif /* ifdef PRELOAD_REGISTER_VALUES */
/* A variable is used to keep track of the critical section nesting. /* A variable is used to keep track of the critical section nesting.
This variable has to be stored as part of the task context and is * This variable has to be stored as part of the task context and is
initially set to zero. */ * initially set to zero. */
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING; *pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
/* Return a pointer to the top of the stack we have generated so this can /* Return a pointer to the top of the stack we have generated so this can
be stored in the task control block for the task. */ * be stored in the task control block for the task. */
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -155,7 +157,7 @@ uint32_t *pulTopOfStack, ulTemp;
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the MSP430 port will get stopped. If required simply /* It is unlikely that the MSP430 port will get stopped. If required simply
disable the tick interrupt here. */ * disable the tick interrupt here. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -171,7 +173,7 @@ void vPortSetupTimerInterrupt( void )
#pragma vector=configTICK_VECTOR #pragma vector=configTICK_VECTOR
interrupt void vTickISREntry( void ) interrupt void vTickISREntry( void )
{ {
extern void vPortTickISR( void ); extern void vPortTickISR( void );
__bic_SR_register_on_exit( SCG1 + SCG0 + OSCOFF + CPUOFF ); __bic_SR_register_on_exit( SCG1 + SCG0 + OSCOFF + CPUOFF );
#if configUSE_PREEMPTION == 1 #if configUSE_PREEMPTION == 1
@ -182,5 +184,3 @@ extern void vPortTickISR( void );
vPortCooperativeTickISR(); vPortCooperativeTickISR();
#endif #endif
} }

View file

@ -60,7 +60,7 @@ typedef portSTACK_TYPE StackType_t;
typedef short BaseType_t; typedef short BaseType_t;
typedef unsigned short UBaseType_t; typedef unsigned short UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
@ -79,8 +79,8 @@ typedef unsigned short UBaseType_t;
#define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 ) #define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 )
#define portENTER_CRITICAL() \ #define portENTER_CRITICAL() \
{ \ { \
extern volatile uint16_t usCriticalNesting; \ extern volatile uint16_t usCriticalNesting; \
\ \
portDISABLE_INTERRUPTS(); \ portDISABLE_INTERRUPTS(); \
\ \
@ -88,11 +88,11 @@ extern volatile uint16_t usCriticalNesting; \
/* directly. Increment ulCriticalNesting to keep a count of how many */ \ /* directly. Increment ulCriticalNesting to keep a count of how many */ \
/* times portENTER_CRITICAL() has been called. */ \ /* times portENTER_CRITICAL() has been called. */ \
usCriticalNesting++; \ usCriticalNesting++; \
} }
#define portEXIT_CRITICAL() \ #define portEXIT_CRITICAL() \
{ \ { \
extern volatile uint16_t usCriticalNesting; \ extern volatile uint16_t usCriticalNesting; \
\ \
if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \ if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \
{ \ { \
@ -106,7 +106,7 @@ extern volatile uint16_t usCriticalNesting; \
portENABLE_INTERRUPTS(); \ portENABLE_INTERRUPTS(); \
} \ } \
} \ } \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
@ -126,8 +126,8 @@ extern void vPortYield( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
extern void vTaskSwitchContext( void ); extern void vTaskSwitchContext( void );
#define portYIELD_FROM_ISR( x ) if( x ) vPortYield() #define portYIELD_FROM_ISR( x ) if( x ) vPortYield()
@ -135,8 +135,7 @@ extern void vTaskSwitchContext( void );
void vApplicationSetupTimerInterrupt( void ); void vApplicationSetupTimerInterrupt( void );
/* sizeof( int ) != sizeof( long ) so a full printf() library is required if /* sizeof( int ) != sizeof( long ) so a full printf() library is required if
run time stats information is to be displayed. */ * run time stats information is to be displayed. */
#define portLU_PRINTF_SPECIFIER_REQUIRED #define portLU_PRINTF_SPECIFIER_REQUIRED
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -32,7 +32,7 @@
#define portINITIAL_FORMAT_VECTOR ( ( StackType_t ) 0x4000 ) #define portINITIAL_FORMAT_VECTOR ( ( StackType_t ) 0x4000 )
/* Supervisor mode set. */ /* Supervisor mode set. */
#define portINITIAL_STATUS_REGISTER ( ( StackType_t ) 0x2000) #define portINITIAL_STATUS_REGISTER ( ( StackType_t ) 0x2000 )
/* The clock prescale into the timer peripheral. */ /* The clock prescale into the timer peripheral. */
#define portPRESCALE_VALUE ( ( uint8_t ) 10 ) #define portPRESCALE_VALUE ( ( uint8_t ) 10 )
@ -44,20 +44,23 @@ asm void interrupt VectorNumber_VL1swi vPortYieldISR( void );
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
/* Used to keep track of the number of nested calls to taskENTER_CRITICAL(). This /* Used to keep track of the number of nested calls to taskENTER_CRITICAL(). This
will be set to 0 prior to the first task being started. */ * will be set to 0 prior to the first task being started. */
static uint32_t ulCriticalNesting = 0x9999UL; static uint32_t ulCriticalNesting = 0x9999UL;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{ {
uint32_t ulOriginalA5;
uint32_t ulOriginalA5; __asm {
MOVE.L A5, ulOriginalA5
__asm{ MOVE.L A5, ulOriginalA5 }; };
*pxTopOfStack = (StackType_t) 0xDEADBEEF; *pxTopOfStack = ( StackType_t ) 0xDEADBEEF;
pxTopOfStack--; pxTopOfStack--;
/* Exception stack frame starts with the return address. */ /* Exception stack frame starts with the return address. */
@ -82,7 +85,7 @@ uint32_t ulOriginalA5;
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
extern void vPortStartFirstTask( void ); extern void vPortStartFirstTask( void );
ulCriticalNesting = 0UL; ulCriticalNesting = 0UL;
@ -105,7 +108,7 @@ static void prvSetupTimerInterrupt( void )
RTCMOD = portRTC_CLOCK_HZ / configTICK_RATE_HZ; RTCMOD = portRTC_CLOCK_HZ / configTICK_RATE_HZ;
/* Enable the RTC to generate interrupts - interrupts are already disabled /* Enable the RTC to generate interrupts - interrupts are already disabled
when this code executes. */ * when this code executes. */
RTCSC_RTIE = 1; RTCSC_RTIE = 1;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -121,19 +124,20 @@ void vPortEnterCritical( void )
if( ulCriticalNesting == 0UL ) if( ulCriticalNesting == 0UL )
{ {
/* Guard against context switches being pended simultaneously with a /* Guard against context switches being pended simultaneously with a
critical section being entered. */ * critical section being entered. */
do do
{ {
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
if( INTC_FRC == 0UL ) if( INTC_FRC == 0UL )
{ {
break; break;
} }
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
} while( 1 ); } while( 1 );
} }
ulCriticalNesting++; ulCriticalNesting++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -141,6 +145,7 @@ void vPortEnterCritical( void )
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
ulCriticalNesting--; ulCriticalNesting--;
if( ulCriticalNesting == 0 ) if( ulCriticalNesting == 0 )
{ {
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
@ -150,7 +155,7 @@ void vPortExitCritical( void )
void vPortYieldHandler( void ) void vPortYieldHandler( void )
{ {
uint32_t ulSavedInterruptMask; uint32_t ulSavedInterruptMask;
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR(); ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
{ {
@ -164,7 +169,7 @@ uint32_t ulSavedInterruptMask;
void interrupt VectorNumber_Vrtc vPortTickISR( void ) void interrupt VectorNumber_Vrtc vPortTickISR( void )
{ {
uint32_t ulSavedInterruptMask; uint32_t ulSavedInterruptMask;
/* Clear the interrupt. */ /* Clear the interrupt. */
RTCSC |= RTCSC_RTIF_MASK; RTCSC |= RTCSC_RTIF_MASK;
@ -179,4 +184,3 @@ uint32_t ulSavedInterruptMask;
} }
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask ); portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
} }

View file

@ -25,11 +25,11 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -42,73 +42,73 @@ extern "C" {
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portBYTE_ALIGNMENT 4 #define portBYTE_ALIGNMENT 4
#define portSTACK_GROWTH -1 #define portSTACK_GROWTH -1
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
uint32_t ulPortSetIPL( uint32_t ); uint32_t ulPortSetIPL( uint32_t );
#define portDISABLE_INTERRUPTS() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY ) #define portDISABLE_INTERRUPTS() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
#define portENABLE_INTERRUPTS() ulPortSetIPL( 0 ) #define portENABLE_INTERRUPTS() ulPortSetIPL( 0 )
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
extern UBaseType_t uxPortSetInterruptMaskFromISR( void ); extern UBaseType_t uxPortSetInterruptMaskFromISR( void );
extern void vPortClearInterruptMaskFromISR( UBaseType_t ); extern void vPortClearInterruptMaskFromISR( UBaseType_t );
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY ) #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) ulPortSetIPL( uxSavedStatusRegister ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) ulPortSetIPL( uxSavedStatusRegister )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
#define portNOP() asm volatile ( "nop" ) #define portNOP() asm volatile ( "nop" )
/* Context switches are requested using the force register. */ /* Context switches are requested using the force register. */
#define portYIELD() INTC_SFRC = 0x3E; portNOP(); portNOP(); portNOP(); portNOP(); portNOP() #define portYIELD() INTC_SFRC = 0x3E; portNOP(); portNOP(); portNOP(); portNOP(); portNOP()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) __attribute__((noreturn)) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) __attribute__( ( noreturn ) )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) \ #define portEND_SWITCHING_ISR( xSwitchRequired ) \
if( xSwitchRequired != pdFALSE ) \
{ \ { \
portYIELD(); \ portYIELD(); \
} }
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -32,36 +32,38 @@
#define portINITIAL_FORMAT_VECTOR ( ( StackType_t ) 0x4000 ) #define portINITIAL_FORMAT_VECTOR ( ( StackType_t ) 0x4000 )
/* Supervisor mode set. */ /* Supervisor mode set. */
#define portINITIAL_STATUS_REGISTER ( ( StackType_t ) 0x2000) #define portINITIAL_STATUS_REGISTER ( ( StackType_t ) 0x2000 )
/* Used to keep track of the number of nested calls to taskENTER_CRITICAL(). This /* Used to keep track of the number of nested calls to taskENTER_CRITICAL(). This
will be set to 0 prior to the first task being started. */ * will be set to 0 prior to the first task being started. */
static uint32_t ulCriticalNesting = 0x9999UL; static uint32_t ulCriticalNesting = 0x9999UL;
#define portSAVE_CONTEXT() \ #define portSAVE_CONTEXT() \
lea.l (-60, %sp), %sp; \ lea.l( -60, % sp ), % sp; \
movem.l %d0-%fp, (%sp); \ movem.l % d0 - % fp, ( % sp ); \
move.l pxCurrentTCB, %a0; \ move.l pxCurrentTCB, % a0; \
move.l %sp, (%a0); move.l % sp, ( % a0 );
#define portRESTORE_CONTEXT() \ #define portRESTORE_CONTEXT() \
move.l pxCurrentTCB, %a0; \ move.l pxCurrentTCB, % a0; \
move.l (%a0), %sp; \ move.l( % a0 ), % sp; \
movem.l (%sp), %d0-%fp; \ movem.l( % sp ), % d0 - % fp; \
lea.l %sp@(60), %sp; \ lea.l % sp@( 60 ), % sp; \
rte rte
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{ {
*pxTopOfStack = ( StackType_t ) pvParameters; *pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = (StackType_t) 0xDEADBEEF; *pxTopOfStack = ( StackType_t ) 0xDEADBEEF;
pxTopOfStack--; pxTopOfStack--;
/* Exception stack frame starts with the return address. */ /* Exception stack frame starts with the return address. */
@ -80,7 +82,7 @@ StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t p
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
extern void vPortStartFirstTask( void ); extern void vPortStartFirstTask( void );
ulCriticalNesting = 0UL; ulCriticalNesting = 0UL;
@ -105,19 +107,20 @@ void vPortEnterCritical( void )
if( ulCriticalNesting == 0UL ) if( ulCriticalNesting == 0UL )
{ {
/* Guard against context switches being pended simultaneously with a /* Guard against context switches being pended simultaneously with a
critical section being entered. */ * critical section being entered. */
do do
{ {
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
if( MCF_INTC0_INTFRCH == 0UL ) if( MCF_INTC0_INTFRCH == 0UL )
{ {
break; break;
} }
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
} while( 1 ); } while( 1 );
} }
ulCriticalNesting++; ulCriticalNesting++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -125,6 +128,7 @@ void vPortEnterCritical( void )
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
ulCriticalNesting--; ulCriticalNesting--;
if( ulCriticalNesting == 0 ) if( ulCriticalNesting == 0 )
{ {
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
@ -134,7 +138,7 @@ void vPortExitCritical( void )
void vPortYieldHandler( void ) void vPortYieldHandler( void )
{ {
uint32_t ulSavedInterruptMask; uint32_t ulSavedInterruptMask;
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR(); ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
/* Note this will clear all forced interrupts - this is done for speed. */ /* Note this will clear all forced interrupts - this is done for speed. */
@ -143,4 +147,3 @@ uint32_t ulSavedInterruptMask;
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask ); portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -25,11 +25,11 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -42,72 +42,72 @@ extern "C" {
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portBYTE_ALIGNMENT 4 #define portBYTE_ALIGNMENT 4
#define portSTACK_GROWTH -1 #define portSTACK_GROWTH -1
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
uint32_t ulPortSetIPL( uint32_t ); uint32_t ulPortSetIPL( uint32_t );
#define portDISABLE_INTERRUPTS() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY ) #define portDISABLE_INTERRUPTS() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
#define portENABLE_INTERRUPTS() ulPortSetIPL( 0 ) #define portENABLE_INTERRUPTS() ulPortSetIPL( 0 )
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
extern UBaseType_t uxPortSetInterruptMaskFromISR( void ); extern UBaseType_t uxPortSetInterruptMaskFromISR( void );
extern void vPortClearInterruptMaskFromISR( UBaseType_t ); extern void vPortClearInterruptMaskFromISR( UBaseType_t );
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY ) #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) ulPortSetIPL( uxSavedStatusRegister ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) ulPortSetIPL( uxSavedStatusRegister )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
#define portNOP() asm volatile ( "nop" ) #define portNOP() asm volatile ( "nop" )
/* Note this will overwrite all other bits in the force register, it is done this way for speed. */ /* Note this will overwrite all other bits in the force register, it is done this way for speed. */
#define portYIELD() MCF_INTC0_INTFRCL = ( 1UL << configYIELD_INTERRUPT_VECTOR ); portNOP(); portNOP() /* -32 as we are using the high word of the 64bit mask. */ #define portYIELD() MCF_INTC0_INTFRCL = ( 1UL << configYIELD_INTERRUPT_VECTOR ); portNOP(); portNOP() /* -32 as we are using the high word of the 64bit mask. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) __attribute__((noreturn)) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) __attribute__( ( noreturn ) )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) \ #define portEND_SWITCHING_ISR( xSwitchRequired ) \
if( xSwitchRequired != pdFALSE ) \
{ \ { \
portYIELD(); \ portYIELD(); \
} }
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -30,8 +30,8 @@
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the HCS12 port. * Implementation of functions defined in portable.h for the HCS12 port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* /*
@ -41,29 +41,29 @@
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
/* Interrupt service routines have to be in non-banked memory - as does the /* Interrupt service routines have to be in non-banked memory - as does the
scheduler startup function. */ * scheduler startup function. */
#pragma CODE_SEG __NEAR_SEG NON_BANKED #pragma CODE_SEG __NEAR_SEG NON_BANKED
/* Manual context switch function. This is the SWI ISR. */ /* Manual context switch function. This is the SWI ISR. */
void interrupt vPortYield( void ); void interrupt vPortYield( void );
/* Tick context switch function. This is the timer ISR. */ /* Tick context switch function. This is the timer ISR. */
void interrupt vPortTickInterrupt( void ); void interrupt vPortTickInterrupt( void );
/* Simply called by xPortStartScheduler(). xPortStartScheduler() does not /* Simply called by xPortStartScheduler(). xPortStartScheduler() does not
start the scheduler directly because the header file containing the * start the scheduler directly because the header file containing the
xPortStartScheduler() prototype is part of the common kernel code, and * xPortStartScheduler() prototype is part of the common kernel code, and
therefore cannot use the CODE_SEG pragma. */ * therefore cannot use the CODE_SEG pragma. */
static BaseType_t xBankedStartScheduler( void ); static BaseType_t xBankedStartScheduler( void );
#pragma CODE_SEG DEFAULT #pragma CODE_SEG DEFAULT
/* Calls to portENTER_CRITICAL() can be nested. When they are nested the /* Calls to portENTER_CRITICAL() can be nested. When they are nested the
critical section should not be left (i.e. interrupts should not be re-enabled) * critical section should not be left (i.e. interrupts should not be re-enabled)
until the nesting depth reaches 0. This variable simply tracks the nesting * until the nesting depth reaches 0. This variable simply tracks the nesting
depth. Each task maintains it's own critical nesting depth variable so * depth. Each task maintains it's own critical nesting depth variable so
uxCriticalNesting is saved and restored from the task stack during a context * uxCriticalNesting is saved and restored from the task stack during a context
switch. */ * switch. */
volatile UBaseType_t uxCriticalNesting = 0xff; volatile UBaseType_t uxCriticalNesting = 0xff;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -71,31 +71,33 @@ volatile UBaseType_t uxCriticalNesting = 0xff;
/* /*
* See header file for description. * See header file for description.
*/ */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{ {
/* /*
Place a few bytes of known values on the bottom of the stack. * Place a few bytes of known values on the bottom of the stack.
This can be uncommented to provide useful stack markers when debugging. * This can be uncommented to provide useful stack markers when debugging.
*
*pxTopOfStack = ( StackType_t ) 0x11; * pxTopOfStack = ( StackType_t ) 0x11;
pxTopOfStack--; * pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x22; * pxTopOfStack = ( StackType_t ) 0x22;
pxTopOfStack--; * pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x33; * pxTopOfStack = ( StackType_t ) 0x33;
pxTopOfStack--; * pxTopOfStack--;
*/ */
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. In this case the stack as * expected by the portRESTORE_CONTEXT() macro. In this case the stack as
expected by the HCS12 RTI instruction. */ * expected by the HCS12 RTI instruction. */
/* The address of the task function is placed in the stack byte at a time. */ /* The address of the task function is placed in the stack byte at a time. */
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pxCode) ) + 1 ); *pxTopOfStack = ( StackType_t ) *( ( ( StackType_t * ) ( &pxCode ) ) + 1 );
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pxCode) ) + 0 ); *pxTopOfStack = ( StackType_t ) *( ( ( StackType_t * ) ( &pxCode ) ) + 0 );
pxTopOfStack--; pxTopOfStack--;
/* Next are all the registers that form part of the task context. */ /* Next are all the registers that form part of the task context. */
@ -113,15 +115,15 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
pxTopOfStack--; pxTopOfStack--;
/* A register contains parameter high byte. */ /* A register contains parameter high byte. */
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pvParameters) ) + 0 ); *pxTopOfStack = ( StackType_t ) *( ( ( StackType_t * ) ( &pvParameters ) ) + 0 );
pxTopOfStack--; pxTopOfStack--;
/* B register contains parameter low byte. */ /* B register contains parameter low byte. */
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pvParameters) ) + 1 ); *pxTopOfStack = ( StackType_t ) *( ( ( StackType_t * ) ( &pvParameters ) ) + 1 );
pxTopOfStack--; pxTopOfStack--;
/* CCR: Note that when the task starts interrupts will be enabled since /* CCR: Note that when the task starts interrupts will be enabled since
"I" bit of CCR is cleared */ * "I" bit of CCR is cleared */
*pxTopOfStack = ( StackType_t ) 0x00; *pxTopOfStack = ( StackType_t ) 0x00;
pxTopOfStack--; pxTopOfStack--;
@ -132,7 +134,7 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
#endif #endif
/* Finally the critical nesting depth is initialised with 0 (not within /* Finally the critical nesting depth is initialised with 0 (not within
a critical section). */ * a critical section). */
*pxTopOfStack = ( StackType_t ) 0x00; *pxTopOfStack = ( StackType_t ) 0x00;
return pxTopOfStack; return pxTopOfStack;
@ -155,10 +157,10 @@ static void prvSetupTimerInterrupt( void )
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* xPortStartScheduler() does not start the scheduler directly because /* xPortStartScheduler() does not start the scheduler directly because
the header file containing the xPortStartScheduler() prototype is part * the header file containing the xPortStartScheduler() prototype is part
of the common kernel code, and therefore cannot use the CODE_SEG pragma. * of the common kernel code, and therefore cannot use the CODE_SEG pragma.
Instead it simply calls the locally defined xBankedStartScheduler() - * Instead it simply calls the locally defined xBankedStartScheduler() -
which does use the CODE_SEG pragma. */ * which does use the CODE_SEG pragma. */
return xBankedStartScheduler(); return xBankedStartScheduler();
} }
@ -169,7 +171,7 @@ BaseType_t xPortStartScheduler( void )
static BaseType_t xBankedStartScheduler( void ) static BaseType_t xBankedStartScheduler( void )
{ {
/* Configure the timer that will generate the RTOS tick. Interrupts are /* Configure the timer that will generate the RTOS tick. Interrupts are
disabled when this function is called. */ * disabled when this function is called. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Restore the context of the first task. */ /* Restore the context of the first task. */
@ -220,17 +222,15 @@ void interrupt vPortTickInterrupt( void )
TFLG1 = 1; TFLG1 = 1;
/* Restore the context of a task - which may be a different task /* Restore the context of a task - which may be a different task
to that interrupted. */ * to that interrupted. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
#else #else /* if configUSE_PREEMPTION == 1 */
{ {
xTaskIncrementTick(); xTaskIncrementTick();
TFLG1 = 1; TFLG1 = 1;
} }
#endif #endif /* if configUSE_PREEMPTION == 1 */
} }
#pragma CODE_SEG DEFAULT #pragma CODE_SEG DEFAULT

View file

@ -51,7 +51,7 @@ typedef portSTACK_TYPE StackType_t;
typedef signed char BaseType_t; typedef signed char BaseType_t;
typedef unsigned char UBaseType_t; typedef unsigned char UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
@ -79,12 +79,12 @@ typedef unsigned char UBaseType_t;
* directly. Each task maintains its own nesting count. * directly. Each task maintains its own nesting count.
*/ */
#define portENTER_CRITICAL() \ #define portENTER_CRITICAL() \
{ \ { \
extern volatile UBaseType_t uxCriticalNesting; \ extern volatile UBaseType_t uxCriticalNesting; \
\ \
portDISABLE_INTERRUPTS(); \ portDISABLE_INTERRUPTS(); \
uxCriticalNesting++; \ uxCriticalNesting++; \
} }
/* /*
* Interrupts are disabled so we can access the nesting count directly. If the * Interrupts are disabled so we can access the nesting count directly. If the
@ -92,7 +92,7 @@ typedef unsigned char UBaseType_t;
* section and interrupts can be re-enabled. * section and interrupts can be re-enabled.
*/ */
#define portEXIT_CRITICAL() \ #define portEXIT_CRITICAL() \
{ \ { \
extern volatile UBaseType_t uxCriticalNesting; \ extern volatile UBaseType_t uxCriticalNesting; \
\ \
uxCriticalNesting--; \ uxCriticalNesting--; \
@ -100,7 +100,7 @@ typedef unsigned char UBaseType_t;
{ \ { \
portENABLE_INTERRUPTS(); \ portENABLE_INTERRUPTS(); \
} \ } \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
@ -116,7 +116,8 @@ typedef unsigned char UBaseType_t;
*/ */
#ifdef BANKED_MODEL #ifdef BANKED_MODEL
/*
/*
* Load the stack pointer for the task, then pull the critical nesting * Load the stack pointer for the task, then pull the critical nesting
* count and PPAGE register from the stack. The remains of the * count and PPAGE register from the stack. The remains of the
* context are restored by the RTI instruction. * context are restored by the RTI instruction.
@ -134,7 +135,7 @@ typedef unsigned char UBaseType_t;
__asm( "staa 0x30" ); /* 0x30 = PPAGE */ \ __asm( "staa 0x30" ); /* 0x30 = PPAGE */ \
} }
/* /*
* By the time this macro is called the processor has already stacked the * By the time this macro is called the processor has already stacked the
* registers. Simply stack the nesting count and PPAGE value, then save * registers. Simply stack the nesting count and PPAGE value, then save
* the task stack pointer. * the task stack pointer.
@ -151,9 +152,9 @@ typedef unsigned char UBaseType_t;
__asm( "ldx pxCurrentTCB" ); \ __asm( "ldx pxCurrentTCB" ); \
__asm( "sts 0, x" ); \ __asm( "sts 0, x" ); \
} }
#else #else /* ifdef BANKED_MODEL */
/* /*
* These macros are as per the BANKED versions above, but without saving * These macros are as per the BANKED versions above, but without saving
* and restoring the PPAGE register. * and restoring the PPAGE register.
*/ */
@ -179,7 +180,7 @@ typedef unsigned char UBaseType_t;
__asm( "ldx pxCurrentTCB" ); \ __asm( "ldx pxCurrentTCB" ); \
__asm( "sts 0, x" ); \ __asm( "sts 0, x" ); \
} }
#endif #endif /* ifdef BANKED_MODEL */
/* /*
* Utility macro to call macros above in correct order in order to perform a * Utility macro to call macros above in correct order in order to perform a
@ -194,8 +195,7 @@ typedef unsigned char UBaseType_t;
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

File diff suppressed because it is too large Load diff

View file

@ -26,13 +26,13 @@
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the Atmel AT91R40008 * Implementation of functions defined in portable.h for the Atmel AT91R40008
* port. * port.
* *
* Components that can be compiled to either ARM or THUMB mode are * Components that can be compiled to either ARM or THUMB mode are
* contained in this file. The ISR routines, which can only be compiled * contained in this file. The ISR routines, which can only be compiled
* to ARM mode are contained in portISR.c. * to ARM mode are contained in portISR.c.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Standard includes. */ /* Standard includes. */
#include <stdlib.h> #include <stdlib.h>
@ -72,22 +72,24 @@ extern void vPortISRStartFirstTask( void );
* *
* See header file for description. * See header file for description.
*/ */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{ {
StackType_t *pxOriginalTOS; StackType_t * pxOriginalTOS;
pxOriginalTOS = pxTopOfStack; pxOriginalTOS = pxTopOfStack;
/* To ensure asserts in tasks.c don't fail, although in this case the assert /* To ensure asserts in tasks.c don't fail, although in this case the assert
is not really required. */ * is not really required. */
pxTopOfStack--; pxTopOfStack--;
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. */ * expected by the portRESTORE_CONTEXT() macro. */
/* First on the stack is the return address - which in this case is the /* First on the stack is the return address - which in this case is the
start of the task. The offset is added to make the return address appear * start of the task. The offset is added to make the return address appear
as it would within an IRQ ISR. */ * as it would within an IRQ ISR. */
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; *pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
pxTopOfStack--; pxTopOfStack--;
@ -121,12 +123,12 @@ StackType_t *pxOriginalTOS;
pxTopOfStack--; pxTopOfStack--;
/* When the task starts is will expect to find the function parameter in /* When the task starts is will expect to find the function parameter in
R0. */ * R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
/* The last thing onto the stack is the status register, which is set for /* The last thing onto the stack is the status register, which is set for
system mode, with interrupts enabled. */ * system mode, with interrupts enabled. */
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR; *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
#ifdef THUMB_INTERWORK #ifdef THUMB_INTERWORK
@ -139,9 +141,9 @@ StackType_t *pxOriginalTOS;
pxTopOfStack--; pxTopOfStack--;
/* Some optimisation levels use the stack differently to others. This /* Some optimisation levels use the stack differently to others. This
means the interrupt flags cannot always be stored on the stack and will * means the interrupt flags cannot always be stored on the stack and will
instead be stored in a variable, which is then saved as part of the * instead be stored in a variable, which is then saved as part of the
tasks context. */ * tasks context. */
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING; *pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
return pxTopOfStack; return pxTopOfStack;
@ -151,7 +153,7 @@ StackType_t *pxOriginalTOS;
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ * here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Start the first task. */ /* Start the first task. */
@ -165,7 +167,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the ARM port will require this function as there /* It is unlikely that the ARM port will require this function as there
is nothing to return to. */ * is nothing to return to. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -174,7 +176,7 @@ void vPortEndScheduler( void )
*/ */
static void prvSetupTimerInterrupt( void ) static void prvSetupTimerInterrupt( void )
{ {
volatile uint32_t ulDummy; volatile uint32_t ulDummy;
/* Enable clock to the tick timer... */ /* Enable clock to the tick timer... */
AT91C_BASE_PS->PS_PCER = portTIMER_CLK_ENABLE_BIT; AT91C_BASE_PS->PS_PCER = portTIMER_CLK_ENABLE_BIT;
@ -189,17 +191,17 @@ volatile uint32_t ulDummy;
ulDummy = portTIMER_REG_BASE_PTR->TC_SR; ulDummy = portTIMER_REG_BASE_PTR->TC_SR;
/* Store interrupt handler function address in tick timer vector register... /* Store interrupt handler function address in tick timer vector register...
The ISR installed depends on whether the preemptive or cooperative * The ISR installed depends on whether the preemptive or cooperative
scheduler is being used. */ * scheduler is being used. */
#if configUSE_PREEMPTION == 1 #if configUSE_PREEMPTION == 1
{ {
extern void ( vPreemptiveTick )( void ); extern void( vPreemptiveTick )( void );
AT91C_BASE_AIC->AIC_SVR[portTIMER_AIC_CHANNEL] = ( uint32_t ) vPreemptiveTick; AT91C_BASE_AIC->AIC_SVR[ portTIMER_AIC_CHANNEL ] = ( uint32_t ) vPreemptiveTick;
} }
#else // else use cooperative scheduler #else // else use cooperative scheduler
{ {
extern void ( vNonPreemptiveTick )( void ); extern void( vNonPreemptiveTick )( void );
AT91C_BASE_AIC->AIC_SVR[portTIMER_AIC_CHANNEL] = ( uint32_t ) vNonPreemptiveTick; AT91C_BASE_AIC->AIC_SVR[ portTIMER_AIC_CHANNEL ] = ( uint32_t ) vNonPreemptiveTick;
} }
#endif #endif
@ -207,31 +209,30 @@ volatile uint32_t ulDummy;
AT91C_BASE_AIC->AIC_SMR[ portTIMER_AIC_CHANNEL ] = AIC_SRCTYPE_INT_LEVEL_SENSITIVE | portTICK_PRIORITY_6; AT91C_BASE_AIC->AIC_SMR[ portTIMER_AIC_CHANNEL ] = AIC_SRCTYPE_INT_LEVEL_SENSITIVE | portTICK_PRIORITY_6;
/* Enable the tick timer interrupt... /* Enable the tick timer interrupt...
*
First at timer level */ * First at timer level */
portTIMER_REG_BASE_PTR->TC_IER = TC_CPCS; portTIMER_REG_BASE_PTR->TC_IER = TC_CPCS;
/* Then at the AIC level. */ /* Then at the AIC level. */
AT91C_BASE_AIC->AIC_IECR = (1 << portTIMER_AIC_CHANNEL); AT91C_BASE_AIC->AIC_IECR = ( 1 << portTIMER_AIC_CHANNEL );
/* Calculate timer compare value to achieve the desired tick rate... */ /* Calculate timer compare value to achieve the desired tick rate... */
if( (configCPU_CLOCK_HZ / (configTICK_RATE_HZ * 2) ) <= 0xFFFF ) if( ( configCPU_CLOCK_HZ / ( configTICK_RATE_HZ * 2 ) ) <= 0xFFFF )
{ {
/* The tick rate is fast enough for us to use the faster timer input /* The tick rate is fast enough for us to use the faster timer input
clock (main clock / 2). */ * clock (main clock / 2). */
portTIMER_REG_BASE_PTR->TC_CMR = TC_WAVE | TC_CLKS_MCK2 | TC_BURST_NONE | TC_CPCTRG; portTIMER_REG_BASE_PTR->TC_CMR = TC_WAVE | TC_CLKS_MCK2 | TC_BURST_NONE | TC_CPCTRG;
portTIMER_REG_BASE_PTR->TC_RC = configCPU_CLOCK_HZ / (configTICK_RATE_HZ * 2); portTIMER_REG_BASE_PTR->TC_RC = configCPU_CLOCK_HZ / ( configTICK_RATE_HZ * 2 );
} }
else else
{ {
/* We must use a slower timer input clock (main clock / 8) because the /* We must use a slower timer input clock (main clock / 8) because the
tick rate is too slow for the faster input clock. */ * tick rate is too slow for the faster input clock. */
portTIMER_REG_BASE_PTR->TC_CMR = TC_WAVE | TC_CLKS_MCK8 | TC_BURST_NONE | TC_CPCTRG; portTIMER_REG_BASE_PTR->TC_CMR = TC_WAVE | TC_CLKS_MCK8 | TC_BURST_NONE | TC_CPCTRG;
portTIMER_REG_BASE_PTR->TC_RC = configCPU_CLOCK_HZ / (configTICK_RATE_HZ * 8); portTIMER_REG_BASE_PTR->TC_RC = configCPU_CLOCK_HZ / ( configTICK_RATE_HZ * 8 );
} }
/* Start tick timer... */ /* Start tick timer... */
portTIMER_REG_BASE_PTR->TC_CCR = TC_SWTRG | TC_CLKEN; portTIMER_REG_BASE_PTR->TC_CCR = TC_SWTRG | TC_CLKEN;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -26,17 +26,17 @@
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Components that can be compiled to either ARM or THUMB mode are * Components that can be compiled to either ARM or THUMB mode are
* contained in port.c The ISR routines, which can only be compiled * contained in port.c The ISR routines, which can only be compiled
* to ARM mode, are contained in this file. * to ARM mode, are contained in this file.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* /*
Changes from V3.2.4 * Changes from V3.2.4
*
+ The assembler statements are now included in a single asm block rather + The assembler statements are now included in a single asm block rather
than each line having its own asm block. + than each line having its own asm block.
*/ */
/* Scheduler includes. */ /* Scheduler includes. */
@ -53,7 +53,7 @@ volatile uint32_t ulCriticalNesting = 9999UL;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* ISR to handle manual context switches (from a call to taskYIELD()). */ /* ISR to handle manual context switches (from a call to taskYIELD()). */
void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked)); void vPortYieldProcessor( void ) __attribute__( ( interrupt( "SWI" ), naked ) );
/* /*
* The scheduler can only be started from ARM mode, hence the inclusion of this * The scheduler can only be started from ARM mode, hence the inclusion of this
@ -65,7 +65,7 @@ void vPortISRStartFirstTask( void );
void vPortISRStartFirstTask( void ) void vPortISRStartFirstTask( void )
{ {
/* Simply start the scheduler. This is included here as it can only be /* Simply start the scheduler. This is included here as it can only be
called from ARM mode. */ * called from ARM mode. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -81,9 +81,9 @@ void vPortISRStartFirstTask( void )
void vPortYieldProcessor( void ) void vPortYieldProcessor( void )
{ {
/* Within an IRQ ISR the link register has an offset from the true return /* Within an IRQ ISR the link register has an offset from the true return
address, but an SWI ISR does not. Add the offset manually so the same * address, but an SWI ISR does not. Add the offset manually so the same
ISR return code can be used in both cases. */ * ISR return code can be used in both cases. */
asm volatile ( "ADD LR, LR, #4" ); asm volatile ( "ADD LR, LR, #4");
/* Perform the context switch. First save the context of the current task. */ /* Perform the context switch. First save the context of the current task. */
portSAVE_CONTEXT(); portSAVE_CONTEXT();
@ -103,9 +103,9 @@ void vPortYieldProcessor( void )
#if configUSE_PREEMPTION == 0 #if configUSE_PREEMPTION == 0
/* The cooperative scheduler requires a normal IRQ service routine to /* The cooperative scheduler requires a normal IRQ service routine to
simply increment the system tick. */ * simply increment the system tick. */
void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ"))); void vNonPreemptiveTick( void ) __attribute__( ( interrupt( "IRQ" ) ) );
void vNonPreemptiveTick( void ) void vNonPreemptiveTick( void )
{ {
static volatile uint32_t ulDummy; static volatile uint32_t ulDummy;
@ -121,23 +121,23 @@ void vPortYieldProcessor( void )
#else /* else preemption is turned on */ #else /* else preemption is turned on */
/* The preemptive scheduler is defined as "naked" as the full context is /* The preemptive scheduler is defined as "naked" as the full context is
saved on entry as part of the context switch. */ * saved on entry as part of the context switch. */
void vPreemptiveTick( void ) __attribute__((naked)); void vPreemptiveTick( void ) __attribute__( ( naked ) );
void vPreemptiveTick( void ) void vPreemptiveTick( void )
{ {
/* Save the context of the interrupted task. */ /* Save the context of the interrupted task. */
portSAVE_CONTEXT(); portSAVE_CONTEXT();
/* WARNING - Do not use local (stack) variables here. Use globals /* WARNING - Do not use local (stack) variables here. Use globals
if you must! */ * if you must! */
static volatile uint32_t ulDummy; static volatile uint32_t ulDummy;
/* Clear tick timer interrupt indication. */ /* Clear tick timer interrupt indication. */
ulDummy = portTIMER_REG_BASE_PTR->TC_SR; ulDummy = portTIMER_REG_BASE_PTR->TC_SR;
/* Increment the RTOS tick count, then look for the highest priority /* Increment the RTOS tick count, then look for the highest priority
task that is ready to run. */ * task that is ready to run. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
vTaskSwitchContext(); vTaskSwitchContext();
@ -150,7 +150,7 @@ void vPortYieldProcessor( void )
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
#endif #endif /* if configUSE_PREEMPTION == 0 */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
@ -161,50 +161,50 @@ void vPortYieldProcessor( void )
*/ */
#ifdef THUMB_INTERWORK #ifdef THUMB_INTERWORK
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked)); void vPortDisableInterruptsFromThumb( void ) __attribute__( ( naked ) );
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked)); void vPortEnableInterruptsFromThumb( void ) __attribute__( ( naked ) );
void vPortDisableInterruptsFromThumb( void ) void vPortDisableInterruptsFromThumb( void )
{ {
asm volatile ( asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t"/* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t"/* Get CPSR. */
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "ORR R0, R0, #0xC0 \n\t"/* Disable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t"/* Write back modified value. */
"LDMIA SP!, {R0} \n\t" /* Pop R0. */ "LDMIA SP!, {R0} \n\t"/* Pop R0. */
"BX R14" ); /* Return back to thumb. */ "BX R14"); /* Return back to thumb. */
} }
void vPortEnableInterruptsFromThumb( void ) void vPortEnableInterruptsFromThumb( void )
{ {
asm volatile ( asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t"/* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t"/* Get CPSR. */
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ "BIC R0, R0, #0xC0 \n\t"/* Enable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t"/* Write back modified value. */
"LDMIA SP!, {R0} \n\t" /* Pop R0. */ "LDMIA SP!, {R0} \n\t"/* Pop R0. */
"BX R14" ); /* Return back to thumb. */ "BX R14"); /* Return back to thumb. */
} }
#endif /* THUMB_INTERWORK */ #endif /* THUMB_INTERWORK */
/* The code generated by the GCC compiler uses the stack in different ways at /* The code generated by the GCC compiler uses the stack in different ways at
different optimisation levels. The interrupt flags can therefore not always * different optimisation levels. The interrupt flags can therefore not always
be saved to the stack. Instead the critical section nesting level is stored * be saved to the stack. Instead the critical section nesting level is stored
in a variable, which is then saved as part of the stack context. */ * in a variable, which is then saved as part of the stack context. */
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */ /* Disable interrupts as per portDISABLE_INTERRUPTS(); */
asm volatile ( asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t"/* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t"/* Get CPSR. */
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "ORR R0, R0, #0xC0 \n\t"/* Disable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t"/* Write back modified value. */
"LDMIA SP!, {R0}" ); /* Pop R0. */ "LDMIA SP!, {R0}"); /* Pop R0. */
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
directly. Increment ulCriticalNesting to keep a count of how many times * directly. Increment ulCriticalNesting to keep a count of how many times
portENTER_CRITICAL() has been called. */ * portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
} }
@ -216,17 +216,16 @@ void vPortExitCritical( void )
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be /* If the nesting level has reached zero then interrupts should be
re-enabled. */ * re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Enable interrupts as per portEXIT_CRITICAL(). */ /* Enable interrupts as per portEXIT_CRITICAL(). */
asm volatile ( asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t"/* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t"/* Get CPSR. */
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ "BIC R0, R0, #0xC0 \n\t"/* Enable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t"/* Write back modified value. */
"LDMIA SP!, {R0}" ); /* Pop R0. */ "LDMIA SP!, {R0}"); /* Pop R0. */
} }
} }
} }

View file

@ -25,34 +25,34 @@
*/ */
/* /*
Changes from V3.2.3 * Changes from V3.2.3
*
+ Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1. + Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1.
+
Changes from V3.2.4 + Changes from V3.2.4
+
+ Removed the use of the %0 parameter within the assembler macros and + Removed the use of the %0 parameter within the assembler macros and
replaced them with hard coded registers. This will ensure the + replaced them with hard coded registers. This will ensure the
assembler does not select the link register as the temp register as + assembler does not select the link register as the temp register as
was occasionally happening previously. + was occasionally happening previously.
+
+ The assembler statements are now included in a single asm block rather + The assembler statements are now included in a single asm block rather
than each line having its own asm block. + than each line having its own asm block.
+
Changes from V4.5.0 + Changes from V4.5.0
+
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros + Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
and replaced them with portYIELD_FROM_ISR() macro. Application code + and replaced them with portYIELD_FROM_ISR() macro. Application code
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT() + should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
macros as per the V4.5.1 demo code. + macros as per the V4.5.1 demo code.
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -65,42 +65,42 @@ extern "C" {
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portYIELD() asm volatile ( "SWI 0" ) #define portYIELD() asm volatile ( "SWI 0" )
#define portNOP() asm volatile ( "NOP" ) #define portNOP() asm volatile ( "NOP" )
/* /*
* These define the timer to use for generating the tick interrupt. * These define the timer to use for generating the tick interrupt.
* They are put in this file so they can be shared between "port.c" * They are put in this file so they can be shared between "port.c"
* and "portisr.c". * and "portisr.c".
*/ */
#define portTIMER_REG_BASE_PTR AT91C_BASE_TC0 #define portTIMER_REG_BASE_PTR AT91C_BASE_TC0
#define portTIMER_CLK_ENABLE_BIT AT91C_PS_TC0 #define portTIMER_CLK_ENABLE_BIT AT91C_PS_TC0
#define portTIMER_AIC_CHANNEL ( ( uint32_t ) 4 ) #define portTIMER_AIC_CHANNEL ( ( uint32_t ) 4 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
@ -112,90 +112,90 @@ typedef unsigned long UBaseType_t;
* THUMB mode code will result in a compile time error. * THUMB mode code will result in a compile time error.
*/ */
#define portRESTORE_CONTEXT() \ #define portRESTORE_CONTEXT() \
{ \ { \
extern volatile void * volatile pxCurrentTCB; \ extern volatile void * volatile pxCurrentTCB; \
extern volatile uint32_t ulCriticalNesting; \ extern volatile uint32_t ulCriticalNesting; \
\ \
/* Set the LR to the task stack. */ \ /* Set the LR to the task stack. */ \
asm volatile ( \ asm volatile ( \
"LDR R0, =pxCurrentTCB \n\t" \ "LDR R0, =pxCurrentTCB \n\t"\
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t"\
"LDR LR, [R0] \n\t" \ "LDR LR, [R0] \n\t"\
\ \
/* The critical nesting depth is the first item on the stack. */ \ /* The critical nesting depth is the first item on the stack. */ \
/* Load it into the ulCriticalNesting variable. */ \ /* Load it into the ulCriticalNesting variable. */ \
"LDR R0, =ulCriticalNesting \n\t" \ "LDR R0, =ulCriticalNesting \n\t"\
"LDMFD LR!, {R1} \n\t" \ "LDMFD LR!, {R1} \n\t"\
"STR R1, [R0] \n\t" \ "STR R1, [R0] \n\t"\
\ \
/* Get the SPSR from the stack. */ \ /* Get the SPSR from the stack. */ \
"LDMFD LR!, {R0} \n\t" \ "LDMFD LR!, {R0} \n\t"\
"MSR SPSR, R0 \n\t" \ "MSR SPSR, R0 \n\t"\
\ \
/* Restore all system mode registers for the task. */ \ /* Restore all system mode registers for the task. */ \
"LDMFD LR, {R0-R14}^ \n\t" \ "LDMFD LR, {R0-R14}^ \n\t"\
"NOP \n\t" \ "NOP \n\t"\
\ \
/* Restore the return address. */ \ /* Restore the return address. */ \
"LDR LR, [LR, #+60] \n\t" \ "LDR LR, [LR, #+60] \n\t"\
\ \
/* And return - correcting the offset in the LR to obtain the */ \ /* And return - correcting the offset in the LR to obtain the */ \
/* correct address. */ \ /* correct address. */ \
"SUBS PC, LR, #4 \n\t" \ "SUBS PC, LR, #4 \n\t"\
); \ ); \
( void ) ulCriticalNesting; \ ( void ) ulCriticalNesting; \
( void ) pxCurrentTCB; \ ( void ) pxCurrentTCB; \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portSAVE_CONTEXT() \ #define portSAVE_CONTEXT() \
{ \ { \
extern volatile void * volatile pxCurrentTCB; \ extern volatile void * volatile pxCurrentTCB; \
extern volatile uint32_t ulCriticalNesting; \ extern volatile uint32_t ulCriticalNesting; \
\ \
/* Push R0 as we are going to use the register. */ \ /* Push R0 as we are going to use the register. */ \
asm volatile ( \ asm volatile ( \
"STMDB SP!, {R0} \n\t" \ "STMDB SP!, {R0} \n\t"\
\ \
/* Set R0 to point to the task stack pointer. */ \ /* Set R0 to point to the task stack pointer. */ \
"STMDB SP,{SP}^ \n\t" \ "STMDB SP,{SP}^ \n\t"\
"NOP \n\t" \ "NOP \n\t"\
"SUB SP, SP, #4 \n\t" \ "SUB SP, SP, #4 \n\t"\
"LDMIA SP!,{R0} \n\t" \ "LDMIA SP!,{R0} \n\t"\
\ \
/* Push the return address onto the stack. */ \ /* Push the return address onto the stack. */ \
"STMDB R0!, {LR} \n\t" \ "STMDB R0!, {LR} \n\t"\
\ \
/* Now we have saved LR we can use it instead of R0. */ \ /* Now we have saved LR we can use it instead of R0. */ \
"MOV LR, R0 \n\t" \ "MOV LR, R0 \n\t"\
\ \
/* Pop R0 so we can save it onto the system mode stack. */ \ /* Pop R0 so we can save it onto the system mode stack. */ \
"LDMIA SP!, {R0} \n\t" \ "LDMIA SP!, {R0} \n\t"\
\ \
/* Push all the system mode registers onto the task stack. */ \ /* Push all the system mode registers onto the task stack. */ \
"STMDB LR,{R0-LR}^ \n\t" \ "STMDB LR,{R0-LR}^ \n\t"\
"NOP \n\t" \ "NOP \n\t"\
"SUB LR, LR, #60 \n\t" \ "SUB LR, LR, #60 \n\t"\
\ \
/* Push the SPSR onto the task stack. */ \ /* Push the SPSR onto the task stack. */ \
"MRS R0, SPSR \n\t" \ "MRS R0, SPSR \n\t"\
"STMDB LR!, {R0} \n\t" \ "STMDB LR!, {R0} \n\t"\
\ \
"LDR R0, =ulCriticalNesting \n\t" \ "LDR R0, =ulCriticalNesting \n\t"\
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t"\
"STMDB LR!, {R0} \n\t" \ "STMDB LR!, {R0} \n\t"\
\ \
/* Store the new top of stack for the task. */ \ /* Store the new top of stack for the task. */ \
"LDR R0, =pxCurrentTCB \n\t" \ "LDR R0, =pxCurrentTCB \n\t"\
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t"\
"STR LR, [R0] \n\t" \ "STR LR, [R0] \n\t"\
); \ ); \
( void ) ulCriticalNesting; \ ( void ) ulCriticalNesting; \
( void ) pxCurrentTCB; \ ( void ) pxCurrentTCB; \
} }
#define portYIELD_FROM_ISR() vTaskSwitchContext() #define portYIELD_FROM_ISR() vTaskSwitchContext()
/* Critical section handling. */ /* Critical section handling. */
@ -206,49 +206,48 @@ extern volatile uint32_t ulCriticalNesting; \
* defined then the utilities are defined as macros here - as per other ports. * defined then the utilities are defined as macros here - as per other ports.
*/ */
#ifdef THUMB_INTERWORK #ifdef THUMB_INTERWORK
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked)); extern void vPortDisableInterruptsFromThumb( void ) __attribute__( ( naked ) );
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked)); extern void vPortEnableInterruptsFromThumb( void ) __attribute__( ( naked ) );
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb() #define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb() #define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
#else #else
#define portDISABLE_INTERRUPTS() \ #define portDISABLE_INTERRUPTS() \
asm volatile ( \ asm volatile ( \
"STMDB SP!, {R0} \n\t" /* Push R0. */ \ "STMDB SP!, {R0} \n\t" /* Push R0. */\
"MRS R0, CPSR \n\t" /* Get CPSR. */ \ "MRS R0, CPSR \n\t" /* Get CPSR. */\
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \ "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */\
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \ "MSR CPSR, R0 \n\t" /* Write back modified value. */\
"LDMIA SP!, {R0} " ) /* Pop R0. */ "LDMIA SP!, {R0} ") /* Pop R0. */
#define portENABLE_INTERRUPTS() \ #define portENABLE_INTERRUPTS() \
asm volatile ( \ asm volatile ( \
"STMDB SP!, {R0} \n\t" /* Push R0. */ \ "STMDB SP!, {R0} \n\t" /* Push R0. */\
"MRS R0, CPSR \n\t" /* Get CPSR. */ \ "MRS R0, CPSR \n\t" /* Get CPSR. */\
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \ "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */\
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \ "MSR CPSR, R0 \n\t" /* Write back modified value. */\
"LDMIA SP!, {R0} " ) /* Pop R0. */ "LDMIA SP!, {R0} ") /* Pop R0. */
#endif /* THUMB_INTERWORK */ #endif /* THUMB_INTERWORK */
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical(); #define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical(); #define portEXIT_CRITICAL() vPortExitCritical();
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,51 +1,50 @@
//* ---------------------------------------------------------------------------- /** ---------------------------------------------------------------------------- */
//* ATMEL Microcontroller Software Support - ROUSSET - /** ATMEL Microcontroller Software Support - ROUSSET - */
//* ---------------------------------------------------------------------------- /** ---------------------------------------------------------------------------- */
//* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR /** DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR */
//* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF /** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE /** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE */
//* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, /** DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, */
//* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT /** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
//* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, /** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
//* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF /** OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */
//* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING /** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
//* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, /** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
//* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
//* ---------------------------------------------------------------------------- /** ---------------------------------------------------------------------------- */
//* File Name : lib_AT91SAM7X256.h /** File Name : lib_AT91SAM7X256.h */
//* Object : AT91SAM7X256 inlined functions /** Object : AT91SAM7X256 inlined functions */
//* Generated : AT91 SW Application Group 05/20/2005 (16:22:29) /** Generated : AT91 SW Application Group 05/20/2005 (16:22:29) */
//* /** */
//* CVS Reference : /lib_dbgu.h/1.1/Fri Jan 31 12:18:40 2003// /** CVS Reference : /lib_dbgu.h/1.1/Fri Jan 31 12:18:40 2003// */
//* CVS Reference : /lib_pmc_SAM7X.h/1.1/Tue Feb 1 08:32:10 2005// /** CVS Reference : /lib_pmc_SAM7X.h/1.1/Tue Feb 1 08:32:10 2005// */
//* CVS Reference : /lib_VREG_6085B.h/1.1/Tue Feb 1 16:20:47 2005// /** CVS Reference : /lib_VREG_6085B.h/1.1/Tue Feb 1 16:20:47 2005// */
//* CVS Reference : /lib_rstc_6098A.h/1.1/Wed Oct 6 10:39:20 2004// /** CVS Reference : /lib_rstc_6098A.h/1.1/Wed Oct 6 10:39:20 2004// */
//* CVS Reference : /lib_ssc.h/1.4/Fri Jan 31 12:19:20 2003// /** CVS Reference : /lib_ssc.h/1.4/Fri Jan 31 12:19:20 2003// */
//* CVS Reference : /lib_wdtc_6080A.h/1.1/Wed Oct 6 10:38:30 2004// /** CVS Reference : /lib_wdtc_6080A.h/1.1/Wed Oct 6 10:38:30 2004// */
//* CVS Reference : /lib_usart.h/1.5/Thu Nov 21 16:01:54 2002// /** CVS Reference : /lib_usart.h/1.5/Thu Nov 21 16:01:54 2002// */
//* CVS Reference : /lib_spi2.h/1.1/Mon Aug 25 14:23:52 2003// /** CVS Reference : /lib_spi2.h/1.1/Mon Aug 25 14:23:52 2003// */
//* CVS Reference : /lib_pitc_6079A.h/1.2/Tue Nov 9 14:43:56 2004// /** CVS Reference : /lib_pitc_6079A.h/1.2/Tue Nov 9 14:43:56 2004// */
//* CVS Reference : /lib_aic_6075b.h/1.1/Fri May 20 14:01:19 2005// /** CVS Reference : /lib_aic_6075b.h/1.1/Fri May 20 14:01:19 2005// */
//* CVS Reference : /lib_aes_6149a.h/1.1/Mon Jan 17 07:43:09 2005// /** CVS Reference : /lib_aes_6149a.h/1.1/Mon Jan 17 07:43:09 2005// */
//* CVS Reference : /lib_twi.h/1.3/Mon Jul 19 14:27:58 2004// /** CVS Reference : /lib_twi.h/1.3/Mon Jul 19 14:27:58 2004// */
//* CVS Reference : /lib_adc.h/1.6/Fri Oct 17 09:12:38 2003// /** CVS Reference : /lib_adc.h/1.6/Fri Oct 17 09:12:38 2003// */
//* CVS Reference : /lib_rttc_6081A.h/1.1/Wed Oct 6 10:39:38 2004// /** CVS Reference : /lib_rttc_6081A.h/1.1/Wed Oct 6 10:39:38 2004// */
//* CVS Reference : /lib_udp.h/1.4/Wed Feb 16 08:39:34 2005// /** CVS Reference : /lib_udp.h/1.4/Wed Feb 16 08:39:34 2005// */
//* CVS Reference : /lib_des3_6150a.h/1.1/Mon Jan 17 09:19:19 2005// /** CVS Reference : /lib_des3_6150a.h/1.1/Mon Jan 17 09:19:19 2005// */
//* CVS Reference : /lib_tc_1753b.h/1.1/Fri Jan 31 12:20:02 2003// /** CVS Reference : /lib_tc_1753b.h/1.1/Fri Jan 31 12:20:02 2003// */
//* CVS Reference : /lib_MC_SAM7X.h/1.1/Thu Mar 25 15:19:14 2004// /** CVS Reference : /lib_MC_SAM7X.h/1.1/Thu Mar 25 15:19:14 2004// */
//* CVS Reference : /lib_pio.h/1.3/Fri Jan 31 12:18:56 2003// /** CVS Reference : /lib_pio.h/1.3/Fri Jan 31 12:18:56 2003// */
//* CVS Reference : /lib_can_AT91.h/1.4/Fri Oct 17 09:12:50 2003// /** CVS Reference : /lib_can_AT91.h/1.4/Fri Oct 17 09:12:50 2003// */
//* CVS Reference : /lib_PWM_SAM.h/1.3/Thu Jan 22 10:10:50 2004// /** CVS Reference : /lib_PWM_SAM.h/1.3/Thu Jan 22 10:10:50 2004// */
//* CVS Reference : /lib_pdc.h/1.2/Tue Jul 2 13:29:40 2002// /** CVS Reference : /lib_pdc.h/1.2/Tue Jul 2 13:29:40 2002// */
//* ---------------------------------------------------------------------------- /** ---------------------------------------------------------------------------- */
#include "AT91SAM7X256.h" #include "AT91SAM7X256.h"
//*---------------------------------------------------------------------------- /**---------------------------------------------------------------------------- */
//* \fn AT91F_AIC_ConfigureIt /** \fn AT91F_AIC_ConfigureIt */
//* \brief Interrupt Handler Initialization /** \brief Interrupt Handler Initialization */
//*---------------------------------------------------------------------------- /**---------------------------------------------------------------------------- */

File diff suppressed because it is too large Load diff

View file

@ -26,12 +26,12 @@
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM7 port. * Implementation of functions defined in portable.h for the ARM7 port.
* *
* Components that can be compiled to either ARM or THUMB mode are * Components that can be compiled to either ARM or THUMB mode are
* contained in this file. The ISR routines, which can only be compiled * contained in this file. The ISR routines, which can only be compiled
* to ARM mode are contained in portISR.c. * to ARM mode are contained in portISR.c.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Standard includes. */ /* Standard includes. */
#include <stdlib.h> #include <stdlib.h>
@ -81,22 +81,24 @@ extern void vPortISRStartFirstTask( void );
* *
* See header file for description. * See header file for description.
*/ */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{ {
StackType_t *pxOriginalTOS; StackType_t * pxOriginalTOS;
pxOriginalTOS = pxTopOfStack; pxOriginalTOS = pxTopOfStack;
/* To ensure asserts in tasks.c don't fail, although in this case the assert /* To ensure asserts in tasks.c don't fail, although in this case the assert
is not really required. */ * is not really required. */
pxTopOfStack--; pxTopOfStack--;
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. */ * expected by the portRESTORE_CONTEXT() macro. */
/* First on the stack is the return address - which in this case is the /* First on the stack is the return address - which in this case is the
start of the task. The offset is added to make the return address appear * start of the task. The offset is added to make the return address appear
as it would within an IRQ ISR. */ * as it would within an IRQ ISR. */
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; *pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
pxTopOfStack--; pxTopOfStack--;
@ -130,12 +132,12 @@ StackType_t *pxOriginalTOS;
pxTopOfStack--; pxTopOfStack--;
/* When the task starts is will expect to find the function parameter in /* When the task starts is will expect to find the function parameter in
R0. */ * R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
/* The last thing onto the stack is the status register, which is set for /* The last thing onto the stack is the status register, which is set for
system mode, with interrupts enabled. */ * system mode, with interrupts enabled. */
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR; *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
#ifdef THUMB_INTERWORK #ifdef THUMB_INTERWORK
@ -148,9 +150,9 @@ StackType_t *pxOriginalTOS;
pxTopOfStack--; pxTopOfStack--;
/* Some optimisation levels use the stack differently to others. This /* Some optimisation levels use the stack differently to others. This
means the interrupt flags cannot always be stored on the stack and will * means the interrupt flags cannot always be stored on the stack and will
instead be stored in a variable, which is then saved as part of the * instead be stored in a variable, which is then saved as part of the
tasks context. */ * tasks context. */
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING; *pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
return pxTopOfStack; return pxTopOfStack;
@ -160,7 +162,7 @@ StackType_t *pxOriginalTOS;
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ * here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Start the first task. */ /* Start the first task. */
@ -174,7 +176,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the ARM port will require this function as there /* It is unlikely that the ARM port will require this function as there
is nothing to return to. */ * is nothing to return to. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -183,30 +185,23 @@ void vPortEndScheduler( void )
*/ */
static void prvSetupTimerInterrupt( void ) static void prvSetupTimerInterrupt( void )
{ {
AT91PS_PITC pxPIT = AT91C_BASE_PITC; AT91PS_PITC pxPIT = AT91C_BASE_PITC;
/* Setup the AIC for PIT interrupts. The interrupt routine chosen depends /* Setup the AIC for PIT interrupts. The interrupt routine chosen depends
on whether the preemptive or cooperative scheduler is being used. */ * on whether the preemptive or cooperative scheduler is being used. */
#if configUSE_PREEMPTION == 0 #if configUSE_PREEMPTION == 0
extern void( vNonPreemptiveTick ) ( void );
extern void ( vNonPreemptiveTick ) ( void ); AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void ( * )( void ) )vNonPreemptiveTick );
AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vNonPreemptiveTick );
#else #else
extern void( vPreemptiveTick )( void );
extern void ( vPreemptiveTick )( void ); AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void ( * )( void ) )vPreemptiveTick );
AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vPreemptiveTick );
#endif #endif
/* Configure the PIT period. */ /* Configure the PIT period. */
pxPIT->PITC_PIMR = portPIT_ENABLE | portPIT_INT_ENABLE | portPIT_COUNTER_VALUE; pxPIT->PITC_PIMR = portPIT_ENABLE | portPIT_INT_ENABLE | portPIT_COUNTER_VALUE;
/* Enable the interrupt. Global interrupts are disables at this point so /* Enable the interrupt. Global interrupts are disables at this point so
this is safe. */ * this is safe. */
AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_SYS; AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_SYS;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -26,17 +26,17 @@
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Components that can be compiled to either ARM or THUMB mode are * Components that can be compiled to either ARM or THUMB mode are
* contained in port.c The ISR routines, which can only be compiled * contained in port.c The ISR routines, which can only be compiled
* to ARM mode, are contained in this file. * to ARM mode, are contained in this file.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* /*
Changes from V3.2.4 * Changes from V3.2.4
*
+ The assembler statements are now included in a single asm block rather + The assembler statements are now included in a single asm block rather
than each line having its own asm block. + than each line having its own asm block.
*/ */
/* Scheduler includes. */ /* Scheduler includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
@ -55,7 +55,7 @@ volatile uint32_t ulCriticalNesting = 9999UL;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* ISR to handle manual context switches (from a call to taskYIELD()). */ /* ISR to handle manual context switches (from a call to taskYIELD()). */
void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked)); void vPortYieldProcessor( void ) __attribute__( ( interrupt( "SWI" ), naked ) );
/* /*
* The scheduler can only be started from ARM mode, hence the inclusion of this * The scheduler can only be started from ARM mode, hence the inclusion of this
@ -67,7 +67,7 @@ void vPortISRStartFirstTask( void );
void vPortISRStartFirstTask( void ) void vPortISRStartFirstTask( void )
{ {
/* Simply start the scheduler. This is included here as it can only be /* Simply start the scheduler. This is included here as it can only be
called from ARM mode. */ * called from ARM mode. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -83,9 +83,9 @@ void vPortISRStartFirstTask( void )
void vPortYieldProcessor( void ) void vPortYieldProcessor( void )
{ {
/* Within an IRQ ISR the link register has an offset from the true return /* Within an IRQ ISR the link register has an offset from the true return
address, but an SWI ISR does not. Add the offset manually so the same * address, but an SWI ISR does not. Add the offset manually so the same
ISR return code can be used in both cases. */ * ISR return code can be used in both cases. */
__asm volatile ( "ADD LR, LR, #4" ); __asm volatile ( "ADD LR, LR, #4");
/* Perform the context switch. First save the context of the current task. */ /* Perform the context switch. First save the context of the current task. */
portSAVE_CONTEXT(); portSAVE_CONTEXT();
@ -105,16 +105,16 @@ void vPortYieldProcessor( void )
#if configUSE_PREEMPTION == 0 #if configUSE_PREEMPTION == 0
/* The cooperative scheduler requires a normal IRQ service routine to /* The cooperative scheduler requires a normal IRQ service routine to
simply increment the system tick. */ * simply increment the system tick. */
void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ"))); void vNonPreemptiveTick( void ) __attribute__( ( interrupt( "IRQ" ) ) );
void vNonPreemptiveTick( void ) void vNonPreemptiveTick( void )
{ {
uint32_t ulDummy; uint32_t ulDummy;
/* Increment the tick count - which may wake some tasks but as the /* Increment the tick count - which may wake some tasks but as the
preemptive scheduler is not being used any woken task is not given * preemptive scheduler is not being used any woken task is not given
processor time no matter what its priority. */ * processor time no matter what its priority. */
xTaskIncrementTick(); xTaskIncrementTick();
/* Clear the PIT interrupt. */ /* Clear the PIT interrupt. */
@ -124,11 +124,11 @@ void vPortYieldProcessor( void )
AT91C_BASE_AIC->AIC_EOICR = ulDummy; AT91C_BASE_AIC->AIC_EOICR = ulDummy;
} }
#else #else /* if configUSE_PREEMPTION == 0 */
/* The preemptive scheduler is defined as "naked" as the full context is /* The preemptive scheduler is defined as "naked" as the full context is
saved on entry as part of the context switch. */ * saved on entry as part of the context switch. */
void vPreemptiveTick( void ) __attribute__((naked)); void vPreemptiveTick( void ) __attribute__( ( naked ) );
void vPreemptiveTick( void ) void vPreemptiveTick( void )
{ {
/* Save the context of the current task. */ /* Save the context of the current task. */
@ -147,7 +147,7 @@ void vPortYieldProcessor( void )
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
#endif #endif /* if configUSE_PREEMPTION == 0 */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
@ -156,49 +156,49 @@ void vPortYieldProcessor( void )
* ensure a switch to ARM mode. When THUMB_INTERWORK is not defined then * ensure a switch to ARM mode. When THUMB_INTERWORK is not defined then
* the utilities are defined as macros in portmacro.h - as per other ports. * the utilities are defined as macros in portmacro.h - as per other ports.
*/ */
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked)); void vPortDisableInterruptsFromThumb( void ) __attribute__( ( naked ) );
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked)); void vPortEnableInterruptsFromThumb( void ) __attribute__( ( naked ) );
void vPortDisableInterruptsFromThumb( void ) void vPortDisableInterruptsFromThumb( void )
{ {
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t"/* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t"/* Get CPSR. */
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "ORR R0, R0, #0xC0 \n\t"/* Disable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t"/* Write back modified value. */
"LDMIA SP!, {R0} \n\t" /* Pop R0. */ "LDMIA SP!, {R0} \n\t"/* Pop R0. */
"BX R14" ); /* Return back to thumb. */ "BX R14"); /* Return back to thumb. */
} }
void vPortEnableInterruptsFromThumb( void ) void vPortEnableInterruptsFromThumb( void )
{ {
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t"/* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t"/* Get CPSR. */
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ "BIC R0, R0, #0xC0 \n\t"/* Enable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t"/* Write back modified value. */
"LDMIA SP!, {R0} \n\t" /* Pop R0. */ "LDMIA SP!, {R0} \n\t"/* Pop R0. */
"BX R14" ); /* Return back to thumb. */ "BX R14"); /* Return back to thumb. */
} }
/* The code generated by the GCC compiler uses the stack in different ways at /* The code generated by the GCC compiler uses the stack in different ways at
different optimisation levels. The interrupt flags can therefore not always * different optimisation levels. The interrupt flags can therefore not always
be saved to the stack. Instead the critical section nesting level is stored * be saved to the stack. Instead the critical section nesting level is stored
in a variable, which is then saved as part of the stack context. */ * in a variable, which is then saved as part of the stack context. */
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */ /* Disable interrupts as per portDISABLE_INTERRUPTS(); */
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t"/* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t"/* Get CPSR. */
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "ORR R0, R0, #0xC0 \n\t"/* Disable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t"/* Write back modified value. */
"LDMIA SP!, {R0}" ); /* Pop R0. */ "LDMIA SP!, {R0}"); /* Pop R0. */
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
directly. Increment ulCriticalNesting to keep a count of how many times * directly. Increment ulCriticalNesting to keep a count of how many times
portENTER_CRITICAL() has been called. */ * portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
} }
@ -210,17 +210,16 @@ void vPortExitCritical( void )
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be /* If the nesting level has reached zero then interrupts should be
re-enabled. */ * re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Enable interrupts as per portEXIT_CRITICAL(). */ /* Enable interrupts as per portEXIT_CRITICAL(). */
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t"/* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t"/* Get CPSR. */
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ "BIC R0, R0, #0xC0 \n\t"/* Enable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t"/* Write back modified value. */
"LDMIA SP!, {R0}" ); /* Pop R0. */ "LDMIA SP!, {R0}"); /* Pop R0. */
} }
} }
} }

View file

@ -25,34 +25,34 @@
*/ */
/* /*
Changes from V3.2.3 * Changes from V3.2.3
*
+ Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1. + Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1.
+
Changes from V3.2.4 + Changes from V3.2.4
+
+ Removed the use of the %0 parameter within the assembler macros and + Removed the use of the %0 parameter within the assembler macros and
replaced them with hard coded registers. This will ensure the + replaced them with hard coded registers. This will ensure the
assembler does not select the link register as the temp register as + assembler does not select the link register as the temp register as
was occasionally happening previously. + was occasionally happening previously.
+
+ The assembler statements are now included in a single asm block rather + The assembler statements are now included in a single asm block rather
than each line having its own asm block. + than each line having its own asm block.
+
Changes from V4.5.0 + Changes from V4.5.0
+
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros + Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
and replaced them with portYIELD_FROM_ISR() macro. Application code + and replaced them with portYIELD_FROM_ISR() macro. Application code
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT() + should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
macros as per the V4.5.1 demo code. + macros as per the V4.5.1 demo code.
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -65,32 +65,32 @@ extern "C" {
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE portLONG #define portBASE_TYPE portLONG
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specifics. */ /* Architecture specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portNOP() __asm volatile ( "NOP" ); #define portNOP() __asm volatile ( "NOP" );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -103,92 +103,92 @@ typedef unsigned long UBaseType_t;
* THUMB mode code will result in a compile time error. * THUMB mode code will result in a compile time error.
*/ */
#define portRESTORE_CONTEXT() \ #define portRESTORE_CONTEXT() \
{ \ { \
extern volatile void * volatile pxCurrentTCB; \ extern volatile void * volatile pxCurrentTCB; \
extern volatile uint32_t ulCriticalNesting; \ extern volatile uint32_t ulCriticalNesting; \
\ \
/* Set the LR to the task stack. */ \ /* Set the LR to the task stack. */ \
__asm volatile ( \ __asm volatile ( \
"LDR R0, =pxCurrentTCB \n\t" \ "LDR R0, =pxCurrentTCB \n\t"\
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t"\
"LDR LR, [R0] \n\t" \ "LDR LR, [R0] \n\t"\
\ \
/* The critical nesting depth is the first item on the stack. */ \ /* The critical nesting depth is the first item on the stack. */ \
/* Load it into the ulCriticalNesting variable. */ \ /* Load it into the ulCriticalNesting variable. */ \
"LDR R0, =ulCriticalNesting \n\t" \ "LDR R0, =ulCriticalNesting \n\t"\
"LDMFD LR!, {R1} \n\t" \ "LDMFD LR!, {R1} \n\t"\
"STR R1, [R0] \n\t" \ "STR R1, [R0] \n\t"\
\ \
/* Get the SPSR from the stack. */ \ /* Get the SPSR from the stack. */ \
"LDMFD LR!, {R0} \n\t" \ "LDMFD LR!, {R0} \n\t"\
"MSR SPSR, R0 \n\t" \ "MSR SPSR, R0 \n\t"\
\ \
/* Restore all system mode registers for the task. */ \ /* Restore all system mode registers for the task. */ \
"LDMFD LR, {R0-R14}^ \n\t" \ "LDMFD LR, {R0-R14}^ \n\t"\
"NOP \n\t" \ "NOP \n\t"\
\ \
/* Restore the return address. */ \ /* Restore the return address. */ \
"LDR LR, [LR, #+60] \n\t" \ "LDR LR, [LR, #+60] \n\t"\
\ \
/* And return - correcting the offset in the LR to obtain the */ \ /* And return - correcting the offset in the LR to obtain the */ \
/* correct address. */ \ /* correct address. */ \
"SUBS PC, LR, #4 \n\t" \ "SUBS PC, LR, #4 \n\t"\
); \ ); \
( void ) ulCriticalNesting; \ ( void ) ulCriticalNesting; \
( void ) pxCurrentTCB; \ ( void ) pxCurrentTCB; \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portSAVE_CONTEXT() \ #define portSAVE_CONTEXT() \
{ \ { \
extern volatile void * volatile pxCurrentTCB; \ extern volatile void * volatile pxCurrentTCB; \
extern volatile uint32_t ulCriticalNesting; \ extern volatile uint32_t ulCriticalNesting; \
\ \
/* Push R0 as we are going to use the register. */ \ /* Push R0 as we are going to use the register. */ \
__asm volatile ( \ __asm volatile ( \
"STMDB SP!, {R0} \n\t" \ "STMDB SP!, {R0} \n\t"\
\ \
/* Set R0 to point to the task stack pointer. */ \ /* Set R0 to point to the task stack pointer. */ \
"STMDB SP,{SP}^ \n\t" \ "STMDB SP,{SP}^ \n\t"\
"NOP \n\t" \ "NOP \n\t"\
"SUB SP, SP, #4 \n\t" \ "SUB SP, SP, #4 \n\t"\
"LDMIA SP!,{R0} \n\t" \ "LDMIA SP!,{R0} \n\t"\
\ \
/* Push the return address onto the stack. */ \ /* Push the return address onto the stack. */ \
"STMDB R0!, {LR} \n\t" \ "STMDB R0!, {LR} \n\t"\
\ \
/* Now we have saved LR we can use it instead of R0. */ \ /* Now we have saved LR we can use it instead of R0. */ \
"MOV LR, R0 \n\t" \ "MOV LR, R0 \n\t"\
\ \
/* Pop R0 so we can save it onto the system mode stack. */ \ /* Pop R0 so we can save it onto the system mode stack. */ \
"LDMIA SP!, {R0} \n\t" \ "LDMIA SP!, {R0} \n\t"\
\ \
/* Push all the system mode registers onto the task stack. */ \ /* Push all the system mode registers onto the task stack. */ \
"STMDB LR,{R0-LR}^ \n\t" \ "STMDB LR,{R0-LR}^ \n\t"\
"NOP \n\t" \ "NOP \n\t"\
"SUB LR, LR, #60 \n\t" \ "SUB LR, LR, #60 \n\t"\
\ \
/* Push the SPSR onto the task stack. */ \ /* Push the SPSR onto the task stack. */ \
"MRS R0, SPSR \n\t" \ "MRS R0, SPSR \n\t"\
"STMDB LR!, {R0} \n\t" \ "STMDB LR!, {R0} \n\t"\
\ \
"LDR R0, =ulCriticalNesting \n\t" \ "LDR R0, =ulCriticalNesting \n\t"\
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t"\
"STMDB LR!, {R0} \n\t" \ "STMDB LR!, {R0} \n\t"\
\ \
/* Store the new top of stack for the task. */ \ /* Store the new top of stack for the task. */ \
"LDR R0, =pxCurrentTCB \n\t" \ "LDR R0, =pxCurrentTCB \n\t"\
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t"\
"STR LR, [R0] \n\t" \ "STR LR, [R0] \n\t"\
); \ ); \
( void ) ulCriticalNesting; \ ( void ) ulCriticalNesting; \
( void ) pxCurrentTCB; \ ( void ) pxCurrentTCB; \
} }
#define portYIELD_FROM_ISR() vTaskSwitchContext() #define portYIELD_FROM_ISR() vTaskSwitchContext()
#define portYIELD() __asm volatile ( "SWI 0" ) #define portYIELD() __asm volatile ( "SWI 0" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -201,48 +201,47 @@ extern volatile uint32_t ulCriticalNesting; \
* defined then the utilities are defined as macros here - as per other ports. * defined then the utilities are defined as macros here - as per other ports.
*/ */
#ifdef THUMB_INTERWORK #ifdef THUMB_INTERWORK
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked)); extern void vPortDisableInterruptsFromThumb( void ) __attribute__( ( naked ) );
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked)); extern void vPortEnableInterruptsFromThumb( void ) __attribute__( ( naked ) );
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb() #define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb() #define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
#else #else
#define portDISABLE_INTERRUPTS() \ #define portDISABLE_INTERRUPTS() \
__asm volatile ( \ __asm volatile ( \
"STMDB SP!, {R0} \n\t" /* Push R0. */ \ "STMDB SP!, {R0} \n\t" /* Push R0. */\
"MRS R0, CPSR \n\t" /* Get CPSR. */ \ "MRS R0, CPSR \n\t" /* Get CPSR. */\
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \ "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */\
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \ "MSR CPSR, R0 \n\t" /* Write back modified value. */\
"LDMIA SP!, {R0} " ) /* Pop R0. */ "LDMIA SP!, {R0} ") /* Pop R0. */
#define portENABLE_INTERRUPTS() \ #define portENABLE_INTERRUPTS() \
__asm volatile ( \ __asm volatile ( \
"STMDB SP!, {R0} \n\t" /* Push R0. */ \ "STMDB SP!, {R0} \n\t" /* Push R0. */\
"MRS R0, CPSR \n\t" /* Get CPSR. */ \ "MRS R0, CPSR \n\t" /* Get CPSR. */\
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \ "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */\
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \ "MSR CPSR, R0 \n\t" /* Write back modified value. */\
"LDMIA SP!, {R0} " ) /* Pop R0. */ "LDMIA SP!, {R0} ") /* Pop R0. */
#endif /* THUMB_INTERWORK */ #endif /* THUMB_INTERWORK */
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical(); #define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical(); #define portEXIT_CRITICAL() vPortExitCritical();
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -26,12 +26,12 @@
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM7 port. * Implementation of functions defined in portable.h for the ARM7 port.
* *
* Components that can be compiled to either ARM or THUMB mode are * Components that can be compiled to either ARM or THUMB mode are
* contained in this file. The ISR routines, which can only be compiled * contained in this file. The ISR routines, which can only be compiled
* to ARM mode are contained in portISR.c. * to ARM mode are contained in portISR.c.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Standard includes. */ /* Standard includes. */
@ -77,22 +77,24 @@ extern void vPortISRStartFirstTask( void );
* *
* See header file for description. * See header file for description.
*/ */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{ {
StackType_t *pxOriginalTOS; StackType_t * pxOriginalTOS;
pxOriginalTOS = pxTopOfStack; pxOriginalTOS = pxTopOfStack;
/* To ensure asserts in tasks.c don't fail, although in this case the assert /* To ensure asserts in tasks.c don't fail, although in this case the assert
is not really required. */ * is not really required. */
pxTopOfStack--; pxTopOfStack--;
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. */ * expected by the portRESTORE_CONTEXT() macro. */
/* First on the stack is the return address - which in this case is the /* First on the stack is the return address - which in this case is the
start of the task. The offset is added to make the return address appear * start of the task. The offset is added to make the return address appear
as it would within an IRQ ISR. */ * as it would within an IRQ ISR. */
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; *pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
pxTopOfStack--; pxTopOfStack--;
@ -126,12 +128,12 @@ StackType_t *pxOriginalTOS;
pxTopOfStack--; pxTopOfStack--;
/* When the task starts is will expect to find the function parameter in /* When the task starts is will expect to find the function parameter in
R0. */ * R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
/* The last thing onto the stack is the status register, which is set for /* The last thing onto the stack is the status register, which is set for
system mode, with interrupts enabled. */ * system mode, with interrupts enabled. */
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR; *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 ) if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 )
@ -143,9 +145,9 @@ StackType_t *pxOriginalTOS;
pxTopOfStack--; pxTopOfStack--;
/* Some optimisation levels use the stack differently to others. This /* Some optimisation levels use the stack differently to others. This
means the interrupt flags cannot always be stored on the stack and will * means the interrupt flags cannot always be stored on the stack and will
instead be stored in a variable, which is then saved as part of the * instead be stored in a variable, which is then saved as part of the
tasks context. */ * tasks context. */
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING; *pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
return pxTopOfStack; return pxTopOfStack;
@ -155,7 +157,7 @@ StackType_t *pxOriginalTOS;
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ * here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Start the first task. */ /* Start the first task. */
@ -169,7 +171,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the ARM port will require this function as there /* It is unlikely that the ARM port will require this function as there
is nothing to return to. */ * is nothing to return to. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -178,18 +180,19 @@ void vPortEndScheduler( void )
*/ */
static void prvSetupTimerInterrupt( void ) static void prvSetupTimerInterrupt( void )
{ {
uint32_t ulCompareMatch; uint32_t ulCompareMatch;
extern void ( vTickISR )( void );
extern void( vTickISR )( void );
/* A 1ms tick does not require the use of the timer prescale. This is /* A 1ms tick does not require the use of the timer prescale. This is
defaulted to zero but can be used if necessary. */ * defaulted to zero but can be used if necessary. */
T0_PR = portPRESCALE_VALUE; T0_PR = portPRESCALE_VALUE;
/* Calculate the match value required for our wanted tick rate. */ /* Calculate the match value required for our wanted tick rate. */
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ; ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
/* Protect against divide by zero. Using an if() statement still results /* Protect against divide by zero. Using an if() statement still results
in a warning - hence the #if. */ * in a warning - hence the #if. */
#if portPRESCALE_VALUE != 0 #if portPRESCALE_VALUE != 0
{ {
ulCompareMatch /= ( portPRESCALE_VALUE + 1 ); ulCompareMatch /= ( portPRESCALE_VALUE + 1 );
@ -205,16 +208,13 @@ extern void ( vTickISR )( void );
VICIntEnable |= portTIMER_VIC_CHANNEL_BIT; VICIntEnable |= portTIMER_VIC_CHANNEL_BIT;
/* The ISR installed depends on whether the preemptive or cooperative /* The ISR installed depends on whether the preemptive or cooperative
scheduler is being used. */ * scheduler is being used. */
VICVectAddr0 = ( int32_t ) vTickISR; VICVectAddr0 = ( int32_t ) vTickISR;
VICVectCntl0 = portTIMER_VIC_CHANNEL | portTIMER_VIC_ENABLE; VICVectCntl0 = portTIMER_VIC_CHANNEL | portTIMER_VIC_ENABLE;
/* Start the timer - interrupts are disabled when this function is called /* Start the timer - interrupts are disabled when this function is called
so it is okay to do this here. */ * so it is okay to do this here. */
T0_TCR = portENABLE_TIMER; T0_TCR = portENABLE_TIMER;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -26,28 +26,28 @@
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Components that can be compiled to either ARM or THUMB mode are * Components that can be compiled to either ARM or THUMB mode are
* contained in port.c The ISR routines, which can only be compiled * contained in port.c The ISR routines, which can only be compiled
* to ARM mode, are contained in this file. * to ARM mode, are contained in this file.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* /*
Changes from V2.5.2 * Changes from V2.5.2
*
+ The critical section management functions have been changed. These no + The critical section management functions have been changed. These no
longer modify the stack and are safe to use at all optimisation levels. + longer modify the stack and are safe to use at all optimisation levels.
The functions are now also the same for both ARM and THUMB modes. + The functions are now also the same for both ARM and THUMB modes.
+
Changes from V2.6.0 + Changes from V2.6.0
+
+ Removed the 'static' from the definition of vNonPreemptiveTick() to + Removed the 'static' from the definition of vNonPreemptiveTick() to
allow the demo to link when using the cooperative scheduler. + allow the demo to link when using the cooperative scheduler.
+
Changes from V3.2.4 + Changes from V3.2.4
+
+ The assembler statements are now included in a single asm block rather + The assembler statements are now included in a single asm block rather
than each line having its own asm block. + than each line having its own asm block.
*/ */
/* Scheduler includes. */ /* Scheduler includes. */
@ -64,7 +64,7 @@ volatile uint32_t ulCriticalNesting = 9999UL;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* ISR to handle manual context switches (from a call to taskYIELD()). */ /* ISR to handle manual context switches (from a call to taskYIELD()). */
void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked)); void vPortYieldProcessor( void ) __attribute__( ( interrupt( "SWI" ), naked ) );
/* /*
* The scheduler can only be started from ARM mode, hence the inclusion of this * The scheduler can only be started from ARM mode, hence the inclusion of this
@ -76,7 +76,7 @@ void vPortISRStartFirstTask( void );
void vPortISRStartFirstTask( void ) void vPortISRStartFirstTask( void )
{ {
/* Simply start the scheduler. This is included here as it can only be /* Simply start the scheduler. This is included here as it can only be
called from ARM mode. */ * called from ARM mode. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -92,9 +92,9 @@ void vPortISRStartFirstTask( void )
void vPortYieldProcessor( void ) void vPortYieldProcessor( void )
{ {
/* Within an IRQ ISR the link register has an offset from the true return /* Within an IRQ ISR the link register has an offset from the true return
address, but an SWI ISR does not. Add the offset manually so the same * address, but an SWI ISR does not. Add the offset manually so the same
ISR return code can be used in both cases. */ * ISR return code can be used in both cases. */
__asm volatile ( "ADD LR, LR, #4" ); __asm volatile ( "ADD LR, LR, #4");
/* Perform the context switch. First save the context of the current task. */ /* Perform the context switch. First save the context of the current task. */
portSAVE_CONTEXT(); portSAVE_CONTEXT();
@ -110,20 +110,20 @@ void vPortYieldProcessor( void )
/* /*
* The ISR used for the scheduler tick. * The ISR used for the scheduler tick.
*/ */
void vTickISR( void ) __attribute__((naked)); void vTickISR( void ) __attribute__( ( naked ) );
void vTickISR( void ) void vTickISR( void )
{ {
/* Save the context of the interrupted task. */ /* Save the context of the interrupted task. */
portSAVE_CONTEXT(); portSAVE_CONTEXT();
/* Increment the RTOS tick count, then look for the highest priority /* Increment the RTOS tick count, then look for the highest priority
task that is ready to run. */ * task that is ready to run. */
__asm volatile __asm volatile
( (
" bl xTaskIncrementTick \t\n" \ " bl xTaskIncrementTick \t\n"\
" cmp r0, #0 \t\n" \ " cmp r0, #0 \t\n"\
" beq SkipContextSwitch \t\n" \ " beq SkipContextSwitch \t\n"\
" bl vTaskSwitchContext \t\n" \ " bl vTaskSwitchContext \t\n"\
"SkipContextSwitch: \t\n" "SkipContextSwitch: \t\n"
); );
@ -144,50 +144,50 @@ void vTickISR( void )
*/ */
#ifdef THUMB_INTERWORK #ifdef THUMB_INTERWORK
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked)); void vPortDisableInterruptsFromThumb( void ) __attribute__( ( naked ) );
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked)); void vPortEnableInterruptsFromThumb( void ) __attribute__( ( naked ) );
void vPortDisableInterruptsFromThumb( void ) void vPortDisableInterruptsFromThumb( void )
{ {
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t"/* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t"/* Get CPSR. */
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "ORR R0, R0, #0xC0 \n\t"/* Disable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t"/* Write back modified value. */
"LDMIA SP!, {R0} \n\t" /* Pop R0. */ "LDMIA SP!, {R0} \n\t"/* Pop R0. */
"BX R14" ); /* Return back to thumb. */ "BX R14"); /* Return back to thumb. */
} }
void vPortEnableInterruptsFromThumb( void ) void vPortEnableInterruptsFromThumb( void )
{ {
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t"/* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t"/* Get CPSR. */
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ "BIC R0, R0, #0xC0 \n\t"/* Enable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t"/* Write back modified value. */
"LDMIA SP!, {R0} \n\t" /* Pop R0. */ "LDMIA SP!, {R0} \n\t"/* Pop R0. */
"BX R14" ); /* Return back to thumb. */ "BX R14"); /* Return back to thumb. */
} }
#endif /* THUMB_INTERWORK */ #endif /* THUMB_INTERWORK */
/* The code generated by the GCC compiler uses the stack in different ways at /* The code generated by the GCC compiler uses the stack in different ways at
different optimisation levels. The interrupt flags can therefore not always * different optimisation levels. The interrupt flags can therefore not always
be saved to the stack. Instead the critical section nesting level is stored * be saved to the stack. Instead the critical section nesting level is stored
in a variable, which is then saved as part of the stack context. */ * in a variable, which is then saved as part of the stack context. */
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */ /* Disable interrupts as per portDISABLE_INTERRUPTS(); */
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t"/* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t"/* Get CPSR. */
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "ORR R0, R0, #0xC0 \n\t"/* Disable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t"/* Write back modified value. */
"LDMIA SP!, {R0}" ); /* Pop R0. */ "LDMIA SP!, {R0}"); /* Pop R0. */
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
directly. Increment ulCriticalNesting to keep a count of how many times * directly. Increment ulCriticalNesting to keep a count of how many times
portENTER_CRITICAL() has been called. */ * portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
} }
@ -199,16 +199,16 @@ void vPortExitCritical( void )
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be /* If the nesting level has reached zero then interrupts should be
re-enabled. */ * re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Enable interrupts as per portEXIT_CRITICAL(). */ /* Enable interrupts as per portEXIT_CRITICAL(). */
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t"/* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t"/* Get CPSR. */
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ "BIC R0, R0, #0xC0 \n\t"/* Enable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t"/* Write back modified value. */
"LDMIA SP!, {R0}" ); /* Pop R0. */ "LDMIA SP!, {R0}"); /* Pop R0. */
} }
} }
} }

View file

@ -25,11 +25,11 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -42,32 +42,32 @@ extern "C" {
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE portLONG #define portBASE_TYPE portLONG
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specifics. */ /* Architecture specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portNOP() __asm volatile ( "NOP" ); #define portNOP() __asm volatile ( "NOP" );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -80,92 +80,92 @@ typedef unsigned long UBaseType_t;
* THUMB mode code will result in a compile time error. * THUMB mode code will result in a compile time error.
*/ */
#define portRESTORE_CONTEXT() \ #define portRESTORE_CONTEXT() \
{ \ { \
extern volatile void * volatile pxCurrentTCB; \ extern volatile void * volatile pxCurrentTCB; \
extern volatile uint32_t ulCriticalNesting; \ extern volatile uint32_t ulCriticalNesting; \
\ \
/* Set the LR to the task stack. */ \ /* Set the LR to the task stack. */ \
__asm volatile ( \ __asm volatile ( \
"LDR R0, =pxCurrentTCB \n\t" \ "LDR R0, =pxCurrentTCB \n\t"\
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t"\
"LDR LR, [R0] \n\t" \ "LDR LR, [R0] \n\t"\
\ \
/* The critical nesting depth is the first item on the stack. */ \ /* The critical nesting depth is the first item on the stack. */ \
/* Load it into the ulCriticalNesting variable. */ \ /* Load it into the ulCriticalNesting variable. */ \
"LDR R0, =ulCriticalNesting \n\t" \ "LDR R0, =ulCriticalNesting \n\t"\
"LDMFD LR!, {R1} \n\t" \ "LDMFD LR!, {R1} \n\t"\
"STR R1, [R0] \n\t" \ "STR R1, [R0] \n\t"\
\ \
/* Get the SPSR from the stack. */ \ /* Get the SPSR from the stack. */ \
"LDMFD LR!, {R0} \n\t" \ "LDMFD LR!, {R0} \n\t"\
"MSR SPSR, R0 \n\t" \ "MSR SPSR, R0 \n\t"\
\ \
/* Restore all system mode registers for the task. */ \ /* Restore all system mode registers for the task. */ \
"LDMFD LR, {R0-R14}^ \n\t" \ "LDMFD LR, {R0-R14}^ \n\t"\
"NOP \n\t" \ "NOP \n\t"\
\ \
/* Restore the return address. */ \ /* Restore the return address. */ \
"LDR LR, [LR, #+60] \n\t" \ "LDR LR, [LR, #+60] \n\t"\
\ \
/* And return - correcting the offset in the LR to obtain the */ \ /* And return - correcting the offset in the LR to obtain the */ \
/* correct address. */ \ /* correct address. */ \
"SUBS PC, LR, #4 \n\t" \ "SUBS PC, LR, #4 \n\t"\
); \ ); \
( void ) ulCriticalNesting; \ ( void ) ulCriticalNesting; \
( void ) pxCurrentTCB; \ ( void ) pxCurrentTCB; \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portSAVE_CONTEXT() \ #define portSAVE_CONTEXT() \
{ \ { \
extern volatile void * volatile pxCurrentTCB; \ extern volatile void * volatile pxCurrentTCB; \
extern volatile uint32_t ulCriticalNesting; \ extern volatile uint32_t ulCriticalNesting; \
\ \
/* Push R0 as we are going to use the register. */ \ /* Push R0 as we are going to use the register. */ \
__asm volatile ( \ __asm volatile ( \
"STMDB SP!, {R0} \n\t" \ "STMDB SP!, {R0} \n\t"\
\ \
/* Set R0 to point to the task stack pointer. */ \ /* Set R0 to point to the task stack pointer. */ \
"STMDB SP,{SP}^ \n\t" \ "STMDB SP,{SP}^ \n\t"\
"NOP \n\t" \ "NOP \n\t"\
"SUB SP, SP, #4 \n\t" \ "SUB SP, SP, #4 \n\t"\
"LDMIA SP!,{R0} \n\t" \ "LDMIA SP!,{R0} \n\t"\
\ \
/* Push the return address onto the stack. */ \ /* Push the return address onto the stack. */ \
"STMDB R0!, {LR} \n\t" \ "STMDB R0!, {LR} \n\t"\
\ \
/* Now we have saved LR we can use it instead of R0. */ \ /* Now we have saved LR we can use it instead of R0. */ \
"MOV LR, R0 \n\t" \ "MOV LR, R0 \n\t"\
\ \
/* Pop R0 so we can save it onto the system mode stack. */ \ /* Pop R0 so we can save it onto the system mode stack. */ \
"LDMIA SP!, {R0} \n\t" \ "LDMIA SP!, {R0} \n\t"\
\ \
/* Push all the system mode registers onto the task stack. */ \ /* Push all the system mode registers onto the task stack. */ \
"STMDB LR,{R0-LR}^ \n\t" \ "STMDB LR,{R0-LR}^ \n\t"\
"NOP \n\t" \ "NOP \n\t"\
"SUB LR, LR, #60 \n\t" \ "SUB LR, LR, #60 \n\t"\
\ \
/* Push the SPSR onto the task stack. */ \ /* Push the SPSR onto the task stack. */ \
"MRS R0, SPSR \n\t" \ "MRS R0, SPSR \n\t"\
"STMDB LR!, {R0} \n\t" \ "STMDB LR!, {R0} \n\t"\
\ \
"LDR R0, =ulCriticalNesting \n\t" \ "LDR R0, =ulCriticalNesting \n\t"\
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t"\
"STMDB LR!, {R0} \n\t" \ "STMDB LR!, {R0} \n\t"\
\ \
/* Store the new top of stack for the task. */ \ /* Store the new top of stack for the task. */ \
"LDR R0, =pxCurrentTCB \n\t" \ "LDR R0, =pxCurrentTCB \n\t"\
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t"\
"STR LR, [R0] \n\t" \ "STR LR, [R0] \n\t"\
); \ ); \
( void ) ulCriticalNesting; \ ( void ) ulCriticalNesting; \
( void ) pxCurrentTCB; \ ( void ) pxCurrentTCB; \
} }
extern void vTaskSwitchContext( void ); extern void vTaskSwitchContext( void );
#define portYIELD_FROM_ISR() vTaskSwitchContext() #define portYIELD_FROM_ISR() vTaskSwitchContext()
#define portYIELD() __asm volatile ( "SWI 0" ) #define portYIELD() __asm volatile ( "SWI 0" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -178,48 +178,47 @@ extern void vTaskSwitchContext( void );
* defined then the utilities are defined as macros here - as per other ports. * defined then the utilities are defined as macros here - as per other ports.
*/ */
#ifdef THUMB_INTERWORK #ifdef THUMB_INTERWORK
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked)); extern void vPortDisableInterruptsFromThumb( void ) __attribute__( ( naked ) );
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked)); extern void vPortEnableInterruptsFromThumb( void ) __attribute__( ( naked ) );
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb() #define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb() #define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
#else #else
#define portDISABLE_INTERRUPTS() \ #define portDISABLE_INTERRUPTS() \
__asm volatile ( \ __asm volatile ( \
"STMDB SP!, {R0} \n\t" /* Push R0. */ \ "STMDB SP!, {R0} \n\t" /* Push R0. */\
"MRS R0, CPSR \n\t" /* Get CPSR. */ \ "MRS R0, CPSR \n\t" /* Get CPSR. */\
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \ "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */\
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \ "MSR CPSR, R0 \n\t" /* Write back modified value. */\
"LDMIA SP!, {R0} " ) /* Pop R0. */ "LDMIA SP!, {R0} ") /* Pop R0. */
#define portENABLE_INTERRUPTS() \ #define portENABLE_INTERRUPTS() \
__asm volatile ( \ __asm volatile ( \
"STMDB SP!, {R0} \n\t" /* Push R0. */ \ "STMDB SP!, {R0} \n\t" /* Push R0. */\
"MRS R0, CPSR \n\t" /* Get CPSR. */ \ "MRS R0, CPSR \n\t" /* Get CPSR. */\
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \ "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */\
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \ "MSR CPSR, R0 \n\t" /* Write back modified value. */\
"LDMIA SP!, {R0} " ) /* Pop R0. */ "LDMIA SP!, {R0} ") /* Pop R0. */
#endif /* THUMB_INTERWORK */ #endif /* THUMB_INTERWORK */
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical(); #define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical(); #define portEXIT_CRITICAL() vPortExitCritical();
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -26,12 +26,12 @@
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM7 port. * Implementation of functions defined in portable.h for the ARM7 port.
* *
* Components that can be compiled to either ARM or THUMB mode are * Components that can be compiled to either ARM or THUMB mode are
* contained in this file. The ISR routines, which can only be compiled * contained in this file. The ISR routines, which can only be compiled
* to ARM mode are contained in portISR.c. * to ARM mode are contained in portISR.c.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Standard includes. */ /* Standard includes. */
@ -77,22 +77,24 @@ extern void vPortISRStartFirstTask( void );
* *
* See header file for description. * See header file for description.
*/ */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{ {
StackType_t *pxOriginalTOS; StackType_t * pxOriginalTOS;
pxOriginalTOS = pxTopOfStack; pxOriginalTOS = pxTopOfStack;
/* To ensure asserts in tasks.c don't fail, although in this case the assert /* To ensure asserts in tasks.c don't fail, although in this case the assert
is not really required. */ * is not really required. */
pxTopOfStack--; pxTopOfStack--;
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. */ * expected by the portRESTORE_CONTEXT() macro. */
/* First on the stack is the return address - which in this case is the /* First on the stack is the return address - which in this case is the
start of the task. The offset is added to make the return address appear * start of the task. The offset is added to make the return address appear
as it would within an IRQ ISR. */ * as it would within an IRQ ISR. */
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; *pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
pxTopOfStack--; pxTopOfStack--;
@ -126,12 +128,12 @@ StackType_t *pxOriginalTOS;
pxTopOfStack--; pxTopOfStack--;
/* When the task starts is will expect to find the function parameter in /* When the task starts is will expect to find the function parameter in
R0. */ * R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
/* The last thing onto the stack is the status register, which is set for /* The last thing onto the stack is the status register, which is set for
system mode, with interrupts enabled. */ * system mode, with interrupts enabled. */
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR; *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 ) if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 )
@ -143,9 +145,9 @@ StackType_t *pxOriginalTOS;
pxTopOfStack--; pxTopOfStack--;
/* Some optimisation levels use the stack differently to others. This /* Some optimisation levels use the stack differently to others. This
means the interrupt flags cannot always be stored on the stack and will * means the interrupt flags cannot always be stored on the stack and will
instead be stored in a variable, which is then saved as part of the * instead be stored in a variable, which is then saved as part of the
tasks context. */ * tasks context. */
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING; *pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
return pxTopOfStack; return pxTopOfStack;
@ -155,7 +157,7 @@ StackType_t *pxOriginalTOS;
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ * here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Start the first task. */ /* Start the first task. */
@ -169,7 +171,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the ARM port will require this function as there /* It is unlikely that the ARM port will require this function as there
is nothing to return to. */ * is nothing to return to. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -178,21 +180,21 @@ void vPortEndScheduler( void )
*/ */
static void prvSetupTimerInterrupt( void ) static void prvSetupTimerInterrupt( void )
{ {
uint32_t ulCompareMatch; uint32_t ulCompareMatch;
PCLKSEL0 = (PCLKSEL0 & (~(0x3<<2))) | (0x01 << 2); PCLKSEL0 = ( PCLKSEL0 & ( ~( 0x3 << 2 ) ) ) | ( 0x01 << 2 );
T0TCR = 2; /* Stop and reset the timer */ T0TCR = 2; /* Stop and reset the timer */
T0CTCR = 0; /* Timer mode */ T0CTCR = 0; /* Timer mode */
/* A 1ms tick does not require the use of the timer prescale. This is /* A 1ms tick does not require the use of the timer prescale. This is
defaulted to zero but can be used if necessary. */ * defaulted to zero but can be used if necessary. */
T0PR = portPRESCALE_VALUE; T0PR = portPRESCALE_VALUE;
/* Calculate the match value required for our wanted tick rate. */ /* Calculate the match value required for our wanted tick rate. */
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ; ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
/* Protect against divide by zero. Using an if() statement still results /* Protect against divide by zero. Using an if() statement still results
in a warning - hence the #if. */ * in a warning - hence the #if. */
#if portPRESCALE_VALUE != 0 #if portPRESCALE_VALUE != 0
{ {
ulCompareMatch /= ( portPRESCALE_VALUE + 1 ); ulCompareMatch /= ( portPRESCALE_VALUE + 1 );
@ -201,21 +203,21 @@ uint32_t ulCompareMatch;
T0MR1 = ulCompareMatch; T0MR1 = ulCompareMatch;
/* Generate tick with timer 0 compare match. */ /* Generate tick with timer 0 compare match. */
T0MCR = (3 << 3); /* Reset timer on match and generate interrupt */ T0MCR = ( 3 << 3 ); /* Reset timer on match and generate interrupt */
/* Setup the VIC for the timer. */ /* Setup the VIC for the timer. */
VICIntEnable = 0x00000010; VICIntEnable = 0x00000010;
/* The ISR installed depends on whether the preemptive or cooperative /* The ISR installed depends on whether the preemptive or cooperative
scheduler is being used. */ * scheduler is being used. */
#if configUSE_PREEMPTION == 1 #if configUSE_PREEMPTION == 1
{ {
extern void ( vPreemptiveTick )( void ); extern void( vPreemptiveTick )( void );
VICVectAddr4 = ( int32_t ) vPreemptiveTick; VICVectAddr4 = ( int32_t ) vPreemptiveTick;
} }
#else #else
{ {
extern void ( vNonPreemptiveTick )( void ); extern void( vNonPreemptiveTick )( void );
VICVectAddr4 = ( int32_t ) vNonPreemptiveTick; VICVectAddr4 = ( int32_t ) vNonPreemptiveTick;
} }
#endif #endif
@ -223,10 +225,7 @@ uint32_t ulCompareMatch;
VICVectCntl4 = 1; VICVectCntl4 = 1;
/* Start the timer - interrupts are disabled when this function is called /* Start the timer - interrupts are disabled when this function is called
so it is okay to do this here. */ * so it is okay to do this here. */
T0TCR = portENABLE_TIMER; T0TCR = portENABLE_TIMER;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -26,10 +26,10 @@
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Components that can be compiled to either ARM or THUMB mode are * Components that can be compiled to either ARM or THUMB mode are
* contained in port.c The ISR routines, which can only be compiled * contained in port.c The ISR routines, which can only be compiled
* to ARM mode, are contained in this file. * to ARM mode, are contained in this file.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Scheduler includes. */ /* Scheduler includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
@ -46,7 +46,7 @@ volatile uint32_t ulCriticalNesting = 9999UL;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* ISR to handle manual context switches (from a call to taskYIELD()). */ /* ISR to handle manual context switches (from a call to taskYIELD()). */
void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked)); void vPortYieldProcessor( void ) __attribute__( ( interrupt( "SWI" ), naked ) );
/* /*
* The scheduler can only be started from ARM mode, hence the inclusion of this * The scheduler can only be started from ARM mode, hence the inclusion of this
@ -58,7 +58,7 @@ void vPortISRStartFirstTask( void );
void vPortISRStartFirstTask( void ) void vPortISRStartFirstTask( void )
{ {
/* Simply start the scheduler. This is included here as it can only be /* Simply start the scheduler. This is included here as it can only be
called from ARM mode. */ * called from ARM mode. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -74,15 +74,15 @@ void vPortISRStartFirstTask( void )
void vPortYieldProcessor( void ) void vPortYieldProcessor( void )
{ {
/* Within an IRQ ISR the link register has an offset from the true return /* Within an IRQ ISR the link register has an offset from the true return
address, but an SWI ISR does not. Add the offset manually so the same * address, but an SWI ISR does not. Add the offset manually so the same
ISR return code can be used in both cases. */ * ISR return code can be used in both cases. */
__asm volatile ( "ADD LR, LR, #4" ); __asm volatile ( "ADD LR, LR, #4");
/* Perform the context switch. First save the context of the current task. */ /* Perform the context switch. First save the context of the current task. */
portSAVE_CONTEXT(); portSAVE_CONTEXT();
/* Find the highest priority task that is ready to run. */ /* Find the highest priority task that is ready to run. */
__asm volatile( "bl vTaskSwitchContext" ); __asm volatile ( "bl vTaskSwitchContext");
/* Restore the context of the new task. */ /* Restore the context of the new task. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
@ -97,9 +97,9 @@ void vPortYieldProcessor( void )
#if configUSE_PREEMPTION == 0 #if configUSE_PREEMPTION == 0
/* The cooperative scheduler requires a normal IRQ service routine to /* The cooperative scheduler requires a normal IRQ service routine to
simply increment the system tick. */ * simply increment the system tick. */
void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ"))); void vNonPreemptiveTick( void ) __attribute__( ( interrupt( "IRQ" ) ) );
void vNonPreemptiveTick( void ) void vNonPreemptiveTick( void )
{ {
xTaskIncrementTick(); xTaskIncrementTick();
@ -107,24 +107,24 @@ void vPortYieldProcessor( void )
VICVectAddr = portCLEAR_VIC_INTERRUPT; VICVectAddr = portCLEAR_VIC_INTERRUPT;
} }
#else #else /* if configUSE_PREEMPTION == 0 */
/* The preemptive scheduler is defined as "naked" as the full context is /* The preemptive scheduler is defined as "naked" as the full context is
saved on entry as part of the context switch. */ * saved on entry as part of the context switch. */
void vPreemptiveTick( void ) __attribute__((naked)); void vPreemptiveTick( void ) __attribute__( ( naked ) );
void vPreemptiveTick( void ) void vPreemptiveTick( void )
{ {
/* Save the context of the interrupted task. */ /* Save the context of the interrupted task. */
portSAVE_CONTEXT(); portSAVE_CONTEXT();
/* Increment the RTOS tick count, then look for the highest priority /* Increment the RTOS tick count, then look for the highest priority
task that is ready to run. */ * task that is ready to run. */
__asm volatile __asm volatile
( (
" bl xTaskIncrementTick \t\n" \ " bl xTaskIncrementTick \t\n"\
" cmp r0, #0 \t\n" \ " cmp r0, #0 \t\n"\
" beq SkipContextSwitch \t\n" \ " beq SkipContextSwitch \t\n"\
" bl vTaskSwitchContext \t\n" \ " bl vTaskSwitchContext \t\n"\
"SkipContextSwitch: \t\n" "SkipContextSwitch: \t\n"
); );
@ -136,7 +136,7 @@ void vPortYieldProcessor( void )
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
#endif #endif /* if configUSE_PREEMPTION == 0 */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
@ -147,50 +147,50 @@ void vPortYieldProcessor( void )
*/ */
#ifdef THUMB_INTERWORK #ifdef THUMB_INTERWORK
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked)); void vPortDisableInterruptsFromThumb( void ) __attribute__( ( naked ) );
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked)); void vPortEnableInterruptsFromThumb( void ) __attribute__( ( naked ) );
void vPortDisableInterruptsFromThumb( void ) void vPortDisableInterruptsFromThumb( void )
{ {
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t"/* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t"/* Get CPSR. */
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "ORR R0, R0, #0xC0 \n\t"/* Disable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t"/* Write back modified value. */
"LDMIA SP!, {R0} \n\t" /* Pop R0. */ "LDMIA SP!, {R0} \n\t"/* Pop R0. */
"BX R14" ); /* Return back to thumb. */ "BX R14"); /* Return back to thumb. */
} }
void vPortEnableInterruptsFromThumb( void ) void vPortEnableInterruptsFromThumb( void )
{ {
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t"/* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t"/* Get CPSR. */
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ "BIC R0, R0, #0xC0 \n\t"/* Enable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t"/* Write back modified value. */
"LDMIA SP!, {R0} \n\t" /* Pop R0. */ "LDMIA SP!, {R0} \n\t"/* Pop R0. */
"BX R14" ); /* Return back to thumb. */ "BX R14"); /* Return back to thumb. */
} }
#endif /* THUMB_INTERWORK */ #endif /* THUMB_INTERWORK */
/* The code generated by the GCC compiler uses the stack in different ways at /* The code generated by the GCC compiler uses the stack in different ways at
different optimisation levels. The interrupt flags can therefore not always * different optimisation levels. The interrupt flags can therefore not always
be saved to the stack. Instead the critical section nesting level is stored * be saved to the stack. Instead the critical section nesting level is stored
in a variable, which is then saved as part of the stack context. */ * in a variable, which is then saved as part of the stack context. */
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */ /* Disable interrupts as per portDISABLE_INTERRUPTS(); */
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t"/* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t"/* Get CPSR. */
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "ORR R0, R0, #0xC0 \n\t"/* Disable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t"/* Write back modified value. */
"LDMIA SP!, {R0}" ); /* Pop R0. */ "LDMIA SP!, {R0}"); /* Pop R0. */
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
directly. Increment ulCriticalNesting to keep a count of how many times * directly. Increment ulCriticalNesting to keep a count of how many times
portENTER_CRITICAL() has been called. */ * portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
} }
@ -202,16 +202,16 @@ void vPortExitCritical( void )
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be /* If the nesting level has reached zero then interrupts should be
re-enabled. */ * re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Enable interrupts as per portEXIT_CRITICAL(). */ /* Enable interrupts as per portEXIT_CRITICAL(). */
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t"/* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t"/* Get CPSR. */
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ "BIC R0, R0, #0xC0 \n\t"/* Enable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t"/* Write back modified value. */
"LDMIA SP!, {R0}" ); /* Pop R0. */ "LDMIA SP!, {R0}"); /* Pop R0. */
} }
} }
} }

View file

@ -25,34 +25,34 @@
*/ */
/* /*
Changes from V3.2.3 * Changes from V3.2.3
*
+ Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1. + Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1.
+
Changes from V3.2.4 + Changes from V3.2.4
+
+ Removed the use of the %0 parameter within the assembler macros and + Removed the use of the %0 parameter within the assembler macros and
replaced them with hard coded registers. This will ensure the + replaced them with hard coded registers. This will ensure the
assembler does not select the link register as the temp register as + assembler does not select the link register as the temp register as
was occasionally happening previously. + was occasionally happening previously.
+
+ The assembler statements are now included in a single asm block rather + The assembler statements are now included in a single asm block rather
than each line having its own asm block. + than each line having its own asm block.
+
Changes from V4.5.0 + Changes from V4.5.0
+
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros + Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
and replaced them with portYIELD_FROM_ISR() macro. Application code + and replaced them with portYIELD_FROM_ISR() macro. Application code
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT() + should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
macros as per the V4.5.1 demo code. + macros as per the V4.5.1 demo code.
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -65,32 +65,32 @@ extern "C" {
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE portLONG #define portBASE_TYPE portLONG
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specifics. */ /* Architecture specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portNOP() __asm volatile ( "NOP" ); #define portNOP() __asm volatile ( "NOP" );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -103,92 +103,92 @@ typedef unsigned long UBaseType_t;
* THUMB mode code will result in a compile time error. * THUMB mode code will result in a compile time error.
*/ */
#define portRESTORE_CONTEXT() \ #define portRESTORE_CONTEXT() \
{ \ { \
extern volatile void * volatile pxCurrentTCB; \ extern volatile void * volatile pxCurrentTCB; \
extern volatile uint32_t ulCriticalNesting; \ extern volatile uint32_t ulCriticalNesting; \
\ \
/* Set the LR to the task stack. */ \ /* Set the LR to the task stack. */ \
__asm volatile ( \ __asm volatile ( \
"LDR R0, =pxCurrentTCB \n\t" \ "LDR R0, =pxCurrentTCB \n\t"\
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t"\
"LDR LR, [R0] \n\t" \ "LDR LR, [R0] \n\t"\
\ \
/* The critical nesting depth is the first item on the stack. */ \ /* The critical nesting depth is the first item on the stack. */ \
/* Load it into the ulCriticalNesting variable. */ \ /* Load it into the ulCriticalNesting variable. */ \
"LDR R0, =ulCriticalNesting \n\t" \ "LDR R0, =ulCriticalNesting \n\t"\
"LDMFD LR!, {R1} \n\t" \ "LDMFD LR!, {R1} \n\t"\
"STR R1, [R0] \n\t" \ "STR R1, [R0] \n\t"\
\ \
/* Get the SPSR from the stack. */ \ /* Get the SPSR from the stack. */ \
"LDMFD LR!, {R0} \n\t" \ "LDMFD LR!, {R0} \n\t"\
"MSR SPSR, R0 \n\t" \ "MSR SPSR, R0 \n\t"\
\ \
/* Restore all system mode registers for the task. */ \ /* Restore all system mode registers for the task. */ \
"LDMFD LR, {R0-R14}^ \n\t" \ "LDMFD LR, {R0-R14}^ \n\t"\
"NOP \n\t" \ "NOP \n\t"\
\ \
/* Restore the return address. */ \ /* Restore the return address. */ \
"LDR LR, [LR, #+60] \n\t" \ "LDR LR, [LR, #+60] \n\t"\
\ \
/* And return - correcting the offset in the LR to obtain the */ \ /* And return - correcting the offset in the LR to obtain the */ \
/* correct address. */ \ /* correct address. */ \
"SUBS PC, LR, #4 \n\t" \ "SUBS PC, LR, #4 \n\t"\
); \ ); \
( void ) ulCriticalNesting; \ ( void ) ulCriticalNesting; \
( void ) pxCurrentTCB; \ ( void ) pxCurrentTCB; \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portSAVE_CONTEXT() \ #define portSAVE_CONTEXT() \
{ \ { \
extern volatile void * volatile pxCurrentTCB; \ extern volatile void * volatile pxCurrentTCB; \
extern volatile uint32_t ulCriticalNesting; \ extern volatile uint32_t ulCriticalNesting; \
\ \
/* Push R0 as we are going to use the register. */ \ /* Push R0 as we are going to use the register. */ \
__asm volatile ( \ __asm volatile ( \
"STMDB SP!, {R0} \n\t" \ "STMDB SP!, {R0} \n\t"\
\ \
/* Set R0 to point to the task stack pointer. */ \ /* Set R0 to point to the task stack pointer. */ \
"STMDB SP,{SP}^ \n\t" \ "STMDB SP,{SP}^ \n\t"\
"NOP \n\t" \ "NOP \n\t"\
"SUB SP, SP, #4 \n\t" \ "SUB SP, SP, #4 \n\t"\
"LDMIA SP!,{R0} \n\t" \ "LDMIA SP!,{R0} \n\t"\
\ \
/* Push the return address onto the stack. */ \ /* Push the return address onto the stack. */ \
"STMDB R0!, {LR} \n\t" \ "STMDB R0!, {LR} \n\t"\
\ \
/* Now we have saved LR we can use it instead of R0. */ \ /* Now we have saved LR we can use it instead of R0. */ \
"MOV LR, R0 \n\t" \ "MOV LR, R0 \n\t"\
\ \
/* Pop R0 so we can save it onto the system mode stack. */ \ /* Pop R0 so we can save it onto the system mode stack. */ \
"LDMIA SP!, {R0} \n\t" \ "LDMIA SP!, {R0} \n\t"\
\ \
/* Push all the system mode registers onto the task stack. */ \ /* Push all the system mode registers onto the task stack. */ \
"STMDB LR,{R0-LR}^ \n\t" \ "STMDB LR,{R0-LR}^ \n\t"\
"NOP \n\t" \ "NOP \n\t"\
"SUB LR, LR, #60 \n\t" \ "SUB LR, LR, #60 \n\t"\
\ \
/* Push the SPSR onto the task stack. */ \ /* Push the SPSR onto the task stack. */ \
"MRS R0, SPSR \n\t" \ "MRS R0, SPSR \n\t"\
"STMDB LR!, {R0} \n\t" \ "STMDB LR!, {R0} \n\t"\
\ \
"LDR R0, =ulCriticalNesting \n\t" \ "LDR R0, =ulCriticalNesting \n\t"\
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t"\
"STMDB LR!, {R0} \n\t" \ "STMDB LR!, {R0} \n\t"\
\ \
/* Store the new top of stack for the task. */ \ /* Store the new top of stack for the task. */ \
"LDR R0, =pxCurrentTCB \n\t" \ "LDR R0, =pxCurrentTCB \n\t"\
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t"\
"STR LR, [R0] \n\t" \ "STR LR, [R0] \n\t"\
); \ ); \
( void ) ulCriticalNesting; \ ( void ) ulCriticalNesting; \
( void ) pxCurrentTCB; \ ( void ) pxCurrentTCB; \
} }
#define portYIELD_FROM_ISR() vTaskSwitchContext() #define portYIELD_FROM_ISR() vTaskSwitchContext()
#define portYIELD() __asm volatile ( "SWI 0" ) #define portYIELD() __asm volatile ( "SWI 0" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -201,48 +201,47 @@ extern volatile uint32_t ulCriticalNesting; \
* defined then the utilities are defined as macros here - as per other ports. * defined then the utilities are defined as macros here - as per other ports.
*/ */
#ifdef THUMB_INTERWORK #ifdef THUMB_INTERWORK
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked)); extern void vPortDisableInterruptsFromThumb( void ) __attribute__( ( naked ) );
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked)); extern void vPortEnableInterruptsFromThumb( void ) __attribute__( ( naked ) );
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb() #define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb() #define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
#else #else
#define portDISABLE_INTERRUPTS() \ #define portDISABLE_INTERRUPTS() \
__asm volatile ( \ __asm volatile ( \
"STMDB SP!, {R0} \n\t" /* Push R0. */ \ "STMDB SP!, {R0} \n\t" /* Push R0. */\
"MRS R0, CPSR \n\t" /* Get CPSR. */ \ "MRS R0, CPSR \n\t" /* Get CPSR. */\
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \ "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */\
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \ "MSR CPSR, R0 \n\t" /* Write back modified value. */\
"LDMIA SP!, {R0} " ) /* Pop R0. */ "LDMIA SP!, {R0} ") /* Pop R0. */
#define portENABLE_INTERRUPTS() \ #define portENABLE_INTERRUPTS() \
__asm volatile ( \ __asm volatile ( \
"STMDB SP!, {R0} \n\t" /* Push R0. */ \ "STMDB SP!, {R0} \n\t" /* Push R0. */\
"MRS R0, CPSR \n\t" /* Get CPSR. */ \ "MRS R0, CPSR \n\t" /* Get CPSR. */\
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \ "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */\
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \ "MSR CPSR, R0 \n\t" /* Write back modified value. */\
"LDMIA SP!, {R0} " ) /* Pop R0. */ "LDMIA SP!, {R0} ") /* Pop R0. */
#endif /* THUMB_INTERWORK */ #endif /* THUMB_INTERWORK */
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical(); #define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical(); #define portEXIT_CRITICAL() vPortExitCritical();
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -32,23 +32,23 @@
#include "task.h" #include "task.h"
#ifndef configINTERRUPT_CONTROLLER_BASE_ADDRESS #ifndef configINTERRUPT_CONTROLLER_BASE_ADDRESS
#error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
#endif #endif
#ifndef configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET #ifndef configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET
#error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
#endif #endif
#ifndef configUNIQUE_INTERRUPT_PRIORITIES #ifndef configUNIQUE_INTERRUPT_PRIORITIES
#error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
#endif #endif
#ifndef configSETUP_TICK_INTERRUPT #ifndef configSETUP_TICK_INTERRUPT
#error configSETUP_TICK_INTERRUPT() must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configSETUP_TICK_INTERRUPT() must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
#endif /* configSETUP_TICK_INTERRUPT */ #endif /* configSETUP_TICK_INTERRUPT */
#ifndef configMAX_API_CALL_INTERRUPT_PRIORITY #ifndef configMAX_API_CALL_INTERRUPT_PRIORITY
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
#endif #endif
#if configMAX_API_CALL_INTERRUPT_PRIORITY == 0 #if configMAX_API_CALL_INTERRUPT_PRIORITY == 0
@ -61,7 +61,7 @@
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */ /* Check the configuration. */
#if( configMAX_PRIORITIES > 32 ) #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. #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 #endif
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
@ -72,24 +72,24 @@
#endif #endif
/* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in /* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in
portmacro.h. */ * portmacro.h. */
#ifndef configCLEAR_TICK_INTERRUPT #ifndef configCLEAR_TICK_INTERRUPT
#define configCLEAR_TICK_INTERRUPT() #define configCLEAR_TICK_INTERRUPT()
#endif #endif
/* A critical section is exited when the critical section nesting count reaches /* A critical section is exited when the critical section nesting count reaches
this value. */ * this value. */
#define portNO_CRITICAL_NESTING ( ( size_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( size_t ) 0 )
/* In all GICs 255 can be written to the priority mask register to unmask all /* In all GICs 255 can be written to the priority mask register to unmask all
(but the lowest) interrupt priority. */ * (but the lowest) interrupt priority. */
#define portUNMASK_VALUE ( 0xFFUL ) #define portUNMASK_VALUE ( 0xFFUL )
/* Tasks are not created with a floating point context, but can be given a /* Tasks are not created with a floating point context, but can be given a
floating point context after they have been created. A variable is stored as * floating point context after they have been created. A variable is stored as
part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task * part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
does not have an FPU context, or any other value if the task does have an FPU * does not have an FPU context, or any other value if the task does have an FPU
context. */ * context. */
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 ) #define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
/* Constants required to setup the initial task context. */ /* Constants required to setup the initial task context. */
@ -107,7 +107,7 @@ context. */
/* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary /* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary
point is zero. */ * point is zero. */
#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 ) #define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 )
/* Masks all bits in the APSR other than the mode bits. */ /* Masks all bits in the APSR other than the mode bits. */
@ -118,13 +118,13 @@ point is zero. */
/* Macro to unmask all interrupt priorities. */ /* Macro to unmask all interrupt priorities. */
#define portCLEAR_INTERRUPT_MASK() \ #define portCLEAR_INTERRUPT_MASK() \
{ \ { \
portDISABLE_INTERRUPTS(); \ portDISABLE_INTERRUPTS(); \
portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \ portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \
__asm volatile ( "DSB SY \n" \ __asm volatile ( "DSB SY \n" \
"ISB SY \n" ); \ "ISB SY \n"); \
portENABLE_INTERRUPTS(); \ portENABLE_INTERRUPTS(); \
} }
/* Hardware specifics used when sanity checking the configuration. */ /* Hardware specifics used when sanity checking the configuration. */
#define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL #define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL
@ -142,38 +142,40 @@ extern void vPortRestoreTaskContext( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* A variable is used to keep track of the critical section nesting. This /* A variable is used to keep track of the critical section nesting. This
variable has to be stored as part of the task context and must be initialised to * variable has to be stored as part of the task context and must be initialised to
a non zero value to ensure interrupts don't inadvertently become unmasked before * a non zero value to ensure interrupts don't inadvertently become unmasked before
the scheduler starts. As it is stored as part of the task context it will * the scheduler starts. As it is stored as part of the task context it will
automatically be set to 0 when the first task is started. */ * automatically be set to 0 when the first task is started. */
volatile uint64_t ullCriticalNesting = 9999ULL; volatile uint64_t ullCriticalNesting = 9999ULL;
/* Saved as part of the task context. If ullPortTaskHasFPUContext is non-zero /* Saved as part of the task context. If ullPortTaskHasFPUContext is non-zero
then floating point context must be saved and restored for the task. */ * then floating point context must be saved and restored for the task. */
uint64_t ullPortTaskHasFPUContext = pdFALSE; uint64_t ullPortTaskHasFPUContext = pdFALSE;
/* Set to 1 to pend a context switch from an ISR. */ /* Set to 1 to pend a context switch from an ISR. */
uint64_t ullPortYieldRequired = pdFALSE; uint64_t ullPortYieldRequired = pdFALSE;
/* Counts the interrupt nesting depth. A context switch is only performed if /* Counts the interrupt nesting depth. A context switch is only performed if
if the nesting depth is 0. */ * if the nesting depth is 0. */
uint64_t ullPortInterruptNesting = 0; uint64_t ullPortInterruptNesting = 0;
/* Used in the ASM code. */ /* Used in the ASM code. */
__attribute__(( used )) const uint64_t ullICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS; __attribute__( ( used ) ) const uint64_t ullICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS;
__attribute__(( used )) const uint64_t ullICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS; __attribute__( ( used ) ) const uint64_t ullICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;
__attribute__(( used )) const uint64_t ullICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS; __attribute__( ( used ) ) const uint64_t ullICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS;
__attribute__(( used )) const uint64_t ullMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); __attribute__( ( used ) ) const uint64_t ullMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* See header file for description. * See header file for description.
*/ */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{ {
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. */ * expected by the portRESTORE_CONTEXT() macro. */
/* First all the general purpose registers. */ /* First all the general purpose registers. */
pxTopOfStack--; pxTopOfStack--;
@ -249,13 +251,13 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
pxTopOfStack--; pxTopOfStack--;
/* The task will start with a critical nesting count of 0 as interrupts are /* The task will start with a critical nesting count of 0 as interrupts are
enabled. */ * enabled. */
*pxTopOfStack = portNO_CRITICAL_NESTING; *pxTopOfStack = portNO_CRITICAL_NESTING;
pxTopOfStack--; pxTopOfStack--;
/* The task will start without a floating point context. A task that uses /* The task will start without a floating point context. A task that uses
the floating point hardware must call vPortTaskUsesFPU() before executing * the floating point hardware must call vPortTaskUsesFPU() before executing
any floating point instructions. */ * any floating point instructions. */
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT; *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
return pxTopOfStack; return pxTopOfStack;
@ -264,21 +266,21 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
uint32_t ulAPSR; uint32_t ulAPSR;
#if( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
volatile uint32_t ulOriginalPriority; volatile uint32_t ulOriginalPriority;
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET ); volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET );
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
/* Determine how many priority bits are implemented in the GIC. /* Determine how many priority bits are implemented in the GIC.
*
Save the interrupt priority value that is about to be clobbered. */ * Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pucFirstUserPriorityRegister; ulOriginalPriority = *pucFirstUserPriorityRegister;
/* Determine the number of priority bits available. First write to /* Determine the number of priority bits available. First write to
all possible bits. */ * all possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -291,13 +293,13 @@ uint32_t ulAPSR;
} }
/* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read /* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
value. */ * value. */
configASSERT( ucMaxPriorityValue >= portLOWEST_INTERRUPT_PRIORITY ); configASSERT( ucMaxPriorityValue >= portLOWEST_INTERRUPT_PRIORITY );
/* Restore the clobbered interrupt priority register to its original /* Restore the clobbered interrupt priority register to its original
value. */ * value. */
*pucFirstUserPriorityRegister = ulOriginalPriority; *pucFirstUserPriorityRegister = ulOriginalPriority;
} }
#endif /* conifgASSERT_DEFINED */ #endif /* conifgASSERT_DEFINED */
@ -307,26 +309,28 @@ uint32_t ulAPSR;
__asm volatile ( "MRS %0, CurrentEL" : "=r" ( ulAPSR ) ); __asm volatile ( "MRS %0, CurrentEL" : "=r" ( ulAPSR ) );
ulAPSR &= portAPSR_MODE_BITS_MASK; ulAPSR &= portAPSR_MODE_BITS_MASK;
#if defined( GUEST ) #if defined( GUEST )
#warning Building for execution as a guest under XEN. THIS IS NOT A FULLY TESTED PATH. #warning Building for execution as a guest under XEN. THIS IS NOT A FULLY TESTED PATH.
configASSERT( ulAPSR == portEL1 ); configASSERT( ulAPSR == portEL1 );
if( ulAPSR == portEL1 ) if( ulAPSR == portEL1 )
#else #else
configASSERT( ulAPSR == portEL3 ); configASSERT( ulAPSR == portEL3 );
if( ulAPSR == portEL3 ) if( ulAPSR == portEL3 )
#endif #endif
{ {
/* Only continue if the binary point value is set to its lowest possible /* Only continue if the binary point value is set to its lowest possible
setting. See the comments in vPortValidateInterruptPriority() below for * setting. See the comments in vPortValidateInterruptPriority() below for
more information. */ * more information. */
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ); configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ) if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
{ {
/* Interrupts are turned off in the CPU itself to ensure a tick does /* Interrupts are turned off in the CPU itself to ensure a tick does
not execute while the scheduler is being started. Interrupts are * not execute while the scheduler is being started. Interrupts are
automatically turned back on in the CPU when the first task starts * automatically turned back on in the CPU when the first task starts
executing. */ * executing. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
/* Start the timer that generates the tick ISR. */ /* Start the timer that generates the tick ISR. */
@ -344,7 +348,7 @@ uint32_t ulAPSR;
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented in ports where there is nothing to return to. /* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */ * Artificially force an assert. */
configASSERT( ullCriticalNesting == 1000ULL ); configASSERT( ullCriticalNesting == 1000ULL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -355,15 +359,15 @@ void vPortEnterCritical( void )
uxPortSetInterruptMask(); uxPortSetInterruptMask();
/* Now interrupts are disabled ullCriticalNesting can be accessed /* Now interrupts are disabled ullCriticalNesting can be accessed
directly. Increment ullCriticalNesting to keep a count of how many times * directly. Increment ullCriticalNesting to keep a count of how many times
portENTER_CRITICAL() has been called. */ * portENTER_CRITICAL() has been called. */
ullCriticalNesting++; ullCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so /* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API * assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if * functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the * the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */ * assert function also uses a critical section. */
if( ullCriticalNesting == 1ULL ) if( ullCriticalNesting == 1ULL )
{ {
configASSERT( ullPortInterruptNesting == 0 ); configASSERT( ullPortInterruptNesting == 0 );
@ -376,15 +380,15 @@ void vPortExitCritical( void )
if( ullCriticalNesting > portNO_CRITICAL_NESTING ) if( ullCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as the critical section is being /* Decrement the nesting count as the critical section is being
exited. */ * exited. */
ullCriticalNesting--; ullCriticalNesting--;
/* If the nesting level has reached zero then all interrupt /* If the nesting level has reached zero then all interrupt
priorities must be re-enabled. */ * priorities must be re-enabled. */
if( ullCriticalNesting == portNO_CRITICAL_NESTING ) if( ullCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Critical nesting has reached zero so all interrupt priorities /* Critical nesting has reached zero so all interrupt priorities
should be unmasked. */ * should be unmasked. */
portCLEAR_INTERRUPT_MASK(); portCLEAR_INTERRUPT_MASK();
} }
} }
@ -401,23 +405,23 @@ void FreeRTOS_Tick_Handler( void )
#endif #endif
/* Interrupts should not be enabled before this point. */ /* Interrupts should not be enabled before this point. */
#if( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
uint32_t ulMaskBits; uint32_t ulMaskBits;
__asm volatile( "mrs %0, daif" : "=r"( ulMaskBits ) :: "memory" ); __asm volatile ( "mrs %0, daif" : "=r" ( ulMaskBits )::"memory" );
configASSERT( ( ulMaskBits & portDAIF_I ) != 0 ); configASSERT( ( ulMaskBits & portDAIF_I ) != 0 );
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/* Set interrupt mask before altering scheduler structures. The tick /* Set interrupt mask before altering scheduler structures. The tick
handler runs at the lowest priority, so interrupts cannot already be masked, * handler runs at the lowest priority, so interrupts cannot already be masked,
so there is no need to save and restore the current mask value. It is * so there is no need to save and restore the current mask value. It is
necessary to turn off interrupts in the CPU itself while the ICCPMR is being * necessary to turn off interrupts in the CPU itself while the ICCPMR is being
updated. */ * updated. */
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
__asm volatile ( "dsb sy \n" __asm volatile ( "dsb sy \n"
"isb sy \n" ::: "memory" ); "isb sy \n"::: "memory" );
/* Ok to enable interrupts after the interrupt source has been cleared. */ /* Ok to enable interrupts after the interrupt source has been cleared. */
configCLEAR_TICK_INTERRUPT(); configCLEAR_TICK_INTERRUPT();
@ -437,11 +441,11 @@ void FreeRTOS_Tick_Handler( void )
void vPortTaskUsesFPU( void ) void vPortTaskUsesFPU( void )
{ {
/* A task is registering the fact that it needs an FPU context. Set the /* A task is registering the fact that it needs an FPU context. Set the
FPU flag (which is saved as part of the task context). */ * FPU flag (which is saved as part of the task context). */
ullPortTaskHasFPUContext = pdTRUE; ullPortTaskHasFPUContext = pdTRUE;
/* Consider initialising the FPSR here - but probably not necessary in /* Consider initialising the FPSR here - but probably not necessary in
AArch64. */ * AArch64. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -456,11 +460,12 @@ void vPortClearInterruptMask( UBaseType_t uxNewMaskValue )
UBaseType_t uxPortSetInterruptMask( void ) UBaseType_t uxPortSetInterruptMask( void )
{ {
uint32_t ulReturn; uint32_t ulReturn;
/* Interrupt in the CPU must be turned off while the ICCPMR is being /* Interrupt in the CPU must be turned off while the ICCPMR is being
updated. */ * updated. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ) if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
{ {
/* Interrupts were already masked. */ /* Interrupts were already masked. */
@ -471,47 +476,47 @@ uint32_t ulReturn;
ulReturn = pdFALSE; ulReturn = pdFALSE;
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
__asm volatile ( "dsb sy \n" __asm volatile ( "dsb sy \n"
"isb sy \n" ::: "memory" ); "isb sy \n"::: "memory" );
} }
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
return ulReturn; return ulReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
void vPortValidateInterruptPriority( void ) void vPortValidateInterruptPriority( void )
{ {
/* The following assertion will fail if a service routine (ISR) for /* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above * an interrupt that has been assigned a priority above
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called * function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below * from interrupts that have been assigned a priority at or below
configMAX_SYSCALL_INTERRUPT_PRIORITY. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
Numerically low interrupt priority numbers represent logically high * Numerically low interrupt priority numbers represent logically high
interrupt priorities, therefore the priority of the interrupt must * interrupt priorities, therefore the priority of the interrupt must
be set to a value equal to or numerically *higher* than * be set to a value equal to or numerically *higher* than
configMAX_SYSCALL_INTERRUPT_PRIORITY. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
FreeRTOS maintains separate thread and ISR API functions to ensure * FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible. */ * interrupt entry is as fast and simple as possible. */
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ); configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
/* Priority grouping: The interrupt controller (GIC) allows the bits /* Priority grouping: The interrupt controller (GIC) allows the bits
that define each interrupt's priority to be split between bits that * that define each interrupt's priority to be split between bits that
define the interrupt's pre-emption priority bits and bits that define * define the interrupt's pre-emption priority bits and bits that define
the interrupt's sub-priority. For simplicity all bits must be defined * the interrupt's sub-priority. For simplicity all bits must be defined
to be pre-emption priority bits. The following assertion will fail if * to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority). * this is not the case (if some bits represent a sub-priority).
*
The priority grouping is configured by the GIC's binary point register * The priority grouping is configured by the GIC's binary point register
(ICCBPR). Writting 0 to ICCBPR will ensure it is set to its lowest * (ICCBPR). Writting 0 to ICCBPR will ensure it is set to its lowest
possible value (which may be above 0). */ * possible value (which may be above 0). */
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ); configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -25,11 +25,11 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -42,169 +42,169 @@
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE size_t #define portSTACK_TYPE size_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef portBASE_TYPE BaseType_t; typedef portBASE_TYPE BaseType_t;
typedef uint64_t UBaseType_t; typedef uint64_t UBaseType_t;
typedef uint64_t TickType_t; typedef uint64_t TickType_t;
#define portMAX_DELAY ( ( TickType_t ) 0xffffffffffffffff ) #define portMAX_DELAY ( ( TickType_t ) 0xffffffffffffffff )
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 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. */ * not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 16 #define portBYTE_ALIGNMENT 16
#define portPOINTER_SIZE_TYPE uint64_t #define portPOINTER_SIZE_TYPE uint64_t
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
/* Called at the end of an ISR that can cause a context switch. */ /* Called at the end of an ISR that can cause a context switch. */
#define portEND_SWITCHING_ISR( xSwitchRequired )\ #define portEND_SWITCHING_ISR( xSwitchRequired ) \
{ \ { \
extern uint64_t ullPortYieldRequired; \ extern uint64_t ullPortYieldRequired; \
\ \
if( xSwitchRequired != pdFALSE ) \ if( xSwitchRequired != pdFALSE ) \
{ \ { \
ullPortYieldRequired = pdTRUE; \ ullPortYieldRequired = pdTRUE; \
} \ } \
} }
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
#if defined( GUEST ) #if defined( GUEST )
#define portYIELD() __asm volatile ( "SVC 0" ::: "memory" ) #define portYIELD() __asm volatile ( "SVC 0" ::: "memory" )
#else #else
#define portYIELD() __asm volatile ( "SMC 0" ::: "memory" ) #define portYIELD() __asm volatile ( "SMC 0" ::: "memory" )
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Critical section control * Critical section control
*----------------------------------------------------------*/ *----------------------------------------------------------*/
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
extern UBaseType_t uxPortSetInterruptMask( void ); extern UBaseType_t uxPortSetInterruptMask( void );
extern void vPortClearInterruptMask( UBaseType_t uxNewMaskValue ); extern void vPortClearInterruptMask( UBaseType_t uxNewMaskValue );
extern void vPortInstallFreeRTOSVectorTable( void ); extern void vPortInstallFreeRTOSVectorTable( void );
#define portDISABLE_INTERRUPTS() \ #define portDISABLE_INTERRUPTS() \
__asm volatile ( "MSR DAIFSET, #2" ::: "memory" ); \ __asm volatile ( "MSR DAIFSET, #2" ::: "memory" ); \
__asm volatile ( "DSB SY" ); \ __asm volatile ( "DSB SY" ); \
__asm volatile ( "ISB SY" ); __asm volatile ( "ISB SY" );
#define portENABLE_INTERRUPTS() \ #define portENABLE_INTERRUPTS() \
__asm volatile ( "MSR DAIFCLR, #2" ::: "memory" ); \ __asm volatile ( "MSR DAIFCLR, #2" ::: "memory" ); \
__asm volatile ( "DSB SY" ); \ __asm volatile ( "DSB SY" ); \
__asm volatile ( "ISB SY" ); __asm volatile ( "ISB SY" );
/* These macros do not globally disable/enable interrupts. They do mask off /* These macros do not globally disable/enable interrupts. They do mask off
interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */ * interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
#define portENTER_CRITICAL() vPortEnterCritical(); #define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical(); #define portEXIT_CRITICAL() vPortExitCritical();
#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMask() #define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortClearInterruptMask( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are /* Task function macros as described on the FreeRTOS.org WEB site. These are
not required for this port but included in case common demo code that uses these * not required for this port but included in case common demo code that uses these
macros is used. */ * macros is used. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/* Prototype of the FreeRTOS tick handler. This must be installed as the /* Prototype of the FreeRTOS tick handler. This must be installed as the
handler for whichever peripheral is used to generate the RTOS tick. */ * handler for whichever peripheral is used to generate the RTOS tick. */
void FreeRTOS_Tick_Handler( void ); void FreeRTOS_Tick_Handler( void );
/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU() /* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
before any floating point instructions are executed. */ * before any floating point instructions are executed. */
void vPortTaskUsesFPU( void ); void vPortTaskUsesFPU( void );
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU() #define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL ) #define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL ) #define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
/* Architecture specific optimisations. */ /* Architecture specific optimisations. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif #endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Store/clear the ready priorities in a bit map. */ /* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#ifdef configASSERT #ifdef configASSERT
void vPortValidateInterruptPriority( void ); void vPortValidateInterruptPriority( void );
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
#endif /* configASSERT */ #endif /* configASSERT */
#define portNOP() __asm volatile( "NOP" ) #define portNOP() __asm volatile ( "NOP" )
#define portINLINE __inline #define portINLINE __inline
#ifdef __cplusplus #ifdef __cplusplus
} /* extern C */ } /* extern C */
#endif #endif
/* The number of bits to shift for an interrupt priority is dependent on the /* The number of bits to shift for an interrupt priority is dependent on the
number of bits implemented by the interrupt controller. */ * number of bits implemented by the interrupt controller. */
#if configUNIQUE_INTERRUPT_PRIORITIES == 16 #if configUNIQUE_INTERRUPT_PRIORITIES == 16
#define portPRIORITY_SHIFT 4 #define portPRIORITY_SHIFT 4
#define portMAX_BINARY_POINT_VALUE 3 #define portMAX_BINARY_POINT_VALUE 3
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32 #elif configUNIQUE_INTERRUPT_PRIORITIES == 32
#define portPRIORITY_SHIFT 3 #define portPRIORITY_SHIFT 3
#define portMAX_BINARY_POINT_VALUE 2 #define portMAX_BINARY_POINT_VALUE 2
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64 #elif configUNIQUE_INTERRUPT_PRIORITIES == 64
#define portPRIORITY_SHIFT 2 #define portPRIORITY_SHIFT 2
#define portMAX_BINARY_POINT_VALUE 1 #define portMAX_BINARY_POINT_VALUE 1
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128 #elif configUNIQUE_INTERRUPT_PRIORITIES == 128
#define portPRIORITY_SHIFT 1 #define portPRIORITY_SHIFT 1
#define portMAX_BINARY_POINT_VALUE 0 #define portMAX_BINARY_POINT_VALUE 0
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256 #elif configUNIQUE_INTERRUPT_PRIORITIES == 256
#define portPRIORITY_SHIFT 0 #define portPRIORITY_SHIFT 0
#define portMAX_BINARY_POINT_VALUE 0 #define portMAX_BINARY_POINT_VALUE 0
#else #else /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware #error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
#endif #endif /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
/* Interrupt controller access addresses. */ /* Interrupt controller access addresses. */
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 ) #define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C ) #define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 ) #define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 ) #define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 ) #define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET ) #define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) ) #define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ) #define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET ) #define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) #define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) ) #define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) ) #define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -32,23 +32,23 @@
#include "task.h" #include "task.h"
#ifndef configINTERRUPT_CONTROLLER_BASE_ADDRESS #ifndef configINTERRUPT_CONTROLLER_BASE_ADDRESS
#error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
#endif #endif
#ifndef configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET #ifndef configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET
#error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
#endif #endif
#ifndef configUNIQUE_INTERRUPT_PRIORITIES #ifndef configUNIQUE_INTERRUPT_PRIORITIES
#error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
#endif #endif
#ifndef configSETUP_TICK_INTERRUPT #ifndef configSETUP_TICK_INTERRUPT
#error configSETUP_TICK_INTERRUPT() must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configSETUP_TICK_INTERRUPT() must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
#endif /* configSETUP_TICK_INTERRUPT */ #endif /* configSETUP_TICK_INTERRUPT */
#ifndef configMAX_API_CALL_INTERRUPT_PRIORITY #ifndef configMAX_API_CALL_INTERRUPT_PRIORITY
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */
#endif #endif
#if configMAX_API_CALL_INTERRUPT_PRIORITY == 0 #if configMAX_API_CALL_INTERRUPT_PRIORITY == 0
@ -61,7 +61,7 @@
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */ /* Check the configuration. */
#if( configMAX_PRIORITIES > 32 ) #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. #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 #endif
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
@ -72,24 +72,24 @@
#endif #endif
/* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in /* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in
portmacro.h. */ * portmacro.h. */
#ifndef configCLEAR_TICK_INTERRUPT #ifndef configCLEAR_TICK_INTERRUPT
#define configCLEAR_TICK_INTERRUPT() #define configCLEAR_TICK_INTERRUPT()
#endif #endif
/* A critical section is exited when the critical section nesting count reaches /* A critical section is exited when the critical section nesting count reaches
this value. */ * this value. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
/* In all GICs 255 can be written to the priority mask register to unmask all /* In all GICs 255 can be written to the priority mask register to unmask all
(but the lowest) interrupt priority. */ * (but the lowest) interrupt priority. */
#define portUNMASK_VALUE ( 0xFFUL ) #define portUNMASK_VALUE ( 0xFFUL )
/* Tasks are not created with a floating point context, but can be given a /* Tasks are not created with a floating point context, but can be given a
floating point context after they have been created. A variable is stored as * floating point context after they have been created. A variable is stored as
part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task * part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
does not have an FPU context, or any other value if the task does have an FPU * does not have an FPU context, or any other value if the task does have an FPU
context. */ * context. */
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 ) #define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
/* Constants required to setup the initial task context. */ /* Constants required to setup the initial task context. */
@ -99,19 +99,19 @@ context. */
#define portTHUMB_MODE_ADDRESS ( 0x01UL ) #define portTHUMB_MODE_ADDRESS ( 0x01UL )
/* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary /* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary
point is zero. */ * point is zero. */
#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 ) #define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 )
/* Masks all bits in the APSR other than the mode bits. */ /* Masks all bits in the APSR other than the mode bits. */
#define portAPSR_MODE_BITS_MASK ( 0x1F ) #define portAPSR_MODE_BITS_MASK ( 0x1F )
/* The value of the mode bits in the APSR when the CPU is executing in user /* The value of the mode bits in the APSR when the CPU is executing in user
mode. */ * mode. */
#define portAPSR_USER_MODE ( 0x10 ) #define portAPSR_USER_MODE ( 0x10 )
/* The critical section macros only mask interrupts up to an application /* The critical section macros only mask interrupts up to an application
determined priority level. Sometimes it is necessary to turn interrupt off in * determined priority level. Sometimes it is necessary to turn interrupt off in
the CPU itself before modifying certain hardware registers. */ * the CPU itself before modifying certain hardware registers. */
#define portCPU_IRQ_DISABLE() \ #define portCPU_IRQ_DISABLE() \
__asm volatile ( "CPSID i" ::: "memory" ); \ __asm volatile ( "CPSID i" ::: "memory" ); \
__asm volatile ( "DSB" ); \ __asm volatile ( "DSB" ); \
@ -125,21 +125,21 @@ the CPU itself before modifying certain hardware registers. */
/* Macro to unmask all interrupt priorities. */ /* Macro to unmask all interrupt priorities. */
#define portCLEAR_INTERRUPT_MASK() \ #define portCLEAR_INTERRUPT_MASK() \
{ \ { \
portCPU_IRQ_DISABLE(); \ portCPU_IRQ_DISABLE(); \
portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \ portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \
__asm volatile ( "DSB \n" \ __asm volatile ( "DSB \n" \
"ISB \n" ); \ "ISB \n"); \
portCPU_IRQ_ENABLE(); \ portCPU_IRQ_ENABLE(); \
} }
#define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL #define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) #define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
#define portBIT_0_SET ( ( uint8_t ) 0x01 ) #define portBIT_0_SET ( ( uint8_t ) 0x01 )
/* Let the user override the pre-loading of the initial LR with the address of /* 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 * prvTaskExitError() in case it messes up unwinding of the stack in the
debugger. */ * debugger. */
#ifdef configTASK_RETURN_ADDRESS #ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#else #else
@ -147,7 +147,7 @@ debugger. */
#endif #endif
/* The space on the stack required to hold the FPU registers. This is 32 64-bit /* The space on the stack required to hold the FPU registers. This is 32 64-bit
registers, plus a 32-bit status register. */ * registers, plus a 32-bit status register. */
#define portFPU_REGISTER_WORDS ( ( 32 * 2 ) + 1 ) #define portFPU_REGISTER_WORDS ( ( 32 * 2 ) + 1 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -182,47 +182,49 @@ static void prvTaskExitError( void );
* FPU registers to be saved on interrupt entry their IRQ handler must be * FPU registers to be saved on interrupt entry their IRQ handler must be
* called vApplicationIRQHandler(). * called vApplicationIRQHandler().
*/ */
void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) __attribute__((weak) ); void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) __attribute__( ( weak ) );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* A variable is used to keep track of the critical section nesting. This /* A variable is used to keep track of the critical section nesting. This
variable has to be stored as part of the task context and must be initialised to * variable has to be stored as part of the task context and must be initialised to
a non zero value to ensure interrupts don't inadvertently become unmasked before * a non zero value to ensure interrupts don't inadvertently become unmasked before
the scheduler starts. As it is stored as part of the task context it will * the scheduler starts. As it is stored as part of the task context it will
automatically be set to 0 when the first task is started. */ * automatically be set to 0 when the first task is started. */
volatile uint32_t ulCriticalNesting = 9999UL; volatile uint32_t ulCriticalNesting = 9999UL;
/* Saved as part of the task context. If ulPortTaskHasFPUContext is non-zero then /* Saved as part of the task context. If ulPortTaskHasFPUContext is non-zero then
a floating point context must be saved and restored for the task. */ * a floating point context must be saved and restored for the task. */
volatile uint32_t ulPortTaskHasFPUContext = pdFALSE; volatile uint32_t ulPortTaskHasFPUContext = pdFALSE;
/* Set to 1 to pend a context switch from an ISR. */ /* Set to 1 to pend a context switch from an ISR. */
volatile uint32_t ulPortYieldRequired = pdFALSE; volatile uint32_t ulPortYieldRequired = pdFALSE;
/* Counts the interrupt nesting depth. A context switch is only performed if /* Counts the interrupt nesting depth. A context switch is only performed if
if the nesting depth is 0. */ * if the nesting depth is 0. */
volatile uint32_t ulPortInterruptNesting = 0UL; volatile uint32_t ulPortInterruptNesting = 0UL;
/* Used in the asm file. */ /* Used in the asm file. */
__attribute__(( used )) const uint32_t ulICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS; __attribute__( ( used ) ) const uint32_t ulICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;
__attribute__(( used )) const uint32_t ulICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS; __attribute__( ( used ) ) const uint32_t ulICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS;
__attribute__(( used )) const uint32_t ulICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS; __attribute__( ( used ) ) const uint32_t ulICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS;
__attribute__(( used )) const uint32_t ulMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); __attribute__( ( used ) ) const uint32_t ulMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* See header file for description. * See header file for description.
*/ */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{ {
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. * expected by the portRESTORE_CONTEXT() macro.
*
The fist real value on the stack is the status register, which is set for * The fist real value on the stack is the status register, which is set for
system mode, with interrupts enabled. A few NULLs are added first to ensure * system mode, with interrupts enabled. A few NULLs are added first to ensure
GDB does not try decoding a non-existent return address. */ * GDB does not try decoding a non-existent return address. */
*pxTopOfStack = ( StackType_t ) NULL; *pxTopOfStack = ( StackType_t ) NULL;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) NULL; *pxTopOfStack = ( StackType_t ) NULL;
@ -274,21 +276,21 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
pxTopOfStack--; pxTopOfStack--;
/* The task will start with a critical nesting count of 0 as interrupts are /* The task will start with a critical nesting count of 0 as interrupts are
enabled. */ * enabled. */
*pxTopOfStack = portNO_CRITICAL_NESTING; *pxTopOfStack = portNO_CRITICAL_NESTING;
#if( configUSE_TASK_FPU_SUPPORT == 1 ) #if ( configUSE_TASK_FPU_SUPPORT == 1 )
{ {
/* The task will start without a floating point context. A task that /* The task will start without a floating point context. A task that
uses the floating point hardware must call vPortTaskUsesFPU() before * uses the floating point hardware must call vPortTaskUsesFPU() before
executing any floating point instructions. */ * executing any floating point instructions. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT; *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
} }
#elif( configUSE_TASK_FPU_SUPPORT == 2 ) #elif ( configUSE_TASK_FPU_SUPPORT == 2 )
{ {
/* The task will start with a floating point context. Leave enough /* The task will start with a floating point context. Leave enough
space for the registers - and ensure they are initialised to 0. */ * space for the registers - and ensure they are initialised to 0. */
pxTopOfStack -= portFPU_REGISTER_WORDS; pxTopOfStack -= portFPU_REGISTER_WORDS;
memset( pxTopOfStack, 0x00, portFPU_REGISTER_WORDS * sizeof( StackType_t ) ); memset( pxTopOfStack, 0x00, portFPU_REGISTER_WORDS * sizeof( StackType_t ) );
@ -296,11 +298,11 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
*pxTopOfStack = pdTRUE; *pxTopOfStack = pdTRUE;
ulPortTaskHasFPUContext = pdTRUE; ulPortTaskHasFPUContext = pdTRUE;
} }
#else #else /* if ( configUSE_TASK_FPU_SUPPORT == 1 ) */
{ {
#error Invalid configUSE_TASK_FPU_SUPPORT setting - configUSE_TASK_FPU_SUPPORT must be set to 1, 2, or left undefined. #error Invalid configUSE_TASK_FPU_SUPPORT setting - configUSE_TASK_FPU_SUPPORT must be set to 1, 2, or left undefined.
} }
#endif #endif /* if ( configUSE_TASK_FPU_SUPPORT == 1 ) */
return pxTopOfStack; return pxTopOfStack;
} }
@ -309,34 +311,37 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
static void prvTaskExitError( void ) static void prvTaskExitError( void )
{ {
/* A function that implements a task must not exit or attempt to return to /* 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 * its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ). * should instead call vTaskDelete( NULL ).
*
Artificially force an assert() to be triggered if configASSERT() is * Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */ * defined, then stop here so application writers can catch the error. */
configASSERT( ulPortInterruptNesting == ~0UL ); configASSERT( ulPortInterruptNesting == ~0UL );
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
for( ;; );
for( ; ; )
{
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
uint32_t ulAPSR; uint32_t ulAPSR;
#if( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
volatile uint32_t ulOriginalPriority; volatile uint32_t ulOriginalPriority;
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET ); volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET );
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
/* Determine how many priority bits are implemented in the GIC. /* Determine how many priority bits are implemented in the GIC.
*
Save the interrupt priority value that is about to be clobbered. */ * Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pucFirstUserPriorityRegister; ulOriginalPriority = *pucFirstUserPriorityRegister;
/* Determine the number of priority bits available. First write to /* Determine the number of priority bits available. First write to
all possible bits. */ * all possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -349,35 +354,35 @@ uint32_t ulAPSR;
} }
/* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read /* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
value. */ * value. */
configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY ); configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY );
/* Restore the clobbered interrupt priority register to its original /* Restore the clobbered interrupt priority register to its original
value. */ * value. */
*pucFirstUserPriorityRegister = ulOriginalPriority; *pucFirstUserPriorityRegister = ulOriginalPriority;
} }
#endif /* conifgASSERT_DEFINED */ #endif /* conifgASSERT_DEFINED */
/* Only continue if the CPU is not in User mode. The CPU must be in a /* Only continue if the CPU is not in User mode. The CPU must be in a
Privileged mode for the scheduler to start. */ * Privileged mode for the scheduler to start. */
__asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) :: "memory" ); __asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR )::"memory" );
ulAPSR &= portAPSR_MODE_BITS_MASK; ulAPSR &= portAPSR_MODE_BITS_MASK;
configASSERT( ulAPSR != portAPSR_USER_MODE ); configASSERT( ulAPSR != portAPSR_USER_MODE );
if( ulAPSR != portAPSR_USER_MODE ) if( ulAPSR != portAPSR_USER_MODE )
{ {
/* Only continue if the binary point value is set to its lowest possible /* Only continue if the binary point value is set to its lowest possible
setting. See the comments in vPortValidateInterruptPriority() below for * setting. See the comments in vPortValidateInterruptPriority() below for
more information. */ * more information. */
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ); configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ) if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
{ {
/* Interrupts are turned off in the CPU itself to ensure tick does /* Interrupts are turned off in the CPU itself to ensure tick does
not execute while the scheduler is being started. Interrupts are * not execute while the scheduler is being started. Interrupts are
automatically turned back on in the CPU when the first task starts * automatically turned back on in the CPU when the first task starts
executing. */ * executing. */
portCPU_IRQ_DISABLE(); portCPU_IRQ_DISABLE();
/* Start the timer that generates the tick ISR. */ /* Start the timer that generates the tick ISR. */
@ -389,10 +394,10 @@ uint32_t ulAPSR;
} }
/* Will only get here if vTaskStartScheduler() was called with the CPU in /* Will only get here if vTaskStartScheduler() was called with the CPU in
a non-privileged mode or the binary point register was not set to its lowest * a non-privileged mode or the binary point register was not set to its lowest
possible value. prvTaskExitError() is referenced to prevent a compiler * possible value. prvTaskExitError() is referenced to prevent a compiler
warning about it being defined but not referenced in the case that the user * warning about it being defined but not referenced in the case that the user
defines their own exit address. */ * defines their own exit address. */
( void ) prvTaskExitError; ( void ) prvTaskExitError;
return 0; return 0;
} }
@ -401,7 +406,7 @@ uint32_t ulAPSR;
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented in ports where there is nothing to return to. /* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */ * Artificially force an assert. */
configASSERT( ulCriticalNesting == 1000UL ); configASSERT( ulCriticalNesting == 1000UL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -412,15 +417,15 @@ void vPortEnterCritical( void )
ulPortSetInterruptMask(); ulPortSetInterruptMask();
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
directly. Increment ulCriticalNesting to keep a count of how many times * directly. Increment ulCriticalNesting to keep a count of how many times
portENTER_CRITICAL() has been called. */ * portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so /* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API * assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if * functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the * the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */ * assert function also uses a critical section. */
if( ulCriticalNesting == 1 ) if( ulCriticalNesting == 1 )
{ {
configASSERT( ulPortInterruptNesting == 0 ); configASSERT( ulPortInterruptNesting == 0 );
@ -433,15 +438,15 @@ void vPortExitCritical( void )
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as the critical section is being /* Decrement the nesting count as the critical section is being
exited. */ * exited. */
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then all interrupt /* If the nesting level has reached zero then all interrupt
priorities must be re-enabled. */ * priorities must be re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Critical nesting has reached zero so all interrupt priorities /* Critical nesting has reached zero so all interrupt priorities
should be unmasked. */ * should be unmasked. */
portCLEAR_INTERRUPT_MASK(); portCLEAR_INTERRUPT_MASK();
} }
} }
@ -451,14 +456,14 @@ void vPortExitCritical( void )
void FreeRTOS_Tick_Handler( void ) void FreeRTOS_Tick_Handler( void )
{ {
/* Set interrupt mask before altering scheduler structures. The tick /* Set interrupt mask before altering scheduler structures. The tick
handler runs at the lowest priority, so interrupts cannot already be masked, * handler runs at the lowest priority, so interrupts cannot already be masked,
so there is no need to save and restore the current mask value. It is * so there is no need to save and restore the current mask value. It is
necessary to turn off interrupts in the CPU itself while the ICCPMR is being * necessary to turn off interrupts in the CPU itself while the ICCPMR is being
updated. */ * updated. */
portCPU_IRQ_DISABLE(); portCPU_IRQ_DISABLE();
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
__asm volatile ( "dsb \n" __asm volatile ( "dsb \n"
"isb \n" ::: "memory" ); "isb \n"::: "memory" );
portCPU_IRQ_ENABLE(); portCPU_IRQ_ENABLE();
/* Increment the RTOS tick. */ /* Increment the RTOS tick. */
@ -473,18 +478,18 @@ void FreeRTOS_Tick_Handler( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configUSE_TASK_FPU_SUPPORT != 2 ) #if ( configUSE_TASK_FPU_SUPPORT != 2 )
void vPortTaskUsesFPU( void ) void vPortTaskUsesFPU( void )
{ {
uint32_t ulInitialFPSCR = 0; uint32_t ulInitialFPSCR = 0;
/* A task is registering the fact that it needs an FPU context. Set the /* A task is registering the fact that it needs an FPU context. Set the
FPU flag (which is saved as part of the task context). */ * FPU flag (which is saved as part of the task context). */
ulPortTaskHasFPUContext = pdTRUE; ulPortTaskHasFPUContext = pdTRUE;
/* Initialise the floating point status register. */ /* Initialise the floating point status register. */
__asm volatile ( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) : "memory" ); __asm volatile ( "FMXR FPSCR, %0" ::"r" ( ulInitialFPSCR ) : "memory" );
} }
#endif /* configUSE_TASK_FPU_SUPPORT */ #endif /* configUSE_TASK_FPU_SUPPORT */
@ -501,11 +506,12 @@ void vPortClearInterruptMask( uint32_t ulNewMaskValue )
uint32_t ulPortSetInterruptMask( void ) uint32_t ulPortSetInterruptMask( void )
{ {
uint32_t ulReturn; uint32_t ulReturn;
/* Interrupt in the CPU must be turned off while the ICCPMR is being /* Interrupt in the CPU must be turned off while the ICCPMR is being
updated. */ * updated. */
portCPU_IRQ_DISABLE(); portCPU_IRQ_DISABLE();
if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ) if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
{ {
/* Interrupts were already masked. */ /* Interrupts were already masked. */
@ -516,44 +522,45 @@ uint32_t ulReturn;
ulReturn = pdFALSE; ulReturn = pdFALSE;
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
__asm volatile ( "dsb \n" __asm volatile ( "dsb \n"
"isb \n" ::: "memory" ); "isb \n"::: "memory" );
} }
portCPU_IRQ_ENABLE(); portCPU_IRQ_ENABLE();
return ulReturn; return ulReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
void vPortValidateInterruptPriority( void ) void vPortValidateInterruptPriority( void )
{ {
/* The following assertion will fail if a service routine (ISR) for /* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above * an interrupt that has been assigned a priority above
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called * function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below * from interrupts that have been assigned a priority at or below
configMAX_SYSCALL_INTERRUPT_PRIORITY. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
Numerically low interrupt priority numbers represent logically high * Numerically low interrupt priority numbers represent logically high
interrupt priorities, therefore the priority of the interrupt must * interrupt priorities, therefore the priority of the interrupt must
be set to a value equal to or numerically *higher* than * be set to a value equal to or numerically *higher* than
configMAX_SYSCALL_INTERRUPT_PRIORITY. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
FreeRTOS maintains separate thread and ISR API functions to ensure * FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible. */ * interrupt entry is as fast and simple as possible. */
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ); configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
/* Priority grouping: The interrupt controller (GIC) allows the bits /* Priority grouping: The interrupt controller (GIC) allows the bits
that define each interrupt's priority to be split between bits that * that define each interrupt's priority to be split between bits that
define the interrupt's pre-emption priority bits and bits that define * define the interrupt's pre-emption priority bits and bits that define
the interrupt's sub-priority. For simplicity all bits must be defined * the interrupt's sub-priority. For simplicity all bits must be defined
to be pre-emption priority bits. The following assertion will fail if * to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority). * this is not the case (if some bits represent a sub-priority).
*
The priority grouping is configured by the GIC's binary point register * The priority grouping is configured by the GIC's binary point register
(ICCBPR). Writting 0 to ICCBPR will ensure it is set to its lowest * (ICCBPR). Writting 0 to ICCBPR will ensure it is set to its lowest
possible value (which may be above 0). */ * possible value (which may be above 0). */
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ); configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
} }

View file

@ -25,11 +25,11 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -42,166 +42,166 @@
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 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. */ * not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
/* Called at the end of an ISR that can cause a context switch. */ /* Called at the end of an ISR that can cause a context switch. */
#define portEND_SWITCHING_ISR( xSwitchRequired )\ #define portEND_SWITCHING_ISR( xSwitchRequired ) \
{ \ { \
extern uint32_t ulPortYieldRequired; \ extern uint32_t ulPortYieldRequired; \
\ \
if( xSwitchRequired != pdFALSE ) \ if( xSwitchRequired != pdFALSE ) \
{ \ { \
ulPortYieldRequired = pdTRUE; \ ulPortYieldRequired = pdTRUE; \
} \ } \
} }
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
#define portYIELD() __asm volatile ( "SWI 0" ::: "memory" ); #define portYIELD() __asm volatile ( "SWI 0" ::: "memory" );
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Critical section control * Critical section control
*----------------------------------------------------------*/ *----------------------------------------------------------*/
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
extern uint32_t ulPortSetInterruptMask( void ); extern uint32_t ulPortSetInterruptMask( void );
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue ); extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
extern void vPortInstallFreeRTOSVectorTable( void ); extern void vPortInstallFreeRTOSVectorTable( void );
/* These macros do not globally disable/enable interrupts. They do mask off /* These macros do not globally disable/enable interrupts. They do mask off
interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */ * interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
#define portENTER_CRITICAL() vPortEnterCritical(); #define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical(); #define portEXIT_CRITICAL() vPortExitCritical();
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() #define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 ) #define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask() #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortClearInterruptMask( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are /* Task function macros as described on the FreeRTOS.org WEB site. These are
not required for this port but included in case common demo code that uses these * not required for this port but included in case common demo code that uses these
macros is used. */ * macros is used. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/* Prototype of the FreeRTOS tick handler. This must be installed as the /* Prototype of the FreeRTOS tick handler. This must be installed as the
handler for whichever peripheral is used to generate the RTOS tick. */ * handler for whichever peripheral is used to generate the RTOS tick. */
void FreeRTOS_Tick_Handler( void ); void FreeRTOS_Tick_Handler( void );
/* If configUSE_TASK_FPU_SUPPORT is set to 1 (or left undefined) then tasks are /* If configUSE_TASK_FPU_SUPPORT is set to 1 (or left undefined) then tasks are
created without an FPU context and must call vPortTaskUsesFPU() to give * created without an FPU context and must call vPortTaskUsesFPU() to give
themselves an FPU context before using any FPU instructions. If * themselves an FPU context before using any FPU instructions. If
configUSE_TASK_FPU_SUPPORT is set to 2 then all tasks will have an FPU context * configUSE_TASK_FPU_SUPPORT is set to 2 then all tasks will have an FPU context
by default. */ * by default. */
#if( configUSE_TASK_FPU_SUPPORT != 2 ) #if ( configUSE_TASK_FPU_SUPPORT != 2 )
void vPortTaskUsesFPU( void ); void vPortTaskUsesFPU( void );
#else #else
/* Each task has an FPU context already, so define this function away to
nothing to prevent it being called accidentally. */
#define vPortTaskUsesFPU()
#endif
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL ) /* Each task has an FPU context already, so define this function away to
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL ) * nothing to prevent it being called accidentally. */
#define vPortTaskUsesFPU()
#endif
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
/* Architecture specific optimisations. */ /* Architecture specific optimisations. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif #endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Store/clear the ready priorities in a bit map. */ /* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) __builtin_clz( uxReadyPriorities ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) __builtin_clz( uxReadyPriorities ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#ifdef configASSERT #ifdef configASSERT
void vPortValidateInterruptPriority( void ); void vPortValidateInterruptPriority( void );
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
#endif /* configASSERT */ #endif /* configASSERT */
#define portNOP() __asm volatile( "NOP" ) #define portNOP() __asm volatile ( "NOP" )
#define portINLINE __inline #define portINLINE __inline
#ifdef __cplusplus #ifdef __cplusplus
} /* extern C */ } /* extern C */
#endif #endif
/* The number of bits to shift for an interrupt priority is dependent on the /* The number of bits to shift for an interrupt priority is dependent on the
number of bits implemented by the interrupt controller. */ * number of bits implemented by the interrupt controller. */
#if configUNIQUE_INTERRUPT_PRIORITIES == 16 #if configUNIQUE_INTERRUPT_PRIORITIES == 16
#define portPRIORITY_SHIFT 4 #define portPRIORITY_SHIFT 4
#define portMAX_BINARY_POINT_VALUE 3 #define portMAX_BINARY_POINT_VALUE 3
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32 #elif configUNIQUE_INTERRUPT_PRIORITIES == 32
#define portPRIORITY_SHIFT 3 #define portPRIORITY_SHIFT 3
#define portMAX_BINARY_POINT_VALUE 2 #define portMAX_BINARY_POINT_VALUE 2
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64 #elif configUNIQUE_INTERRUPT_PRIORITIES == 64
#define portPRIORITY_SHIFT 2 #define portPRIORITY_SHIFT 2
#define portMAX_BINARY_POINT_VALUE 1 #define portMAX_BINARY_POINT_VALUE 1
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128 #elif configUNIQUE_INTERRUPT_PRIORITIES == 128
#define portPRIORITY_SHIFT 1 #define portPRIORITY_SHIFT 1
#define portMAX_BINARY_POINT_VALUE 0 #define portMAX_BINARY_POINT_VALUE 0
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256 #elif configUNIQUE_INTERRUPT_PRIORITIES == 256
#define portPRIORITY_SHIFT 0 #define portPRIORITY_SHIFT 0
#define portMAX_BINARY_POINT_VALUE 0 #define portMAX_BINARY_POINT_VALUE 0
#else #else /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware #error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
#endif #endif /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
/* Interrupt controller access addresses. */ /* Interrupt controller access addresses. */
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 ) #define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C ) #define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 ) #define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 ) #define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 ) #define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET ) #define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) ) #define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ) #define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET ) #define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) #define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) ) #define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) ) #define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -25,19 +25,19 @@
*/ */
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM CM0 port. * Implementation of functions defined in portable.h for the ARM CM0 port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Scheduler includes. */ /* Scheduler includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
/* Constants required to manipulate the NVIC. */ /* Constants required to manipulate the NVIC. */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) #define portNVIC_SYSPRI2_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) #define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) #define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
@ -54,15 +54,15 @@
#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) #define portMAX_24_BIT_NUMBER ( 0xffffffUL )
/* A fiddle factor to estimate the number of SysTick counts that would have /* A fiddle factor to estimate the number of SysTick counts that would have
occurred while the SysTick counter is stopped during tickless idle * occurred while the SysTick counter is stopped during tickless idle
calculations. */ * calculations. */
#ifndef portMISSED_COUNTS_FACTOR #ifndef portMISSED_COUNTS_FACTOR
#define portMISSED_COUNTS_FACTOR ( 45UL ) #define portMISSED_COUNTS_FACTOR ( 45UL )
#endif #endif
/* Let the user override the pre-loading of the initial LR with the address of /* 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 * prvTaskExitError() in case it messes up unwinding of the stack in the
debugger. */ * debugger. */
#ifdef configTASK_RETURN_ADDRESS #ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#else #else
@ -79,14 +79,14 @@ void vPortSetupTimerInterrupt( void );
/* /*
* Exception handlers. * Exception handlers.
*/ */
void xPortPendSVHandler( void ) __attribute__ (( naked )); void xPortPendSVHandler( void ) __attribute__( ( naked ) );
void xPortSysTickHandler( void ); void xPortSysTickHandler( void );
void vPortSVCHandler( void ); void vPortSVCHandler( void );
/* /*
* Start first task is a separate function so it can be tested in isolation. * Start first task is a separate function so it can be tested in isolation.
*/ */
static void vPortStartFirstTask( void ) __attribute__ (( naked )); static void vPortStartFirstTask( void ) __attribute__( ( naked ) );
/* /*
* Used to catch tasks that attempt to return from their implementing function. * Used to catch tasks that attempt to return from their implementing function.
@ -96,15 +96,15 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Each task maintains its own interrupt status in the critical nesting /* Each task maintains its own interrupt status in the critical nesting
variable. */ * variable. */
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* The number of SysTick increments that make up one tick period. * The number of SysTick increments that make up one tick period.
*/ */
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulTimerCountsForOneTick = 0; static uint32_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
@ -112,7 +112,7 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
* The maximum number of tick periods that can be suppressed is limited by the * The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer. * 24 bit resolution of the SysTick timer.
*/ */
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
static uint32_t xMaximumPossibleSuppressedTicks = 0; static uint32_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
@ -120,7 +120,7 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
* Compensate for the CPU cycles that pass while the SysTick is stopped (low * Compensate for the CPU cycles that pass while the SysTick is stopped (low
* power functionality only. * power functionality only.
*/ */
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulStoppedTimerCompensation = 0; static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
@ -129,10 +129,12 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
/* /*
* See header file for description. * See header file for description.
*/ */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{ {
/* Simulate the stack frame as it would be created by a context switch /* Simulate the stack frame as it would be created by a context switch
interrupt. */ * interrupt. */
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */ *pxTopOfStack = portINITIAL_XPSR; /* xPSR */
pxTopOfStack--; pxTopOfStack--;
@ -149,25 +151,26 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
static void prvTaskExitError( void ) static void prvTaskExitError( void )
{ {
volatile uint32_t ulDummy = 0UL; volatile uint32_t ulDummy = 0UL;
/* A function that implements a task must not exit or attempt to return to /* 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 * its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ). * should instead call vTaskDelete( NULL ).
*
Artificially force an assert() to be triggered if configASSERT() is * Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */ * defined, then stop here so application writers can catch the error. */
configASSERT( uxCriticalNesting == ~0UL ); configASSERT( uxCriticalNesting == ~0UL );
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
while( ulDummy == 0 ) while( ulDummy == 0 )
{ {
/* This file calls prvTaskExitError() after the scheduler has been /* This file calls prvTaskExitError() after the scheduler has been
started to remove a compiler warning about the function being defined * started to remove a compiler warning about the function being defined
but never called. ulDummy is used purely to quieten other warnings * but never called. ulDummy is used purely to quieten other warnings
about code appearing after this function is called - making ulDummy * about code appearing after this function is called - making ulDummy
volatile makes the compiler think the function could return and * volatile makes the compiler think the function could return and
therefore not output an 'unreachable code' warning for code that appears * therefore not output an 'unreachable code' warning for code that appears
after it. */ * after it. */
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -175,31 +178,31 @@ volatile uint32_t ulDummy = 0UL;
void vPortSVCHandler( void ) void vPortSVCHandler( void )
{ {
/* This function is no longer used, but retained for backward /* This function is no longer used, but retained for backward
compatibility. */ * compatibility. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortStartFirstTask( void ) void vPortStartFirstTask( void )
{ {
/* The MSP stack is not reset as, unlike on M3/4 parts, there is no vector /* The MSP stack is not reset as, unlike on M3/4 parts, there is no vector
table offset register that can be used to locate the initial stack value. * table offset register that can be used to locate the initial stack value.
Not all M0 parts have the application vector table at address 0. */ * Not all M0 parts have the application vector table at address 0. */
__asm volatile( __asm volatile (
" .syntax unified \n" " .syntax unified \n"
" ldr r2, pxCurrentTCBConst2 \n" /* Obtain location of pxCurrentTCB. */ " ldr r2, pxCurrentTCBConst2 \n"/* Obtain location of pxCurrentTCB. */
" ldr r3, [r2] \n" " ldr r3, [r2] \n"
" ldr r0, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. */
" adds r0, #32 \n" /* Discard everything up to r0. */ " 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. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" movs r0, #2 \n" /* Switch to the psp stack. */ " movs r0, #2 \n"/* Switch to the psp stack. */
" msr CONTROL, r0 \n" " msr CONTROL, r0 \n"
" isb \n" " isb \n"
" pop {r0-r5} \n" /* Pop the registers that are saved automatically. */ " pop {r0-r5} \n"/* Pop the registers that are saved automatically. */
" mov lr, r5 \n" /* lr is now in r5. */ " mov lr, r5 \n"/* lr is now in r5. */
" pop {r3} \n" /* Return address is now in r3. */ " pop {r3} \n"/* Return address is now in r3. */
" pop {r2} \n" /* Pop and discard XPSR. */ " pop {r2} \n"/* Pop and discard XPSR. */
" cpsie i \n" /* The first task has its context and interrupts can be enabled. */ " cpsie i \n"/* The first task has its context and interrupts can be enabled. */
" bx r3 \n" /* Finally, jump to the user defined task code. */ " bx r3 \n"/* Finally, jump to the user defined task code. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB " "pxCurrentTCBConst2: .word pxCurrentTCB "
@ -217,7 +220,7 @@ BaseType_t xPortStartScheduler( void )
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ * here already. */
vPortSetupTimerInterrupt(); vPortSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */ /* Initialise the critical nesting count ready for the first task. */
@ -227,11 +230,11 @@ BaseType_t xPortStartScheduler( void )
vPortStartFirstTask(); vPortStartFirstTask();
/* Should never get here as the tasks will now be executing! Call the task /* 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 * exit error function to prevent compiler warnings about a static function
not being called in the case that the application writer overrides this * not being called in the case that the application writer overrides this
functionality by defining configTASK_RETURN_ADDRESS. Call * functionality by defining configTASK_RETURN_ADDRESS. Call
vTaskSwitchContext() so link time optimisation does not remove the * vTaskSwitchContext() so link time optimisation does not remove the
symbol. */ * symbol. */
vTaskSwitchContext(); vTaskSwitchContext();
prvTaskExitError(); prvTaskExitError();
@ -243,7 +246,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented in ports where there is nothing to return to. /* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */ * Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL ); configASSERT( uxCriticalNesting == 1000UL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -254,9 +257,9 @@ void vPortYield( void )
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
/* Barriers are normally not required but do ensure the code is completely /* Barriers are normally not required but do ensure the code is completely
within the specified behaviour for the architecture. */ * within the specified behaviour for the architecture. */
__asm volatile( "dsb" ::: "memory" ); __asm volatile ( "dsb" ::: "memory" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -264,8 +267,8 @@ void vPortEnterCritical( void )
{ {
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
uxCriticalNesting++; uxCriticalNesting++;
__asm volatile( "dsb" ::: "memory" ); __asm volatile ( "dsb" ::: "memory" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -273,6 +276,7 @@ void vPortExitCritical( void )
{ {
configASSERT( uxCriticalNesting ); configASSERT( uxCriticalNesting );
uxCriticalNesting--; uxCriticalNesting--;
if( uxCriticalNesting == 0 ) if( uxCriticalNesting == 0 )
{ {
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
@ -282,7 +286,7 @@ void vPortExitCritical( void )
uint32_t ulSetInterruptMaskFromISR( void ) uint32_t ulSetInterruptMaskFromISR( void )
{ {
__asm volatile( __asm volatile (
" mrs r0, PRIMASK \n" " mrs r0, PRIMASK \n"
" cpsid i \n" " cpsid i \n"
" bx lr " " bx lr "
@ -293,7 +297,7 @@ uint32_t ulSetInterruptMaskFromISR( void )
void vClearInterruptMaskFromISR( __attribute__( ( unused ) ) uint32_t ulMask ) void vClearInterruptMaskFromISR( __attribute__( ( unused ) ) uint32_t ulMask )
{ {
__asm volatile( __asm volatile (
" msr PRIMASK, r0 \n" " msr PRIMASK, r0 \n"
" bx lr " " bx lr "
::: "memory" ::: "memory"
@ -310,13 +314,13 @@ void xPortPendSVHandler( void )
" .syntax unified \n" " .syntax unified \n"
" mrs r0, psp \n" " mrs r0, psp \n"
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */
" ldr r2, [r3] \n" " ldr r2, [r3] \n"
" \n" " \n"
" subs r0, r0, #32 \n" /* Make space for the remaining low registers. */ " subs r0, r0, #32 \n"/* Make space for the remaining low registers. */
" str r0, [r2] \n" /* Save the new top of stack. */ " str r0, [r2] \n"/* Save the new top of stack. */
" stmia r0!, {r4-r7} \n" /* Store the low registers that are not saved automatically. */ " stmia r0!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */
" mov r4, r8 \n" /* Store the high registers. */ " mov r4, r8 \n"/* Store the high registers. */
" mov r5, r9 \n" " mov r5, r9 \n"
" mov r6, r10 \n" " mov r6, r10 \n"
" mov r7, r11 \n" " mov r7, r11 \n"
@ -326,21 +330,21 @@ void xPortPendSVHandler( void )
" cpsid i \n" " cpsid i \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" cpsie i \n" " cpsie i \n"
" pop {r2, r3} \n" /* lr goes in r3. r2 now holds tcb pointer. */ " pop {r2, r3} \n"/* lr goes in r3. r2 now holds tcb pointer. */
" \n" " \n"
" ldr r1, [r2] \n" " ldr r1, [r2] \n"
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */
" adds r0, r0, #16 \n" /* Move to the high registers. */ " adds r0, r0, #16 \n"/* Move to the high registers. */
" ldmia r0!, {r4-r7} \n" /* Pop the high registers. */ " ldmia r0!, {r4-r7} \n"/* Pop the high registers. */
" mov r8, r4 \n" " mov r8, r4 \n"
" mov r9, r5 \n" " mov r9, r5 \n"
" mov r10, r6 \n" " mov r10, r6 \n"
" mov r11, r7 \n" " mov r11, r7 \n"
" \n" " \n"
" msr psp, r0 \n" /* Remember the new top of stack for the task. */ " msr psp, r0 \n"/* Remember the new top of stack for the task. */
" \n" " \n"
" subs r0, r0, #32 \n" /* Go back for the low registers that are not automatically restored. */ " subs r0, r0, #32 \n"/* Go back for the low registers that are not automatically restored. */
" ldmia r0!, {r4-r7} \n" /* Pop low registers. */ " ldmia r0!, {r4-r7} \n"/* Pop low registers. */
" \n" " \n"
" bx r3 \n" " bx r3 \n"
" \n" " \n"
@ -352,7 +356,7 @@ void xPortPendSVHandler( void )
void xPortSysTickHandler( void ) void xPortSysTickHandler( void )
{ {
uint32_t ulPreviousMask; uint32_t ulPreviousMask;
ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
{ {
@ -371,10 +375,10 @@ uint32_t ulPreviousMask;
* Setup the systick timer to generate the tick interrupts at the required * Setup the systick timer to generate the tick interrupts at the required
* frequency. * frequency.
*/ */
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void )
{ {
/* Calculate the constants required to configure the tick interrupt. */ /* Calculate the constants required to configure the tick interrupt. */
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
{ {
ulTimerCountsForOneTick = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ); ulTimerCountsForOneTick = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
@ -392,9 +396,9 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
__attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{ {
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
TickType_t xModifiableIdleTime; TickType_t xModifiableIdleTime;
@ -406,44 +410,45 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
} }
/* Stop the SysTick momentarily. The time the SysTick is stopped for /* Stop the SysTick momentarily. The time the SysTick is stopped for
is accounted for as best it can be, but using the tickless mode will * is accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the * inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */ * kernel with respect to calendar time. */
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
/* Calculate the reload value required to wait xExpectedIdleTime /* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way * tick periods. -1 is used because this code will execute part way
through one of the tick periods. */ * through one of the tick periods. */
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
if( ulReloadValue > ulStoppedTimerCompensation ) if( ulReloadValue > ulStoppedTimerCompensation )
{ {
ulReloadValue -= ulStoppedTimerCompensation; ulReloadValue -= ulStoppedTimerCompensation;
} }
/* Enter a critical section but don't use the taskENTER_CRITICAL() /* Enter a critical section but don't use the taskENTER_CRITICAL()
method as that will mask interrupts that should exit sleep mode. */ * method as that will mask interrupts that should exit sleep mode. */
__asm volatile( "cpsid i" ::: "memory" ); __asm volatile ( "cpsid i" ::: "memory" );
__asm volatile( "dsb" ); __asm volatile ( "dsb" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
/* If a context switch is pending or a task is waiting for the scheduler /* If a context switch is pending or a task is waiting for the scheduler
to be unsuspended then abandon the low power entry. */ * to be unsuspended then abandon the low power entry. */
if( eTaskConfirmSleepModeStatus() == eAbortSleep ) if( eTaskConfirmSleepModeStatus() == eAbortSleep )
{ {
/* Restart from whatever is left in the count register to complete /* Restart from whatever is left in the count register to complete
this tick period. */ * this tick period. */
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* Restart SysTick. */ /* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Reset the reload register to the value required for normal tick /* Reset the reload register to the value required for normal tick
periods. */ * periods. */
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Re-enable interrupts - see comments above the cpsid instruction() /* Re-enable interrupts - see comments above the cpsid instruction()
above. */ * above. */
__asm volatile( "cpsie i" ::: "memory" ); __asm volatile ( "cpsie i" ::: "memory" );
} }
else else
{ {
@ -451,69 +456,71 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
portNVIC_SYSTICK_LOAD_REG = ulReloadValue; portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
/* Clear the SysTick count flag and set the count value back to /* Clear the SysTick count flag and set the count value back to
zero. */ * zero. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */ /* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
set its parameter to 0 to indicate that its implementation contains * set its parameter to 0 to indicate that its implementation contains
its own wait for interrupt or wait for event instruction, and so wfi * its own wait for interrupt or wait for event instruction, and so wfi
should not be executed again. However, the original expected idle * should not be executed again. However, the original expected idle
time variable must remain unmodified, so a copy is taken. */ * time variable must remain unmodified, so a copy is taken. */
xModifiableIdleTime = xExpectedIdleTime; xModifiableIdleTime = xExpectedIdleTime;
configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
if( xModifiableIdleTime > 0 ) if( xModifiableIdleTime > 0 )
{ {
__asm volatile( "dsb" ::: "memory" ); __asm volatile ( "dsb" ::: "memory" );
__asm volatile( "wfi" ); __asm volatile ( "wfi" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
} }
configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
/* Re-enable interrupts to allow the interrupt that brought the MCU /* Re-enable interrupts to allow the interrupt that brought the MCU
out of sleep mode to execute immediately. see comments above * out of sleep mode to execute immediately. see comments above
__disable_interrupt() call above. */ * __disable_interrupt() call above. */
__asm volatile( "cpsie i" ::: "memory" ); __asm volatile ( "cpsie i" ::: "memory" );
__asm volatile( "dsb" ); __asm volatile ( "dsb" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
/* Disable interrupts again because the clock is about to be stopped /* Disable interrupts again because the clock is about to be stopped
and interrupts that execute while the clock is stopped will increase * and interrupts that execute while the clock is stopped will increase
any slippage between the time maintained by the RTOS and calendar * any slippage between the time maintained by the RTOS and calendar
time. */ * time. */
__asm volatile( "cpsid i" ::: "memory" ); __asm volatile ( "cpsid i" ::: "memory" );
__asm volatile( "dsb" ); __asm volatile ( "dsb" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
/* Disable the SysTick clock without reading the /* Disable the SysTick clock without reading the
portNVIC_SYSTICK_CTRL_REG register to ensure the * portNVIC_SYSTICK_CTRL_REG register to ensure the
portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
the time the SysTick is stopped for is accounted for as best it can * the time the SysTick is stopped for is accounted for as best it can
be, but using the tickless mode will inevitably result in some tiny * be, but using the tickless mode will inevitably result in some tiny
drift of the time maintained by the kernel with respect to calendar * drift of the time maintained by the kernel with respect to calendar
time*/ * time*/
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT ); portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
/* Determine if the SysTick clock has already counted to zero and /* Determine if the SysTick clock has already counted to zero and
been set back to the current reload value (the reload back being * been set back to the current reload value (the reload back being
correct for the entire expected idle time) or if the SysTick is yet * correct for the entire expected idle time) or if the SysTick is yet
to count to zero (in which case an interrupt other than the SysTick * to count to zero (in which case an interrupt other than the SysTick
must have brought the system out of sleep mode). */ * must have brought the system out of sleep mode). */
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{ {
uint32_t ulCalculatedLoadValue; uint32_t ulCalculatedLoadValue;
/* The tick interrupt is already pending, and the SysTick count /* The tick interrupt is already pending, and the SysTick count
reloaded with ulReloadValue. Reset the * reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick * portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */ * period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
/* Don't allow a tiny value, or values that have somehow /* Don't allow a tiny value, or values that have somehow
underflowed because the post sleep hook did something * underflowed because the post sleep hook did something
that took too long. */ * that took too long. */
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
{ {
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
@ -522,37 +529,37 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
/* As the pending tick will be processed as soon as this /* As the pending tick will be processed as soon as this
function exits, the tick value maintained by the tick is stepped * function exits, the tick value maintained by the tick is stepped
forward by one less than the time spent waiting. */ * forward by one less than the time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL; ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
} }
else else
{ {
/* Something other than the tick interrupt ended the sleep. /* Something other than the tick interrupt ended the sleep.
Work out how long the sleep lasted rounded to complete tick * Work out how long the sleep lasted rounded to complete tick
periods (not the ulReload value which accounted for part * periods (not the ulReload value which accounted for part
ticks). */ * ticks). */
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* How many complete tick periods passed while the processor /* How many complete tick periods passed while the processor
was waiting? */ * was waiting? */
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
/* The reload value is set to whatever fraction of a single tick /* The reload value is set to whatever fraction of a single tick
period remains. */ * period remains. */
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
} }
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard * again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
value. */ * value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
vTaskStepTick( ulCompleteTickPeriods ); vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrpts enabled. */ /* Exit with interrpts enabled. */
__asm volatile( "cpsie i" ::: "memory" ); __asm volatile ( "cpsie i" ::: "memory" );
} }
} }

View file

@ -26,11 +26,11 @@
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -43,82 +43,81 @@ extern "C" {
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 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. */ * not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specifics. */ /* Architecture specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portDONT_DISCARD __attribute__(( used )) #define portDONT_DISCARD __attribute__( ( used ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Scheduler utilities. */ /* Scheduler utilities. */
extern void vPortYield( void ); extern void vPortYield( void );
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section management. */ /* Critical section management. */
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
extern uint32_t ulSetInterruptMaskFromISR( void ) __attribute__((naked)); extern uint32_t ulSetInterruptMaskFromISR( void ) __attribute__( ( naked ) );
extern void vClearInterruptMaskFromISR( uint32_t ulMask ) __attribute__((naked)); extern void vClearInterruptMaskFromISR( uint32_t ulMask ) __attribute__( ( naked ) );
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR() #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMaskFromISR( x ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMaskFromISR( x )
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) #define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) #define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Tickless idle/low power functionality. */ /* Tickless idle/low power functionality. */
#ifndef portSUPPRESS_TICKS_AND_SLEEP #ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portNOP() #define portNOP()
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -39,7 +39,7 @@
/* Portasm includes. */ /* Portasm includes. */
#include "portasm.h" #include "portasm.h"
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/* Secure components includes. */ /* Secure components includes. */
#include "secure_context.h" #include "secure_context.h"
#include "secure_init.h" #include "secure_init.h"
@ -62,7 +62,7 @@
* 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support: * 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 * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0
*/ */
#if( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) ) #if ( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) )
#error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side. #error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side.
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -70,10 +70,10 @@
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) #define portNVIC_SYSPRI2_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) #define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) #define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) #define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
@ -85,7 +85,8 @@
/* Ensure the SysTick is clocked at the same frequency as the core. */ /* Ensure the SysTick is clocked at the same frequency as the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#else #else
/* The way the SysTick is clocked is not modified in case it is not the
/* The way the SysTick is clocked is not modified in case it is not the
* same a the core. */ * same a the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 0 ) #define portNVIC_SYSTICK_CLK_BIT ( 0 )
#endif #endif
@ -94,7 +95,7 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -117,24 +118,24 @@
/** /**
* @brief Constants required to manipulate the MPU. * @brief Constants required to manipulate the MPU.
*/ */
#define portMPU_TYPE_REG ( * ( ( volatile uint32_t * ) 0xe000ed90 ) ) #define portMPU_TYPE_REG ( *( ( volatile uint32_t * ) 0xe000ed90 ) )
#define portMPU_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed94 ) ) #define portMPU_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed94 ) )
#define portMPU_RNR_REG ( * ( ( volatile uint32_t * ) 0xe000ed98 ) ) #define portMPU_RNR_REG ( *( ( volatile uint32_t * ) 0xe000ed98 ) )
#define portMPU_RBAR_REG ( * ( ( volatile uint32_t * ) 0xe000ed9c ) ) #define portMPU_RBAR_REG ( *( ( volatile uint32_t * ) 0xe000ed9c ) )
#define portMPU_RLAR_REG ( * ( ( volatile uint32_t * ) 0xe000eda0 ) ) #define portMPU_RLAR_REG ( *( ( volatile uint32_t * ) 0xe000eda0 ) )
#define portMPU_RBAR_A1_REG ( * ( ( volatile uint32_t * ) 0xe000eda4 ) ) #define portMPU_RBAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda4 ) )
#define portMPU_RLAR_A1_REG ( * ( ( volatile uint32_t * ) 0xe000eda8 ) ) #define portMPU_RLAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda8 ) )
#define portMPU_RBAR_A2_REG ( * ( ( volatile uint32_t * ) 0xe000edac ) ) #define portMPU_RBAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edac ) )
#define portMPU_RLAR_A2_REG ( * ( ( volatile uint32_t * ) 0xe000edb0 ) ) #define portMPU_RLAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edb0 ) )
#define portMPU_RBAR_A3_REG ( * ( ( volatile uint32_t * ) 0xe000edb4 ) ) #define portMPU_RBAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb4 ) )
#define portMPU_RLAR_A3_REG ( * ( ( volatile uint32_t * ) 0xe000edb8 ) ) #define portMPU_RLAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb8 ) )
#define portMPU_MAIR0_REG ( * ( ( volatile uint32_t * ) 0xe000edc0 ) ) #define portMPU_MAIR0_REG ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
#define portMPU_MAIR1_REG ( * ( ( volatile uint32_t * ) 0xe000edc4 ) ) #define portMPU_MAIR1_REG ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */ #define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */ #define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
@ -204,8 +205,9 @@
*/ */
#define portINITIAL_XPSR ( 0x01000000 ) #define portINITIAL_XPSR ( 0x01000000 )
#if( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/**
/**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -221,7 +223,8 @@
*/ */
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/**
/**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -284,15 +287,17 @@
*/ */
static void prvTaskExitError( void ); static void prvTaskExitError( void );
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/**
/**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/**
/**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -337,7 +342,7 @@ void SysTick_Handler( void ) PRIVILEGED_FUNCTION;
/** /**
* @brief C part of SVC handler. * @brief C part of SVC handler.
*/ */
portDONT_DISCARD void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) PRIVILEGED_FUNCTION; portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIVILEGED_FUNCTION;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -346,27 +351,29 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) PRIVI
*/ */
static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/**
/**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
/**
/**
* @brief The number of SysTick increments that make up one tick period. * @brief The number of SysTick increments that make up one tick period.
*/ */
static uint32_t ulTimerCountsForOneTick = 0; static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
static uint32_t xMaximumPossibleSuppressedTicks = 0; static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -374,8 +381,8 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
__attribute__(( weak )) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{ {
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
TickType_t xModifiableIdleTime; TickType_t xModifiableIdleTime;
@ -396,6 +403,7 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
* tick periods. -1 is used because this code will execute part way * tick periods. -1 is used because this code will execute part way
* through one of the tick periods. */ * through one of the tick periods. */
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
if( ulReloadValue > ulStoppedTimerCompensation ) if( ulReloadValue > ulStoppedTimerCompensation )
{ {
ulReloadValue -= ulStoppedTimerCompensation; ulReloadValue -= ulStoppedTimerCompensation;
@ -403,9 +411,9 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
/* Enter a critical section but don't use the taskENTER_CRITICAL() /* Enter a critical section but don't use the taskENTER_CRITICAL()
* method as that will mask interrupts that should exit sleep mode. */ * method as that will mask interrupts that should exit sleep mode. */
__asm volatile( "cpsid i" ::: "memory" ); __asm volatile ( "cpsid i" ::: "memory" );
__asm volatile( "dsb" ); __asm volatile ( "dsb" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
/* If a context switch is pending or a task is waiting for the scheduler /* If a context switch is pending or a task is waiting for the scheduler
* to be un-suspended then abandon the low power entry. */ * to be un-suspended then abandon the low power entry. */
@ -424,7 +432,7 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
/* Re-enable interrupts - see comments above the cpsid instruction() /* Re-enable interrupts - see comments above the cpsid instruction()
* above. */ * above. */
__asm volatile( "cpsie i" ::: "memory" ); __asm volatile ( "cpsie i" ::: "memory" );
} }
else else
{ {
@ -446,28 +454,30 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
* so a copy is taken. */ * so a copy is taken. */
xModifiableIdleTime = xExpectedIdleTime; xModifiableIdleTime = xExpectedIdleTime;
configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
if( xModifiableIdleTime > 0 ) if( xModifiableIdleTime > 0 )
{ {
__asm volatile( "dsb" ::: "memory" ); __asm volatile ( "dsb" ::: "memory" );
__asm volatile( "wfi" ); __asm volatile ( "wfi" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
} }
configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
/* Re-enable interrupts to allow the interrupt that brought the MCU /* Re-enable interrupts to allow the interrupt that brought the MCU
* out of sleep mode to execute immediately. See comments above * out of sleep mode to execute immediately. See comments above
* the cpsid instruction above. */ * the cpsid instruction above. */
__asm volatile( "cpsie i" ::: "memory" ); __asm volatile ( "cpsie i" ::: "memory" );
__asm volatile( "dsb" ); __asm volatile ( "dsb" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
/* Disable interrupts again because the clock is about to be stopped /* Disable interrupts again because the clock is about to be stopped
* and interrupts that execute while the clock is stopped will * and interrupts that execute while the clock is stopped will
* increase any slippage between the time maintained by the RTOS and * increase any slippage between the time maintained by the RTOS and
* calendar time. */ * calendar time. */
__asm volatile( "cpsid i" ::: "memory" ); __asm volatile ( "cpsid i" ::: "memory" );
__asm volatile( "dsb" ); __asm volatile ( "dsb" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
/* Disable the SysTick clock without reading the /* Disable the SysTick clock without reading the
* portNVIC_SYSTICK_CTRL_REG register to ensure the * portNVIC_SYSTICK_CTRL_REG register to ensure the
@ -534,16 +544,16 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrupts enabled. */ /* Exit with interrupts enabled. */
__asm volatile( "cpsie i" ::: "memory" ); __asm volatile ( "cpsie i" ::: "memory" );
} }
} }
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
{ {
/* Calculate the constants required to configure the tick interrupt. */ /* Calculate the constants required to configure the tick interrupt. */
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
{ {
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
@ -563,7 +573,7 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNC
static void prvTaskExitError( void ) static void prvTaskExitError( void )
{ {
volatile uint32_t ulDummy = 0UL; volatile uint32_t ulDummy = 0UL;
/* A function that implements a task must not exit or attempt to return to /* 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 * its caller as there is nothing to return to. If a task wants to exit it
@ -586,10 +596,11 @@ volatile uint32_t ulDummy = 0UL;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */ static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */
{ {
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -600,7 +611,7 @@ volatile uint32_t ulDummy = 0UL;
extern uint32_t * __unprivileged_flash_end__; extern uint32_t * __unprivileged_flash_end__;
extern uint32_t * __privileged_sram_start__; extern uint32_t * __privileged_sram_start__;
extern uint32_t * __privileged_sram_end__; extern uint32_t * __privileged_sram_end__;
#else #else /* if defined( __ARMCC_VERSION ) */
/* Declaration when these variable are exported from linker scripts. */ /* Declaration when these variable are exported from linker scripts. */
extern uint32_t __privileged_functions_start__[]; extern uint32_t __privileged_functions_start__[];
extern uint32_t __privileged_functions_end__[]; extern uint32_t __privileged_functions_end__[];
@ -671,10 +682,10 @@ volatile uint32_t ulDummy = 0UL;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */ static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */
{ {
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
{ {
/* Enable non-secure access to the FPU. */ /* Enable non-secure access to the FPU. */
SecureInit_EnableNSFPUAccess(); SecureInit_EnableNSFPUAccess();
@ -703,8 +714,8 @@ void vPortYield( void ) /* PRIVILEGED_FUNCTION */
/* Barriers are normally not required but do ensure the code is /* Barriers are normally not required but do ensure the code is
* completely within the specified behaviour for the architecture. */ * completely within the specified behaviour for the architecture. */
__asm volatile( "dsb" ::: "memory" ); __asm volatile ( "dsb" ::: "memory" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -715,8 +726,8 @@ void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
/* Barriers are normally not required but do ensure the code is /* Barriers are normally not required but do ensure the code is
* completely within the specified behaviour for the architecture. */ * completely within the specified behaviour for the architecture. */
__asm volatile( "dsb" ::: "memory" ); __asm volatile ( "dsb" ::: "memory" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -734,7 +745,7 @@ void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */ void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
{ {
uint32_t ulPreviousMask; uint32_t ulPreviousMask;
ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
{ {
@ -749,10 +760,11 @@ uint32_t ulPreviousMask;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */
{ {
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -762,33 +774,33 @@ void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) /* PRIVILEGED_FUNCTION
extern uint32_t __syscalls_flash_start__[]; extern uint32_t __syscalls_flash_start__[];
extern uint32_t __syscalls_flash_end__[]; extern uint32_t __syscalls_flash_end__[];
#endif /* defined( __ARMCC_VERSION ) */ #endif /* defined( __ARMCC_VERSION ) */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
uint32_t ulPC; uint32_t ulPC;
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
uint32_t ulR0; uint32_t ulR0;
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
uint32_t ulControl, ulIsTaskPrivileged; uint32_t ulControl, ulIsTaskPrivileged;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
uint8_t ucSVCNumber; uint8_t ucSVCNumber;
/* Register are stored on the stack in the following order - R0, R1, R2, R3, /* Register are stored on the stack in the following order - R0, R1, R2, R3,
* R12, LR, PC, xPSR. */ * R12, LR, PC, xPSR. */
ulPC = pulCallerStackAddress[ 6 ]; ulPC = pulCallerStackAddress[ 6 ];
ucSVCNumber = ( ( uint8_t *) ulPC )[ -2 ]; ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ];
switch( ucSVCNumber ) switch( ucSVCNumber )
{ {
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
case portSVC_ALLOCATE_SECURE_CONTEXT: case portSVC_ALLOCATE_SECURE_CONTEXT:
{
/* R0 contains the stack size passed as parameter to the /* R0 contains the stack size passed as parameter to the
* vPortAllocateSecureContext function. */ * vPortAllocateSecureContext function. */
ulR0 = pulCallerStackAddress[ 0 ]; ulR0 = pulCallerStackAddress[ 0 ];
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
/* Read the CONTROL register value. */ /* Read the CONTROL register value. */
__asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
@ -800,7 +812,7 @@ uint8_t ucSVCNumber;
/* Allocate and load a context for the secure task. */ /* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged ); xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
} }
#else #else /* if ( configENABLE_MPU == 1 ) */
{ {
/* Allocate and load a context for the secure task. */ /* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0 ); xSecureContext = SecureContext_AllocateContext( ulR0 );
@ -809,23 +821,19 @@ uint8_t ucSVCNumber;
configASSERT( xSecureContext != NULL ); configASSERT( xSecureContext != NULL );
SecureContext_LoadContext( xSecureContext ); SecureContext_LoadContext( xSecureContext );
}
break; break;
case portSVC_FREE_SECURE_CONTEXT: case portSVC_FREE_SECURE_CONTEXT:
{
/* R0 contains the secure context handle to be freed. */ /* R0 contains the secure context handle to be freed. */
ulR0 = pulCallerStackAddress[ 0 ]; ulR0 = pulCallerStackAddress[ 0 ];
/* Free the secure context. */ /* Free the secure context. */
SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 ); SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 );
}
break; break;
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
case portSVC_START_SCHEDULER: case portSVC_START_SCHEDULER:
{ #if ( configENABLE_TRUSTZONE == 1 )
#if( configENABLE_TRUSTZONE == 1 )
{ {
/* De-prioritize the non-secure exceptions so that the /* De-prioritize the non-secure exceptions so that the
* non-secure pendSV runs at the lowest priority. */ * non-secure pendSV runs at the lowest priority. */
@ -836,7 +844,7 @@ uint8_t ucSVCNumber;
} }
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
#if( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
{ {
/* Setup the Floating Point Unit (FPU). */ /* Setup the Floating Point Unit (FPU). */
prvSetupFPU(); prvSetupFPU();
@ -846,41 +854,44 @@ uint8_t ucSVCNumber;
/* Setup the context of the first task so that the first task starts /* Setup the context of the first task so that the first task starts
* executing. */ * executing. */
vRestoreContextOfFirstTask(); vRestoreContextOfFirstTask();
}
break; break;
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
case portSVC_RAISE_PRIVILEGE: case portSVC_RAISE_PRIVILEGE:
{
/* Only raise the privilege, if the svc was raised from any of /* Only raise the privilege, if the svc was raised from any of
* the system calls. */ * the system calls. */
if( ulPC >= ( uint32_t ) __syscalls_flash_start__ && if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
ulPC <= ( uint32_t ) __syscalls_flash_end__ ) ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
{ {
vRaisePrivilege(); vRaisePrivilege();
} }
}
break; break;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
default: default:
{
/* Incorrect SVC call. */ /* Incorrect SVC call. */
configASSERT( pdFALSE ); configASSERT( pdFALSE );
} }
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
#else #else
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters ) /* PRIVILEGED_FUNCTION */ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters ) /* PRIVILEGED_FUNCTION */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
{ {
/* Simulate the stack frame as it would be created by a context switch /* Simulate the stack frame as it would be created by a context switch
* interrupt. */ * interrupt. */
#if( portPRELOAD_REGISTERS == 0 ) #if ( portPRELOAD_REGISTERS == 0 )
{ {
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */ *pxTopOfStack = portINITIAL_XPSR; /* xPSR */
@ -893,9 +904,10 @@ uint8_t ucSVCNumber;
pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */ pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
*pxTopOfStack = portINITIAL_EXC_RETURN; *pxTopOfStack = portINITIAL_EXC_RETURN;
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
pxTopOfStack--; pxTopOfStack--;
if( xRunPrivileged == pdTRUE ) if( xRunPrivileged == pdTRUE )
{ {
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */ *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
@ -910,7 +922,7 @@ uint8_t ucSVCNumber;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
{ {
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
@ -954,9 +966,10 @@ uint8_t ucSVCNumber;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */ *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
pxTopOfStack--; pxTopOfStack--;
if( xRunPrivileged == pdTRUE ) if( xRunPrivileged == pdTRUE )
{ {
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */ *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
@ -971,7 +984,7 @@ uint8_t ucSVCNumber;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
{ {
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
@ -990,7 +1003,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
/* Setup the Memory Protection Unit (MPU). */ /* Setup the Memory Protection Unit (MPU). */
prvSetupMPU(); prvSetupMPU();
@ -1029,8 +1042,11 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth ) void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
const struct xMEMORY_REGION * const xRegions,
StackType_t * pxBottomOfStack,
uint32_t ulStackDepth )
{ {
uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber; uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber;
int32_t lIndex = 0; int32_t lIndex = 0;
@ -1126,13 +1142,13 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xPortIsInsideInterrupt( void ) BaseType_t xPortIsInsideInterrupt( void )
{ {
uint32_t ulCurrentInterrupt; uint32_t ulCurrentInterrupt;
BaseType_t xReturn; BaseType_t xReturn;
/* Obtain the number of the currently executing interrupt. Interrupt Program /* Obtain the number of the currently executing interrupt. Interrupt Program
* Status Register (IPSR) holds the exception number of the currently-executing * Status Register (IPSR) holds the exception number of the currently-executing
* exception or zero for Thread mode.*/ * exception or zero for Thread mode.*/
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" ); __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" );
if( ulCurrentInterrupt == 0 ) if( ulCurrentInterrupt == 0 )
{ {

View file

@ -38,7 +38,7 @@
* header files. */ * header files. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#if( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0. #error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
#endif #endif
@ -48,80 +48,80 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst2 \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r3, [r2] \n" /* Read 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. */ " ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n" /* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r5, #1 \n" /* r5 = 1. */ " movs r5, #1 \n"/* r5 = 1. */
" bics r4, r5 \n" /* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */ " bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n" /* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ " 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 r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const2 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n" /* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n" /* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
" movs r5, #4 \n" /* r5 = 4. */ " movs r5, #4 \n"/* r5 = 4. */
" str r5, [r2] \n" /* Program RNR = 4. */ " str r5, [r2] \n"/* Program RNR = 4. */
" ldmia r3!, {r6,r7} \n" /* Read first set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst2 \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n" /* Write first set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
" movs r5, #5 \n" /* r5 = 5. */ " movs r5, #5 \n"/* r5 = 5. */
" str r5, [r2] \n" /* Program RNR = 5. */ " str r5, [r2] \n"/* Program RNR = 5. */
" ldmia r3!, {r6,r7} \n" /* Read second set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst2 \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n" /* Write second set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
" movs r5, #6 \n" /* r5 = 6. */ " movs r5, #6 \n"/* r5 = 6. */
" str r5, [r2] \n" /* Program RNR = 6. */ " str r5, [r2] \n"/* Program RNR = 6. */
" ldmia r3!, {r6,r7} \n" /* Read third set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst2 \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n" /* Write third set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
" movs r5, #7 \n" /* r5 = 7. */ " movs r5, #7 \n"/* r5 = 7. */
" str r5, [r2] \n" /* Program RNR = 7. */ " str r5, [r2] \n"/* Program RNR = 7. */
" ldmia r3!, {r6,r7} \n" /* Read fourth set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst2 \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n" /* Write fourth set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
" \n" " \n"
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r5, #1 \n" /* r5 = 1. */ " movs r5, #1 \n"/* r5 = 1. */
" orrs r4, r5 \n" /* r4 = r4 | r5 i.e. Set the bit 0 in r4. */ " orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n" /* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n" /* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r4} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */ " ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
" ldr r5, xSecureContextConst2 \n" " ldr r5, xSecureContextConst2 \n"
" str r1, [r5] \n" /* Set xSecureContext to this task's value for the same. */ " 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 psplim, r2 \n"/* Set this task's PSPLIM value. */
" msr control, r3 \n" /* Set this task's CONTROL value. */ " msr control, r3 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n" /* Discard everything up to r0. */ " 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. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r4 \n" /* Finally, branch to EXC_RETURN. */ " bx r4 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
" ldr r4, xSecureContextConst2 \n" " ldr r4, xSecureContextConst2 \n"
" str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */ " str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */
" msr psplim, r2 \n" /* Set this task's PSPLIM value. */ " msr psplim, r2 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n" /* r1 = 2. */ " movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */ " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n" /* Discard everything up to r0. */ " 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. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r3 \n" /* Finally, branch to EXC_RETURN. */ " bx r3 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
"xSecureContextConst2: .word xSecureContext \n" "xSecureContextConst2: .word xSecureContext \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n" "xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n" "xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n" "xRNRConst2: .word 0xe000ed98 \n"
@ -135,15 +135,15 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n" /* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" movs r1, #1 \n" /* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" tst r0, r1 \n" /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */ " tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
" beq running_privileged \n" /* If the result of previous AND operation was 0, branch. */ " beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */
" movs r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
" running_privileged: \n" " running_privileged: \n"
" movs r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ " movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
@ -155,11 +155,11 @@ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n" /* Read the CONTROL register. */ " mrs r0, control \n"/* Read the CONTROL register. */
" movs r1, #1 \n" /* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" bics r0, r1 \n" /* Clear the bit 0. */ " bics r0, r1 \n"/* Clear the bit 0. */
" msr control, r0 \n" /* Write back the new CONTROL value. */ " msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n" /* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
@ -169,12 +169,12 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n" /* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" movs r1, #1 \n" /* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" orrs r0, r1 \n" /* r0 = r0 | r1. */ " orrs r0, r1 \n"/* r0 = r0 | r1. */
" msr control, r0 \n" /* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n" /* Return to the caller. */ " bx lr \n"/* Return to the caller. */
:::"r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -183,19 +183,19 @@ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" ldr r0, xVTORConst \n" /* Use the NVIC offset register to locate the stack. */ " 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"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */ " 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. */ " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n" /* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n" /* System call to start the first task. */ " svc %0 \n"/* System call to start the first task. */
" nop \n" " nop \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n" "xVTORConst: .word 0xe000ed08 \n"
:: "i" ( portSVC_START_SCHEDULER ) : "memory" ::"i" ( portSVC_START_SCHEDULER ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -231,64 +231,64 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
" .extern SecureContext_SaveContext \n" " .extern SecureContext_SaveContext \n"
" .extern SecureContext_LoadContext \n" " .extern SecureContext_LoadContext \n"
" \n" " \n"
" mrs r1, psp \n" /* Read PSP in r1. */ " mrs r1, psp \n"/* Read PSP in r1. */
" ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ " 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. */ " ldr r0, [r2] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
" \n" " \n"
" cbz r0, save_ns_context \n" /* No secure context to save. */ " cbz r0, save_ns_context \n"/* No secure context to save. */
" push {r0-r2, r14} \n" " push {r0-r2, r14} \n"
" bl SecureContext_SaveContext \n" " bl SecureContext_SaveContext \n"
" pop {r0-r3} \n" /* LR is now in r3. */ " pop {r0-r3} \n"/* LR is now in r3. */
" mov lr, r3 \n" /* LR = 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. */ " 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. */ " 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 r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r2, [r3] \n" /* Read pxCurrentTCB. */ " ldr r2, [r3] \n"/* Read pxCurrentTCB. */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r1, r1, #16 \n" /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " 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. */ " str r1, [r2] \n"/* Save the new top of stack in TCB. */
" mrs r2, psplim \n" /* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mrs r3, control \n" /* r3 = CONTROL. */ " mrs r3, control \n"/* r3 = CONTROL. */
" mov r4, lr \n" /* r4 = LR/EXC_RETURN. */ " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
" stmia r1!, {r0, r2-r4} \n" /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " stmia r1!, {r0, r2-r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r1, r1, #12 \n" /* Make space for xSecureContext, PSPLIM and LR on the stack. */ " 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. */ " str r1, [r2] \n"/* Save the new top of stack in TCB. */
" mrs r2, psplim \n" /* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r1!, {r0, r2-r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */ " stmia r1!, {r0, r2-r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" b select_next_task \n" " b select_next_task \n"
" \n" " \n"
" save_ns_context: \n" " save_ns_context: \n"
" ldr r3, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r2, [r3] \n" /* Read pxCurrentTCB. */ " ldr r2, [r3] \n"/* Read pxCurrentTCB. */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r1, r1, #48 \n" /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */ " 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. */ " str r1, [r2] \n"/* Save the new top of stack in TCB. */
" adds r1, r1, #16 \n" /* r1 = r1 + 16. */ " adds r1, r1, #16 \n"/* r1 = r1 + 16. */
" stmia r1!, {r4-r7} \n" /* Store the low registers that are not saved automatically. */ " stmia r1!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */
" mov r4, r8 \n" /* r4 = r8. */ " mov r4, r8 \n"/* r4 = r8. */
" mov r5, r9 \n" /* r5 = r9. */ " mov r5, r9 \n"/* r5 = r9. */
" mov r6, r10 \n" /* r6 = r10. */ " mov r6, r10 \n"/* r6 = r10. */
" mov r7, r11 \n" /* r7 = r11. */ " mov r7, r11 \n"/* r7 = r11. */
" stmia r1!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */ " stmia r1!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
" mrs r2, psplim \n" /* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mrs r3, control \n" /* r3 = CONTROL. */ " mrs r3, control \n"/* r3 = CONTROL. */
" mov r4, lr \n" /* r4 = LR/EXC_RETURN. */ " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
" subs r1, r1, #48 \n" /* r1 = r1 - 48. */ " subs r1, r1, #48 \n"/* r1 = r1 - 48. */
" stmia r1!, {r0, r2-r4} \n" /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " stmia r1!, {r0, r2-r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r1, r1, #44 \n" /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ " 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. */ " str r1, [r2] \n"/* Save the new top of stack in TCB. */
" mrs r2, psplim \n" /* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r1!, {r0, r2-r7} \n" /* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */ " stmia r1!, {r0, r2-r7} \n"/* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */
" mov r4, r8 \n" /* r4 = r8. */ " mov r4, r8 \n"/* r4 = r8. */
" mov r5, r9 \n" /* r5 = r9. */ " mov r5, r9 \n"/* r5 = r9. */
" mov r6, r10 \n" /* r6 = r10. */ " mov r6, r10 \n"/* r6 = r10. */
" mov r7, r11 \n" /* r7 = r11. */ " mov r7, r11 \n"/* r7 = r11. */
" stmia r1!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */ " stmia r1!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
@ -296,102 +296,102 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" cpsie i \n" " cpsie i \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r3, [r2] \n" /* Read 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. */ " ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. r1 now points to the top of stack. */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n" /* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r5, #1 \n" /* r5 = 1. */ " movs r5, #1 \n"/* r5 = 1. */
" bics r4, r5 \n" /* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */ " bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n" /* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ " 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 r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n" /* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst \n" /* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
" movs r5, #4 \n" /* r5 = 4. */ " movs r5, #4 \n"/* r5 = 4. */
" str r5, [r2] \n" /* Program RNR = 4. */ " str r5, [r2] \n"/* Program RNR = 4. */
" ldmia r3!, {r6,r7} \n" /* Read first set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n" /* Write first set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
" movs r5, #5 \n" /* r5 = 5. */ " movs r5, #5 \n"/* r5 = 5. */
" str r5, [r2] \n" /* Program RNR = 5. */ " str r5, [r2] \n"/* Program RNR = 5. */
" ldmia r3!, {r6,r7} \n" /* Read second set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n" /* Write second set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
" movs r5, #6 \n" /* r5 = 6. */ " movs r5, #6 \n"/* r5 = 6. */
" str r5, [r2] \n" /* Program RNR = 6. */ " str r5, [r2] \n"/* Program RNR = 6. */
" ldmia r3!, {r6,r7} \n" /* Read third set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n" /* Write third set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
" movs r5, #7 \n" /* r5 = 7. */ " movs r5, #7 \n"/* r5 = 7. */
" str r5, [r2] \n" /* Program RNR = 7. */ " str r5, [r2] \n"/* Program RNR = 7. */
" ldmia r3!, {r6,r7} \n" /* Read fourth set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n" /* Write fourth set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
" \n" " \n"
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r5, #1 \n" /* r5 = 1. */ " movs r5, #1 \n"/* r5 = 1. */
" orrs r4, r5 \n" /* r4 = r4 | r5 i.e. Set the bit 0 in r4. */ " orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n" /* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n" /* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldmia r1!, {r0, r2-r4} \n" /* Read from stack - r0 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = LR. */ " 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 psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r3 \n" /* Restore the CONTROL register value for the task. */ " msr control, r3 \n"/* Restore the CONTROL register value for the task. */
" mov lr, r4 \n" /* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r2] \n" /* Restore the task's 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. */ " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
" push {r1,r4} \n" " push {r1,r4} \n"
" bl SecureContext_LoadContext \n" /* Restore the secure context. */ " bl SecureContext_LoadContext \n"/* Restore the secure context. */
" pop {r1,r4} \n" " pop {r1,r4} \n"
" mov lr, r4 \n" /* LR = r4. */ " 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. */ " 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. */ " 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. */ " msr psp, r1 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldmia r1!, {r0, r2-r3} \n" /* Read from stack - r0 = xSecureContext, r2 = PSPLIM and r3 = LR. */ " 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. */ " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
" mov lr, r3 \n" /* LR = r3. */ " mov lr, r3 \n"/* LR = r3. */
" ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r2] \n" /* Restore the task's 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. */ " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
" push {r1,r3} \n" " push {r1,r3} \n"
" bl SecureContext_LoadContext \n" /* Restore the secure context. */ " bl SecureContext_LoadContext \n"/* Restore the secure context. */
" pop {r1,r3} \n" " pop {r1,r3} \n"
" mov lr, r3 \n" /* LR = 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. */ " 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. */ " 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. */ " msr psp, r1 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" restore_ns_context: \n" " restore_ns_context: \n"
" adds r1, r1, #16 \n" /* Move to the high registers. */ " adds r1, r1, #16 \n"/* Move to the high registers. */
" ldmia r1!, {r4-r7} \n" /* Restore the high registers that are not automatically restored. */ " ldmia r1!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
" mov r8, r4 \n" /* r8 = r4. */ " mov r8, r4 \n"/* r8 = r4. */
" mov r9, r5 \n" /* r9 = r5. */ " mov r9, r5 \n"/* r9 = r5. */
" mov r10, r6 \n" /* r10 = r6. */ " mov r10, r6 \n"/* r10 = r6. */
" mov r11, r7 \n" /* r11 = r7. */ " mov r11, r7 \n"/* r11 = r7. */
" msr psp, r1 \n" /* Remember the new top of stack for the task. */ " msr psp, r1 \n"/* Remember the new top of stack for the task. */
" subs r1, r1, #32 \n" /* Go back to the low registers. */ " subs r1, r1, #32 \n"/* Go back to the low registers. */
" ldmia r1!, {r4-r7} \n" /* Restore the low registers that are not automatically restored. */ " ldmia r1!, {r4-r7} \n"/* Restore the low registers that are not automatically restored. */
" bx lr \n" " bx lr \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
"xSecureContextConst: .word xSecureContext \n" "xSecureContextConst: .word xSecureContext \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n" "xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n" "xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n" "xRNRConst: .word 0xe000ed98 \n"
@ -427,26 +427,26 @@ void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (
{ {
__asm volatile __asm volatile
( (
" svc %0 \n" /* Secure context is allocated in the supervisor call. */ " svc %0 \n"/* Secure context is allocated in the supervisor call. */
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
:: "i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory" ::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" ldr r1, [r0] \n" /* The first item in the TCB is the top of the stack. */ " 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. */ " 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. */ " cmp r0, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */
" beq free_secure_context \n" " beq free_secure_context \n"
" bx lr \n" /* There is no secure context (xSecureContext is NULL). */ " bx lr \n"/* There is no secure context (xSecureContext is NULL). */
" free_secure_context: \n" " free_secure_context: \n"
" svc %0 \n" /* Secure context is freed in the supervisor call. */ " svc %0 \n"/* Secure context is freed in the supervisor call. */
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
:: "i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory" ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -37,14 +37,14 @@
* @brief Restore the context of the first task so that the first task starts * @brief Restore the context of the first task so that the first task starts
* executing. * executing.
*/ */
void vRestoreContextOfFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; void vRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/** /**
* @brief Checks whether or not the processor is privileged. * @brief Checks whether or not the processor is privileged.
* *
* @return 1 if the processor is already privileged, 0 otherwise. * @return 1 if the processor is already privileged, 0 otherwise.
*/ */
BaseType_t xIsPrivileged( void ) __attribute__ (( naked )); BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) );
/** /**
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL * @brief Raises the privilege level by clearing the bit 0 of the CONTROL
@ -57,7 +57,7 @@ BaseType_t xIsPrivileged( void ) __attribute__ (( naked ));
* Bit[0] = 0 --> The processor is running privileged * Bit[0] = 0 --> The processor is running privileged
* Bit[0] = 1 --> The processor is running unprivileged. * Bit[0] = 1 --> The processor is running unprivileged.
*/ */
void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/** /**
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL * @brief Lowers the privilege level by setting the bit 0 of the CONTROL
@ -67,32 +67,32 @@ void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
* Bit[0] = 0 --> The processor is running privileged * Bit[0] = 0 --> The processor is running privileged
* Bit[0] = 1 --> The processor is running unprivileged. * Bit[0] = 1 --> The processor is running unprivileged.
*/ */
void vResetPrivilege( void ) __attribute__ (( naked )); void vResetPrivilege( void ) __attribute__( ( naked ) );
/** /**
* @brief Starts the first task. * @brief Starts the first task.
*/ */
void vStartFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/** /**
* @brief Disables interrupts. * @brief Disables interrupts.
*/ */
uint32_t ulSetInterruptMask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION; uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/** /**
* @brief Enables interrupts. * @brief Enables interrupts.
*/ */
void vClearInterruptMask( uint32_t ulMask ) __attribute__(( naked )) PRIVILEGED_FUNCTION; void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/** /**
* @brief PendSV Exception handler. * @brief PendSV Exception handler.
*/ */
void PendSV_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/** /**
* @brief SVC Handler. * @brief SVC Handler.
*/ */
void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/** /**
* @brief Allocate a Secure context for the calling task. * @brief Allocate a Secure context for the calling task.
@ -100,13 +100,13 @@ void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
* @param[in] ulSecureStackSize The size of the stack to be allocated on the * @param[in] ulSecureStackSize The size of the stack to be allocated on the
* secure side for the calling task. * secure side for the calling task.
*/ */
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__ (( naked )); void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__( ( naked ) );
/** /**
* @brief Free the task's secure context. * @brief Free the task's secure context.
* *
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task. * @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
*/ */
void vPortFreeSecureContext( uint32_t *pulTCB ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
#endif /* __PORT_ASM_H__ */ #endif /* __PORT_ASM_H__ */

View file

@ -25,11 +25,11 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -41,109 +41,109 @@ extern "C" {
*------------------------------------------------------------------------------ *------------------------------------------------------------------------------
*/ */
#ifndef configENABLE_FPU #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. #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 */ #endif /* configENABLE_FPU */
#ifndef configENABLE_MPU #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. #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 */ #endif /* configENABLE_MPU */
#ifndef configENABLE_TRUSTZONE #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. #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 */ #endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Type definitions. * @brief Type definitions.
*/ */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 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. */ * not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* Architecture specifics. * Architecture specifics.
*/ */
#define portARCH_NAME "Cortex-M23" #define portARCH_NAME "Cortex-M23"
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portNOP() #define portNOP()
#define portINLINE __inline #define portINLINE __inline
#ifndef portFORCE_INLINE #ifndef portFORCE_INLINE
#define portFORCE_INLINE inline __attribute__(( always_inline )) #define portFORCE_INLINE inline __attribute__( ( always_inline ) )
#endif #endif
#define portHAS_STACK_OVERFLOW_CHECKING 1 #define portHAS_STACK_OVERFLOW_CHECKING 1
#define portDONT_DISCARD __attribute__(( used )) #define portDONT_DISCARD __attribute__( ( used ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Extern declarations. * @brief Extern declarations.
*/ */
extern BaseType_t xPortIsInsideInterrupt( void ); extern BaseType_t xPortIsInsideInterrupt( void );
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief MPU specific constants. * @brief MPU specific constants.
*/ */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
#define portUSING_MPU_WRAPPERS 1 #define portUSING_MPU_WRAPPERS 1
#define portPRIVILEGE_BIT ( 0x80000000UL ) #define portPRIVILEGE_BIT ( 0x80000000UL )
#else #else
#define portPRIVILEGE_BIT ( 0x0UL ) #define portPRIVILEGE_BIT ( 0x0UL )
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/* MPU regions. */ /* MPU regions. */
#define portPRIVILEGED_FLASH_REGION ( 0UL ) #define portPRIVILEGED_FLASH_REGION ( 0UL )
#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) #define portUNPRIVILEGED_FLASH_REGION ( 1UL )
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
#define portPRIVILEGED_RAM_REGION ( 3UL ) #define portPRIVILEGED_RAM_REGION ( 3UL )
#define portSTACK_REGION ( 4UL ) #define portSTACK_REGION ( 4UL )
#define portFIRST_CONFIGURABLE_REGION ( 5UL ) #define portFIRST_CONFIGURABLE_REGION ( 5UL )
#define portLAST_CONFIGURABLE_REGION ( 7UL ) #define portLAST_CONFIGURABLE_REGION ( 7UL )
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) #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 portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
/* Device memory attributes used in MPU_MAIR registers. /* Device memory attributes used in MPU_MAIR registers.
* *
@ -155,95 +155,96 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
* 11 --> Device-GRE * 11 --> Device-GRE
* Bit[1:0] - 00, Reserved. * Bit[1:0] - 00, Reserved.
*/ */
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
/* Normal memory attributes used in MPU_MAIR registers. */ /* Normal memory attributes used in MPU_MAIR registers. */
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ #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. */ #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
/* Attributes used in MPU_RBAR registers. */ /* Attributes used in MPU_RBAR registers. */
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) #define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) #define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) #define portMPU_REGION_EXECUTE_NEVER ( 1UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Settings to define an MPU region. * @brief Settings to define an MPU region.
*/ */
typedef struct MPURegionSettings typedef struct MPURegionSettings
{ {
uint32_t ulRBAR; /**< RBAR for the region. */ uint32_t ulRBAR; /**< RBAR for the region. */
uint32_t ulRLAR; /**< RLAR for the region. */ uint32_t ulRLAR; /**< RLAR for the region. */
} MPURegionSettings_t; } MPURegionSettings_t;
/** /**
* @brief MPU settings as stored in the TCB. * @brief MPU settings as stored in the TCB.
*/ */
typedef struct MPU_SETTINGS typedef struct MPU_SETTINGS
{ {
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ 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. */ MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
} xMPU_SETTINGS; } xMPU_SETTINGS;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief SVC numbers. * @brief SVC numbers.
*/ */
#define portSVC_ALLOCATE_SECURE_CONTEXT 0 #define portSVC_ALLOCATE_SECURE_CONTEXT 0
#define portSVC_FREE_SECURE_CONTEXT 1 #define portSVC_FREE_SECURE_CONTEXT 1
#define portSVC_START_SCHEDULER 2 #define portSVC_START_SCHEDULER 2
#define portSVC_RAISE_PRIVILEGE 3 #define portSVC_RAISE_PRIVILEGE 3
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Scheduler utilities. * @brief Scheduler utilities.
*/ */
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Critical section management. * @brief Critical section management.
*/ */
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMask( x ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) #define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) #define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Tickless idle/low power functionality. * @brief Tickless idle/low power functionality.
*/ */
#ifndef portSUPPRESS_TICKS_AND_SLEEP #ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Task function macros as described on the FreeRTOS.org WEB site. * @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_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/**
/**
* @brief Allocate a secure context for the task. * @brief Allocate a secure context for the task.
* *
* Tasks are not created with a secure context. Any task that is going to call * Tasks are not created with a secure context. Any task that is going to call
@ -254,56 +255,57 @@ typedef struct MPU_SETTINGS
*/ */
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
/** /**
* @brief Called when a task is deleted to delete the task's secure context, * @brief Called when a task is deleted to delete the task's secure context,
* if it has one. * if it has one.
* *
* @param[in] pxTCB The TCB of the task being deleted. * @param[in] pxTCB The TCB of the task being deleted.
*/ */
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
#else #else
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
#define portCLEAN_UP_TCB( pxTCB ) #define portCLEAN_UP_TCB( pxTCB )
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/**
/**
* @brief Checks whether or not the processor is privileged. * @brief Checks whether or not the processor is privileged.
* *
* @return 1 if the processor is already privileged, 0 otherwise. * @return 1 if the processor is already privileged, 0 otherwise.
*/ */
#define portIS_PRIVILEGED() xIsPrivileged() #define portIS_PRIVILEGED() xIsPrivileged()
/** /**
* @brief Raise an SVC request to raise privilege. * @brief Raise an SVC request to raise privilege.
* *
* The SVC handler checks that the SVC was raised from a system call and only * 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, * then it raises the privilege. If this is called from any other place,
* the privilege is not raised. * the privilege is not raised.
*/ */
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); #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 * @brief Lowers the privilege level by setting the bit 0 of the CONTROL
* register. * register.
*/ */
#define portRESET_PRIVILEGE() vResetPrivilege() #define portRESET_PRIVILEGE() vResetPrivilege()
#else #else
#define portIS_PRIVILEGED() #define portIS_PRIVILEGED()
#define portRAISE_PRIVILEGE() #define portRAISE_PRIVILEGE()
#define portRESET_PRIVILEGE() #define portRESET_PRIVILEGE()
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
* @brief Barriers. * @brief Barriers.
*/ */
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -58,9 +58,9 @@
*/ */
typedef struct SecureContext typedef struct SecureContext
{ {
uint8_t *pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */ uint8_t * pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
uint8_t *pucStackLimit; /**< Last location of the stack memory (PSPLIM). */ uint8_t * pucStackLimit; /**< Last location of the stack memory (PSPLIM). */
uint8_t *pucStackStart; /**< First location of the stack memory. */ uint8_t * pucStackStart; /**< First location of the stack memory. */
} SecureContext_t; } SecureContext_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -79,7 +79,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
secureportSET_PSPLIM( securecontextNO_STACK ); secureportSET_PSPLIM( securecontextNO_STACK );
secureportSET_PSP( securecontextNO_STACK ); secureportSET_PSP( securecontextNO_STACK );
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
/* Configure thread mode to use PSP and to be unprivileged. */ /* Configure thread mode to use PSP and to be unprivileged. */
secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED ); secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );
@ -94,17 +94,19 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged ) secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
uint32_t ulIsTaskPrivileged )
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize ) secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize )
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
{ {
uint8_t *pucStackMemory = NULL; uint8_t * pucStackMemory = NULL;
uint32_t ulIPSR; uint32_t ulIPSR;
SecureContextHandle_t xSecureContextHandle = NULL; SecureContextHandle_t xSecureContextHandle = NULL;
#if( configENABLE_MPU == 1 )
uint32_t *pulCurrentStackPointer = NULL; #if ( configENABLE_MPU == 1 )
uint32_t * pulCurrentStackPointer = NULL;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/* Read the Interrupt Program Status Register (IPSR) value. */ /* Read the Interrupt Program Status Register (IPSR) value. */
@ -136,13 +138,14 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
* programmed in the PSPLIM register on context switch.*/ * programmed in the PSPLIM register on context switch.*/
xSecureContextHandle->pucStackLimit = pucStackMemory; xSecureContextHandle->pucStackLimit = pucStackMemory;
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
/* Store the correct CONTROL value for the task on the stack. /* Store the correct CONTROL value for the task on the stack.
* This value is programmed in the CONTROL register on * This value is programmed in the CONTROL register on
* context switch. */ * context switch. */
pulCurrentStackPointer = ( uint32_t * ) xSecureContextHandle->pucStackStart; pulCurrentStackPointer = ( uint32_t * ) xSecureContextHandle->pucStackStart;
pulCurrentStackPointer--; pulCurrentStackPointer--;
if( ulIsTaskPrivileged ) if( ulIsTaskPrivileged )
{ {
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED; *( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
@ -161,7 +164,6 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
/* Current SP is set to the starting of the stack. This /* Current SP is set to the starting of the stack. This
* value programmed in the PSP register on context switch. */ * value programmed in the PSP register on context switch. */
xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart; xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart;
} }
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
} }

View file

@ -42,7 +42,7 @@
* @brief Opaque handle. * @brief Opaque handle.
*/ */
struct SecureContext; struct SecureContext;
typedef struct SecureContext* SecureContextHandle_t; typedef struct SecureContext * SecureContextHandle_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -68,8 +68,9 @@ void SecureContext_Init( void );
* @return Opaque context handle if context is successfully allocated, NULL * @return Opaque context handle if context is successfully allocated, NULL
* otherwise. * otherwise.
*/ */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged ); SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
uint32_t ulIsTaskPrivileged );
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize ); SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize );
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */

View file

@ -30,7 +30,7 @@
/* Secure port macros. */ /* Secure port macros. */
#include "secure_port_macros.h" #include "secure_port_macros.h"
#if( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0. #error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
#endif #endif
@ -41,20 +41,20 @@ secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandl
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r1, ipsr \n" /* r1 = IPSR. */ " mrs r1, ipsr \n"/* r1 = IPSR. */
" cbz r1, load_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */ " 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. */ " ldmia r0!, {r1, r2} \n"/* r1 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldmia r1!, {r3} \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */ " ldmia r1!, {r3} \n"/* Read CONTROL register value from task's stack. r3 = CONTROL. */
" msr control, r3 \n" /* CONTROL = r3. */ " msr control, r3 \n"/* CONTROL = r3. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" msr psplim, r2 \n" /* PSPLIM = r2. */ " msr psplim, r2 \n"/* PSPLIM = r2. */
" msr psp, r1 \n" /* PSP = r1. */ " msr psp, r1 \n"/* PSP = r1. */
" \n" " \n"
" load_ctx_therad_mode: \n" " load_ctx_therad_mode: \n"
" nop \n" " nop \n"
" \n" " \n"
:::"r0", "r1", "r2" ::: "r0", "r1", "r2"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -66,25 +66,25 @@ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandl
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r1, ipsr \n" /* r1 = IPSR. */ " mrs r1, ipsr \n"/* r1 = IPSR. */
" cbz r1, save_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */ " cbz r1, save_ctx_therad_mode \n"/* Do nothing if the processor is running in the Thread Mode. */
" mrs r1, psp \n" /* r1 = PSP. */ " mrs r1, psp \n"/* r1 = PSP. */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" mrs r2, control \n" /* r2 = CONTROL. */ " mrs r2, control \n"/* r2 = CONTROL. */
" subs r1, r1, #4 \n" /* Make space for the CONTROL value on the stack. */ " subs r1, r1, #4 \n"/* Make space for the CONTROL value on the stack. */
" str r1, [r0] \n" /* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */ " str r1, [r0] \n"/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */
" stmia r1!, {r2} \n" /* Store CONTROL value on the stack. */ " stmia r1!, {r2} \n"/* Store CONTROL value on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" str r1, [r0] \n" /* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */ " str r1, [r0] \n"/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" movs r1, %0 \n" /* r1 = securecontextNO_STACK. */ " movs r1, %0 \n"/* r1 = securecontextNO_STACK. */
" msr psplim, r1 \n" /* PSPLIM = 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. */ " msr psp, r1 \n"/* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
" \n" " \n"
" save_ctx_therad_mode: \n" " save_ctx_therad_mode: \n"
" nop \n" " nop \n"
" \n" " \n"
:: "i" ( securecontextNO_STACK ) : "r1", "memory" ::"i" ( securecontextNO_STACK ) : "r1", "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -61,9 +61,10 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Allocate the memory for the heap. */ /* Allocate the memory for the heap. */
#if( configAPPLICATION_ALLOCATED_HEAP == 1 ) #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. */ /* 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 ]; extern uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
#else /* configAPPLICATION_ALLOCATED_HEAP */ #else /* configAPPLICATION_ALLOCATED_HEAP */
static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ]; static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
@ -76,7 +77,7 @@
*/ */
typedef struct A_BLOCK_LINK typedef struct A_BLOCK_LINK
{ {
struct A_BLOCK_LINK *pxNextFreeBlock; /**< The next free block in the list. */ struct A_BLOCK_LINK * pxNextFreeBlock; /**< The next free block in the list. */
size_t xBlockSize; /**< The size of the free block. */ size_t xBlockSize; /**< The size of the free block. */
} BlockLink_t; } BlockLink_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -96,7 +97,7 @@ static void prvHeapInit( void );
* *
* @param[in] pxBlockToInsert The block being freed. * @param[in] pxBlockToInsert The block being freed.
*/ */
static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ); static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -108,7 +109,7 @@ static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( s
/** /**
* @brief Create a couple of list links to mark the start and end of the list. * @brief Create a couple of list links to mark the start and end of the list.
*/ */
static BlockLink_t xStart, *pxEnd = NULL; static BlockLink_t xStart, * pxEnd = NULL;
/** /**
* @brief Keeps track of the number of free bytes remaining, but says nothing * @brief Keeps track of the number of free bytes remaining, but says nothing
@ -129,10 +130,10 @@ static size_t xBlockAllocatedBit = 0;
static void prvHeapInit( void ) static void prvHeapInit( void )
{ {
BlockLink_t *pxFirstFreeBlock; BlockLink_t * pxFirstFreeBlock;
uint8_t *pucAlignedHeap; uint8_t * pucAlignedHeap;
size_t uxAddress; size_t uxAddress;
size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE; size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
/* Ensure the heap starts on a correctly aligned boundary. */ /* Ensure the heap starts on a correctly aligned boundary. */
uxAddress = ( size_t ) ucHeap; uxAddress = ( size_t ) ucHeap;
@ -175,10 +176,10 @@ size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ) static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert )
{ {
BlockLink_t *pxIterator; BlockLink_t * pxIterator;
uint8_t *puc; uint8_t * puc;
/* Iterate through the list until a block is found that has a higher address /* Iterate through the list until a block is found that has a higher address
* than the block being inserted. */ * than the block being inserted. */
@ -190,6 +191,7 @@ uint8_t *puc;
/* Do the block being inserted, and the block it is being inserted after /* Do the block being inserted, and the block it is being inserted after
* make a contiguous block of memory? */ * make a contiguous block of memory? */
puc = ( uint8_t * ) pxIterator; puc = ( uint8_t * ) pxIterator;
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert ) if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
{ {
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize; pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
@ -203,6 +205,7 @@ uint8_t *puc;
/* Do the block being inserted, and the block it is being inserted before /* Do the block being inserted, and the block it is being inserted before
* make a contiguous block of memory? */ * make a contiguous block of memory? */
puc = ( uint8_t * ) pxBlockToInsert; puc = ( uint8_t * ) pxBlockToInsert;
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock ) if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
{ {
if( pxIterator->pxNextFreeBlock != pxEnd ) if( pxIterator->pxNextFreeBlock != pxEnd )
@ -236,10 +239,10 @@ uint8_t *puc;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void *pvPortMalloc( size_t xWantedSize ) void * pvPortMalloc( size_t xWantedSize )
{ {
BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; BlockLink_t * pxBlock, * pxPreviousBlock, * pxNewBlockLink;
void *pvReturn = NULL; void * pvReturn = NULL;
/* If this is the first call to malloc then the heap will require /* If this is the first call to malloc then the heap will require
* initialisation to setup the list of free blocks. */ * initialisation to setup the list of free blocks. */
@ -288,6 +291,7 @@ void *pvReturn = NULL;
* one of adequate size is found. */ * one of adequate size is found. */
pxPreviousBlock = &xStart; pxPreviousBlock = &xStart;
pxBlock = xStart.pxNextFreeBlock; pxBlock = xStart.pxNextFreeBlock;
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
{ {
pxPreviousBlock = pxBlock; pxPreviousBlock = pxBlock;
@ -363,7 +367,7 @@ void *pvReturn = NULL;
traceMALLOC( pvReturn, xWantedSize ); traceMALLOC( pvReturn, xWantedSize );
#if( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) #if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 )
{ {
if( pvReturn == NULL ) if( pvReturn == NULL )
{ {
@ -375,17 +379,17 @@ void *pvReturn = NULL;
mtCOVERAGE_TEST_MARKER(); mtCOVERAGE_TEST_MARKER();
} }
} }
#endif #endif /* if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) */
secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 ); secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
return pvReturn; return pvReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortFree( void *pv ) void vPortFree( void * pv )
{ {
uint8_t *puc = ( uint8_t * ) pv; uint8_t * puc = ( uint8_t * ) pv;
BlockLink_t *pxLink; BlockLink_t * pxLink;
if( pv != NULL ) if( pv != NULL )
{ {

View file

@ -38,13 +38,13 @@
* @return Pointer to the memory region if the allocation is successful, NULL * @return Pointer to the memory region if the allocation is successful, NULL
* otherwise. * otherwise.
*/ */
void *pvPortMalloc( size_t xWantedSize ); void * pvPortMalloc( size_t xWantedSize );
/** /**
* @brief Frees the previously allocated memory. * @brief Frees the previously allocated memory.
* *
* @param[in] pv Pointer to the memory to be freed. * @param[in] pv Pointer to the memory to be freed.
*/ */
void vPortFree( void *pv ); void vPortFree( void * pv );
#endif /* __SECURE_HEAP_H__ */ #endif /* __SECURE_HEAP_H__ */

View file

@ -93,7 +93,7 @@ secureportNON_SECURE_CALLABLE void SecureInit_EnableNSFPUAccess( void )
/* LSPENS = 0 ==> LSPEN is writable fron non-secure state. This ensures /* LSPENS = 0 ==> LSPEN is writable fron non-secure state. This ensures
* that we can enable/disable lazy stacking in port.c file. */ * that we can enable/disable lazy stacking in port.c file. */
*( secureinitFPCCR ) &= ~ ( secureinitFPCCR_LSPENS_MASK ); *( secureinitFPCCR ) &= ~( secureinitFPCCR_LSPENS_MASK );
/* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP /* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP
* registers (S16-S31) are also pushed to stack on exception entry and * registers (S16-S31) are also pushed to stack on exception entry and

View file

@ -39,7 +39,7 @@
#if defined( __IAR_SYSTEMS_ICC__ ) #if defined( __IAR_SYSTEMS_ICC__ )
#define secureportNON_SECURE_CALLABLE __cmse_nonsecure_entry __root #define secureportNON_SECURE_CALLABLE __cmse_nonsecure_entry __root
#else #else
#define secureportNON_SECURE_CALLABLE __attribute__((cmse_nonsecure_entry)) __attribute__((used)) #define secureportNON_SECURE_CALLABLE __attribute__( ( cmse_nonsecure_entry ) ) __attribute__( ( used ) )
#endif #endif
/** /**
@ -126,7 +126,7 @@
{ \ { \
secureportDISABLE_SECURE_INTERRUPTS(); \ secureportDISABLE_SECURE_INTERRUPTS(); \
secureportDISABLE_NON_SECURE_INTERRUPTS(); \ secureportDISABLE_NON_SECURE_INTERRUPTS(); \
for( ;; ); \ for( ; ; ) {; } \
} }
#endif /* __SECURE_PORT_MACROS_H__ */ #endif /* __SECURE_PORT_MACROS_H__ */

View file

@ -39,7 +39,7 @@
/* Portasm includes. */ /* Portasm includes. */
#include "portasm.h" #include "portasm.h"
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/* Secure components includes. */ /* Secure components includes. */
#include "secure_context.h" #include "secure_context.h"
#include "secure_init.h" #include "secure_init.h"
@ -62,7 +62,7 @@
* 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support: * 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 * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0
*/ */
#if( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) ) #if ( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) )
#error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side. #error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side.
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -70,10 +70,10 @@
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) #define portNVIC_SYSPRI2_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) #define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) #define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) #define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
@ -85,7 +85,8 @@
/* Ensure the SysTick is clocked at the same frequency as the core. */ /* Ensure the SysTick is clocked at the same frequency as the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#else #else
/* The way the SysTick is clocked is not modified in case it is not the
/* The way the SysTick is clocked is not modified in case it is not the
* same a the core. */ * same a the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 0 ) #define portNVIC_SYSTICK_CLK_BIT ( 0 )
#endif #endif
@ -94,7 +95,7 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -117,24 +118,24 @@
/** /**
* @brief Constants required to manipulate the MPU. * @brief Constants required to manipulate the MPU.
*/ */
#define portMPU_TYPE_REG ( * ( ( volatile uint32_t * ) 0xe000ed90 ) ) #define portMPU_TYPE_REG ( *( ( volatile uint32_t * ) 0xe000ed90 ) )
#define portMPU_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed94 ) ) #define portMPU_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed94 ) )
#define portMPU_RNR_REG ( * ( ( volatile uint32_t * ) 0xe000ed98 ) ) #define portMPU_RNR_REG ( *( ( volatile uint32_t * ) 0xe000ed98 ) )
#define portMPU_RBAR_REG ( * ( ( volatile uint32_t * ) 0xe000ed9c ) ) #define portMPU_RBAR_REG ( *( ( volatile uint32_t * ) 0xe000ed9c ) )
#define portMPU_RLAR_REG ( * ( ( volatile uint32_t * ) 0xe000eda0 ) ) #define portMPU_RLAR_REG ( *( ( volatile uint32_t * ) 0xe000eda0 ) )
#define portMPU_RBAR_A1_REG ( * ( ( volatile uint32_t * ) 0xe000eda4 ) ) #define portMPU_RBAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda4 ) )
#define portMPU_RLAR_A1_REG ( * ( ( volatile uint32_t * ) 0xe000eda8 ) ) #define portMPU_RLAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda8 ) )
#define portMPU_RBAR_A2_REG ( * ( ( volatile uint32_t * ) 0xe000edac ) ) #define portMPU_RBAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edac ) )
#define portMPU_RLAR_A2_REG ( * ( ( volatile uint32_t * ) 0xe000edb0 ) ) #define portMPU_RLAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edb0 ) )
#define portMPU_RBAR_A3_REG ( * ( ( volatile uint32_t * ) 0xe000edb4 ) ) #define portMPU_RBAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb4 ) )
#define portMPU_RLAR_A3_REG ( * ( ( volatile uint32_t * ) 0xe000edb8 ) ) #define portMPU_RLAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb8 ) )
#define portMPU_MAIR0_REG ( * ( ( volatile uint32_t * ) 0xe000edc0 ) ) #define portMPU_MAIR0_REG ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
#define portMPU_MAIR1_REG ( * ( ( volatile uint32_t * ) 0xe000edc4 ) ) #define portMPU_MAIR1_REG ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */ #define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */ #define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
@ -204,8 +205,9 @@
*/ */
#define portINITIAL_XPSR ( 0x01000000 ) #define portINITIAL_XPSR ( 0x01000000 )
#if( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/**
/**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -221,7 +223,8 @@
*/ */
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/**
/**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -284,15 +287,17 @@
*/ */
static void prvTaskExitError( void ); static void prvTaskExitError( void );
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/**
/**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/**
/**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -337,7 +342,7 @@ void SysTick_Handler( void ) PRIVILEGED_FUNCTION;
/** /**
* @brief C part of SVC handler. * @brief C part of SVC handler.
*/ */
portDONT_DISCARD void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) PRIVILEGED_FUNCTION; portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIVILEGED_FUNCTION;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -346,27 +351,29 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) PRIVI
*/ */
static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/**
/**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
/**
/**
* @brief The number of SysTick increments that make up one tick period. * @brief The number of SysTick increments that make up one tick period.
*/ */
static uint32_t ulTimerCountsForOneTick = 0; static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
static uint32_t xMaximumPossibleSuppressedTicks = 0; static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -374,8 +381,8 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
__attribute__(( weak )) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{ {
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
TickType_t xModifiableIdleTime; TickType_t xModifiableIdleTime;
@ -396,6 +403,7 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
* tick periods. -1 is used because this code will execute part way * tick periods. -1 is used because this code will execute part way
* through one of the tick periods. */ * through one of the tick periods. */
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
if( ulReloadValue > ulStoppedTimerCompensation ) if( ulReloadValue > ulStoppedTimerCompensation )
{ {
ulReloadValue -= ulStoppedTimerCompensation; ulReloadValue -= ulStoppedTimerCompensation;
@ -403,9 +411,9 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
/* Enter a critical section but don't use the taskENTER_CRITICAL() /* Enter a critical section but don't use the taskENTER_CRITICAL()
* method as that will mask interrupts that should exit sleep mode. */ * method as that will mask interrupts that should exit sleep mode. */
__asm volatile( "cpsid i" ::: "memory" ); __asm volatile ( "cpsid i" ::: "memory" );
__asm volatile( "dsb" ); __asm volatile ( "dsb" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
/* If a context switch is pending or a task is waiting for the scheduler /* If a context switch is pending or a task is waiting for the scheduler
* to be un-suspended then abandon the low power entry. */ * to be un-suspended then abandon the low power entry. */
@ -424,7 +432,7 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
/* Re-enable interrupts - see comments above the cpsid instruction() /* Re-enable interrupts - see comments above the cpsid instruction()
* above. */ * above. */
__asm volatile( "cpsie i" ::: "memory" ); __asm volatile ( "cpsie i" ::: "memory" );
} }
else else
{ {
@ -446,28 +454,30 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
* so a copy is taken. */ * so a copy is taken. */
xModifiableIdleTime = xExpectedIdleTime; xModifiableIdleTime = xExpectedIdleTime;
configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
if( xModifiableIdleTime > 0 ) if( xModifiableIdleTime > 0 )
{ {
__asm volatile( "dsb" ::: "memory" ); __asm volatile ( "dsb" ::: "memory" );
__asm volatile( "wfi" ); __asm volatile ( "wfi" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
} }
configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
/* Re-enable interrupts to allow the interrupt that brought the MCU /* Re-enable interrupts to allow the interrupt that brought the MCU
* out of sleep mode to execute immediately. See comments above * out of sleep mode to execute immediately. See comments above
* the cpsid instruction above. */ * the cpsid instruction above. */
__asm volatile( "cpsie i" ::: "memory" ); __asm volatile ( "cpsie i" ::: "memory" );
__asm volatile( "dsb" ); __asm volatile ( "dsb" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
/* Disable interrupts again because the clock is about to be stopped /* Disable interrupts again because the clock is about to be stopped
* and interrupts that execute while the clock is stopped will * and interrupts that execute while the clock is stopped will
* increase any slippage between the time maintained by the RTOS and * increase any slippage between the time maintained by the RTOS and
* calendar time. */ * calendar time. */
__asm volatile( "cpsid i" ::: "memory" ); __asm volatile ( "cpsid i" ::: "memory" );
__asm volatile( "dsb" ); __asm volatile ( "dsb" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
/* Disable the SysTick clock without reading the /* Disable the SysTick clock without reading the
* portNVIC_SYSTICK_CTRL_REG register to ensure the * portNVIC_SYSTICK_CTRL_REG register to ensure the
@ -534,16 +544,16 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrupts enabled. */ /* Exit with interrupts enabled. */
__asm volatile( "cpsie i" ::: "memory" ); __asm volatile ( "cpsie i" ::: "memory" );
} }
} }
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
{ {
/* Calculate the constants required to configure the tick interrupt. */ /* Calculate the constants required to configure the tick interrupt. */
#if( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )
{ {
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
@ -563,7 +573,7 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNC
static void prvTaskExitError( void ) static void prvTaskExitError( void )
{ {
volatile uint32_t ulDummy = 0UL; volatile uint32_t ulDummy = 0UL;
/* A function that implements a task must not exit or attempt to return to /* 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 * its caller as there is nothing to return to. If a task wants to exit it
@ -586,10 +596,11 @@ volatile uint32_t ulDummy = 0UL;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */ static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */
{ {
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -600,7 +611,7 @@ volatile uint32_t ulDummy = 0UL;
extern uint32_t * __unprivileged_flash_end__; extern uint32_t * __unprivileged_flash_end__;
extern uint32_t * __privileged_sram_start__; extern uint32_t * __privileged_sram_start__;
extern uint32_t * __privileged_sram_end__; extern uint32_t * __privileged_sram_end__;
#else #else /* if defined( __ARMCC_VERSION ) */
/* Declaration when these variable are exported from linker scripts. */ /* Declaration when these variable are exported from linker scripts. */
extern uint32_t __privileged_functions_start__[]; extern uint32_t __privileged_functions_start__[];
extern uint32_t __privileged_functions_end__[]; extern uint32_t __privileged_functions_end__[];
@ -671,10 +682,10 @@ volatile uint32_t ulDummy = 0UL;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */ static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */
{ {
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
{ {
/* Enable non-secure access to the FPU. */ /* Enable non-secure access to the FPU. */
SecureInit_EnableNSFPUAccess(); SecureInit_EnableNSFPUAccess();
@ -703,8 +714,8 @@ void vPortYield( void ) /* PRIVILEGED_FUNCTION */
/* Barriers are normally not required but do ensure the code is /* Barriers are normally not required but do ensure the code is
* completely within the specified behaviour for the architecture. */ * completely within the specified behaviour for the architecture. */
__asm volatile( "dsb" ::: "memory" ); __asm volatile ( "dsb" ::: "memory" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -715,8 +726,8 @@ void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
/* Barriers are normally not required but do ensure the code is /* Barriers are normally not required but do ensure the code is
* completely within the specified behaviour for the architecture. */ * completely within the specified behaviour for the architecture. */
__asm volatile( "dsb" ::: "memory" ); __asm volatile ( "dsb" ::: "memory" );
__asm volatile( "isb" ); __asm volatile ( "isb" );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -734,7 +745,7 @@ void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */ void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
{ {
uint32_t ulPreviousMask; uint32_t ulPreviousMask;
ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
{ {
@ -749,10 +760,11 @@ uint32_t ulPreviousMask;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */
{ {
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -762,33 +774,33 @@ void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) /* PRIVILEGED_FUNCTION
extern uint32_t __syscalls_flash_start__[]; extern uint32_t __syscalls_flash_start__[];
extern uint32_t __syscalls_flash_end__[]; extern uint32_t __syscalls_flash_end__[];
#endif /* defined( __ARMCC_VERSION ) */ #endif /* defined( __ARMCC_VERSION ) */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
uint32_t ulPC; uint32_t ulPC;
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
uint32_t ulR0; uint32_t ulR0;
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
uint32_t ulControl, ulIsTaskPrivileged; uint32_t ulControl, ulIsTaskPrivileged;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
uint8_t ucSVCNumber; uint8_t ucSVCNumber;
/* Register are stored on the stack in the following order - R0, R1, R2, R3, /* Register are stored on the stack in the following order - R0, R1, R2, R3,
* R12, LR, PC, xPSR. */ * R12, LR, PC, xPSR. */
ulPC = pulCallerStackAddress[ 6 ]; ulPC = pulCallerStackAddress[ 6 ];
ucSVCNumber = ( ( uint8_t *) ulPC )[ -2 ]; ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ];
switch( ucSVCNumber ) switch( ucSVCNumber )
{ {
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
case portSVC_ALLOCATE_SECURE_CONTEXT: case portSVC_ALLOCATE_SECURE_CONTEXT:
{
/* R0 contains the stack size passed as parameter to the /* R0 contains the stack size passed as parameter to the
* vPortAllocateSecureContext function. */ * vPortAllocateSecureContext function. */
ulR0 = pulCallerStackAddress[ 0 ]; ulR0 = pulCallerStackAddress[ 0 ];
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
/* Read the CONTROL register value. */ /* Read the CONTROL register value. */
__asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
@ -800,7 +812,7 @@ uint8_t ucSVCNumber;
/* Allocate and load a context for the secure task. */ /* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged ); xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
} }
#else #else /* if ( configENABLE_MPU == 1 ) */
{ {
/* Allocate and load a context for the secure task. */ /* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0 ); xSecureContext = SecureContext_AllocateContext( ulR0 );
@ -809,23 +821,19 @@ uint8_t ucSVCNumber;
configASSERT( xSecureContext != NULL ); configASSERT( xSecureContext != NULL );
SecureContext_LoadContext( xSecureContext ); SecureContext_LoadContext( xSecureContext );
}
break; break;
case portSVC_FREE_SECURE_CONTEXT: case portSVC_FREE_SECURE_CONTEXT:
{
/* R0 contains the secure context handle to be freed. */ /* R0 contains the secure context handle to be freed. */
ulR0 = pulCallerStackAddress[ 0 ]; ulR0 = pulCallerStackAddress[ 0 ];
/* Free the secure context. */ /* Free the secure context. */
SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 ); SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 );
}
break; break;
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
case portSVC_START_SCHEDULER: case portSVC_START_SCHEDULER:
{ #if ( configENABLE_TRUSTZONE == 1 )
#if( configENABLE_TRUSTZONE == 1 )
{ {
/* De-prioritize the non-secure exceptions so that the /* De-prioritize the non-secure exceptions so that the
* non-secure pendSV runs at the lowest priority. */ * non-secure pendSV runs at the lowest priority. */
@ -836,7 +844,7 @@ uint8_t ucSVCNumber;
} }
#endif /* configENABLE_TRUSTZONE */ #endif /* configENABLE_TRUSTZONE */
#if( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
{ {
/* Setup the Floating Point Unit (FPU). */ /* Setup the Floating Point Unit (FPU). */
prvSetupFPU(); prvSetupFPU();
@ -846,41 +854,44 @@ uint8_t ucSVCNumber;
/* Setup the context of the first task so that the first task starts /* Setup the context of the first task so that the first task starts
* executing. */ * executing. */
vRestoreContextOfFirstTask(); vRestoreContextOfFirstTask();
}
break; break;
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
case portSVC_RAISE_PRIVILEGE: case portSVC_RAISE_PRIVILEGE:
{
/* Only raise the privilege, if the svc was raised from any of /* Only raise the privilege, if the svc was raised from any of
* the system calls. */ * the system calls. */
if( ulPC >= ( uint32_t ) __syscalls_flash_start__ && if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
ulPC <= ( uint32_t ) __syscalls_flash_end__ ) ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
{ {
vRaisePrivilege(); vRaisePrivilege();
} }
}
break; break;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
default: default:
{
/* Incorrect SVC call. */ /* Incorrect SVC call. */
configASSERT( pdFALSE ); configASSERT( pdFALSE );
} }
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
#else #else
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters ) /* PRIVILEGED_FUNCTION */ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
StackType_t * pxEndOfStack,
TaskFunction_t pxCode,
void * pvParameters ) /* PRIVILEGED_FUNCTION */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
{ {
/* Simulate the stack frame as it would be created by a context switch /* Simulate the stack frame as it would be created by a context switch
* interrupt. */ * interrupt. */
#if( portPRELOAD_REGISTERS == 0 ) #if ( portPRELOAD_REGISTERS == 0 )
{ {
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */ *pxTopOfStack = portINITIAL_XPSR; /* xPSR */
@ -893,9 +904,10 @@ uint8_t ucSVCNumber;
pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */ pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
*pxTopOfStack = portINITIAL_EXC_RETURN; *pxTopOfStack = portINITIAL_EXC_RETURN;
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
pxTopOfStack--; pxTopOfStack--;
if( xRunPrivileged == pdTRUE ) if( xRunPrivileged == pdTRUE )
{ {
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */ *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
@ -910,7 +922,7 @@ uint8_t ucSVCNumber;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
{ {
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
@ -954,9 +966,10 @@ uint8_t ucSVCNumber;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */ *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
pxTopOfStack--; pxTopOfStack--;
if( xRunPrivileged == pdTRUE ) if( xRunPrivileged == pdTRUE )
{ {
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */ *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
@ -971,7 +984,7 @@ uint8_t ucSVCNumber;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
#if( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
{ {
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
@ -990,7 +1003,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
/* Setup the Memory Protection Unit (MPU). */ /* Setup the Memory Protection Unit (MPU). */
prvSetupMPU(); prvSetupMPU();
@ -1029,8 +1042,11 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth ) void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
const struct xMEMORY_REGION * const xRegions,
StackType_t * pxBottomOfStack,
uint32_t ulStackDepth )
{ {
uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber; uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber;
int32_t lIndex = 0; int32_t lIndex = 0;
@ -1126,13 +1142,13 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xPortIsInsideInterrupt( void ) BaseType_t xPortIsInsideInterrupt( void )
{ {
uint32_t ulCurrentInterrupt; uint32_t ulCurrentInterrupt;
BaseType_t xReturn; BaseType_t xReturn;
/* Obtain the number of the currently executing interrupt. Interrupt Program /* Obtain the number of the currently executing interrupt. Interrupt Program
* Status Register (IPSR) holds the exception number of the currently-executing * Status Register (IPSR) holds the exception number of the currently-executing
* exception or zero for Thread mode.*/ * exception or zero for Thread mode.*/
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" ); __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" );
if( ulCurrentInterrupt == 0 ) if( ulCurrentInterrupt == 0 )
{ {

View file

@ -38,7 +38,7 @@
* header files. */ * header files. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#if( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0. #error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
#endif #endif
@ -48,75 +48,75 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst2 \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n" /* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r4, #1 \n" /* r4 = 1. */ " movs r4, #1 \n"/* r4 = 1. */
" bics r3, r4 \n" /* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */ " bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
" str r3, [r2] \n" /* Disable MPU. */ " str r3, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r4, [r1] \n" /* r4 = *r1 i.e. r4 = MAIR0. */ " ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const2 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n" /* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n" /* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" movs r4, #4 \n" /* r4 = 4. */ " movs r4, #4 \n"/* r4 = 4. */
" str r4, [r2] \n" /* Program RNR = 4. */ " str r4, [r2] \n"/* Program RNR = 4. */
" ldmia r1!, {r5,r6} \n" /* Read first set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst2 \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n" /* Write first set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */
" movs r4, #5 \n" /* r4 = 5. */ " movs r4, #5 \n"/* r4 = 5. */
" str r4, [r2] \n" /* Program RNR = 5. */ " str r4, [r2] \n"/* Program RNR = 5. */
" ldmia r1!, {r5,r6} \n" /* Read second set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst2 \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n" /* Write second set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */
" movs r4, #6 \n" /* r4 = 6. */ " movs r4, #6 \n"/* r4 = 6. */
" str r4, [r2] \n" /* Program RNR = 6. */ " str r4, [r2] \n"/* Program RNR = 6. */
" ldmia r1!, {r5,r6} \n" /* Read third set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst2 \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n" /* Write third set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */
" movs r4, #7 \n" /* r4 = 7. */ " movs r4, #7 \n"/* r4 = 7. */
" str r4, [r2] \n" /* Program RNR = 7. */ " str r4, [r2] \n"/* Program RNR = 7. */
" ldmia r1!, {r5,r6} \n" /* Read fourth set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst2 \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n" /* Write fourth set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */
" \n" " \n"
" ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r4, #1 \n" /* r4 = 1. */ " movs r4, #1 \n"/* r4 = 1. */
" orrs r3, r4 \n" /* r3 = r3 | r4 i.e. Set the bit 0 in r3. */ " orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
" str r3, [r2] \n" /* Enable MPU. */ " str r3, [r2] \n"/* Enable MPU. */
" dsb \n" /* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */ " msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" msr control, r2 \n" /* Set this task's CONTROL value. */ " msr control, r2 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n" /* Discard everything up to r0. */ " 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. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r3 \n" /* Finally, branch to EXC_RETURN. */ " bx r3 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ " ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */ " msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n" /* r1 = 2. */ " movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */ " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n" /* Discard everything up to r0. */ " 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. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r2 \n" /* Finally, branch to EXC_RETURN. */ " bx r2 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n" "xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n" "xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n" "xRNRConst2: .word 0xe000ed98 \n"
@ -130,15 +130,15 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n" /* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" movs r1, #1 \n" /* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" tst r0, r1 \n" /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */ " tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
" beq running_privileged \n" /* If the result of previous AND operation was 0, branch. */ " beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */
" movs r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
" running_privileged: \n" " running_privileged: \n"
" movs r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ " movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n" /* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
@ -150,11 +150,11 @@ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n" /* Read the CONTROL register. */ " mrs r0, control \n"/* Read the CONTROL register. */
" movs r1, #1 \n" /* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" bics r0, r1 \n" /* Clear the bit 0. */ " bics r0, r1 \n"/* Clear the bit 0. */
" msr control, r0 \n" /* Write back the new CONTROL value. */ " msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n" /* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
@ -164,12 +164,12 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n" /* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" movs r1, #1 \n" /* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" orrs r0, r1 \n" /* r0 = r0 | r1. */ " orrs r0, r1 \n"/* r0 = r0 | r1. */
" msr control, r0 \n" /* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n" /* Return to the caller. */ " bx lr \n"/* Return to the caller. */
:::"r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -178,19 +178,19 @@ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" ldr r0, xVTORConst \n" /* Use the NVIC offset register to locate the stack. */ " 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"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */ " 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. */ " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n" /* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n" /* System call to start the first task. */ " svc %0 \n"/* System call to start the first task. */
" nop \n" " nop \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n" "xVTORConst: .word 0xe000ed08 \n"
:: "i" ( portSVC_START_SCHEDULER ) : "memory" ::"i" ( portSVC_START_SCHEDULER ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -224,115 +224,115 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, psp \n" /* Read PSP in r0. */ " mrs r0, psp \n"/* Read PSP in r0. */
" ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r0, r0, #44 \n" /* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */ " subs r0, r0, #44 \n"/* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */
" str r0, [r1] \n" /* Save the new top of stack in TCB. */ " str r0, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r1, psplim \n" /* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r2, control \n" /* r2 = CONTROL. */ " mrs r2, control \n"/* r2 = CONTROL. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r0!, {r1-r7} \n" /* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */ " stmia r0!, {r1-r7} \n"/* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */
" mov r4, r8 \n" /* r4 = r8. */ " mov r4, r8 \n"/* r4 = r8. */
" mov r5, r9 \n" /* r5 = r9. */ " mov r5, r9 \n"/* r5 = r9. */
" mov r6, r10 \n" /* r6 = r10. */ " mov r6, r10 \n"/* r6 = r10. */
" mov r7, r11 \n" /* r7 = r11. */ " mov r7, r11 \n"/* r7 = r11. */
" stmia r0!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */ " stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r0, r0, #40 \n" /* Make space for PSPLIM, LR and the remaining registers on the stack. */ " subs r0, r0, #40 \n"/* Make space for PSPLIM, LR and the remaining registers on the stack. */
" str r0, [r1] \n" /* Save the new top of stack in TCB. */ " str r0, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r2, psplim \n" /* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r0!, {r2-r7} \n" /* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */ " stmia r0!, {r2-r7} \n"/* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */
" mov r4, r8 \n" /* r4 = r8. */ " mov r4, r8 \n"/* r4 = r8. */
" mov r5, r9 \n" /* r5 = r9. */ " mov r5, r9 \n"/* r5 = r9. */
" mov r6, r10 \n" /* r6 = r10. */ " mov r6, r10 \n"/* r6 = r10. */
" mov r7, r11 \n" /* r7 = r11. */ " mov r7, r11 \n"/* r7 = r11. */
" stmia r0!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */ " stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" cpsid i \n" " cpsid i \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" cpsie i \n" " cpsie i \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n" /* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r4, #1 \n" /* r4 = 1. */ " movs r4, #1 \n"/* r4 = 1. */
" bics r3, r4 \n" /* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */ " bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
" str r3, [r2] \n" /* Disable MPU. */ " str r3, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r4, [r1] \n" /* r4 = *r1 i.e. r4 = MAIR0. */ " ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n" /* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst \n" /* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" movs r4, #4 \n" /* r4 = 4. */ " movs r4, #4 \n"/* r4 = 4. */
" str r4, [r2] \n" /* Program RNR = 4. */ " str r4, [r2] \n"/* Program RNR = 4. */
" ldmia r1!, {r5,r6} \n" /* Read first set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n" /* Write first set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */
" movs r4, #5 \n" /* r4 = 5. */ " movs r4, #5 \n"/* r4 = 5. */
" str r4, [r2] \n" /* Program RNR = 5. */ " str r4, [r2] \n"/* Program RNR = 5. */
" ldmia r1!, {r5,r6} \n" /* Read second set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n" /* Write second set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */
" movs r4, #6 \n" /* r4 = 6. */ " movs r4, #6 \n"/* r4 = 6. */
" str r4, [r2] \n" /* Program RNR = 6. */ " str r4, [r2] \n"/* Program RNR = 6. */
" ldmia r1!, {r5,r6} \n" /* Read third set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n" /* Write third set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */
" movs r4, #7 \n" /* r4 = 7. */ " movs r4, #7 \n"/* r4 = 7. */
" str r4, [r2] \n" /* Program RNR = 7. */ " str r4, [r2] \n"/* Program RNR = 7. */
" ldmia r1!, {r5,r6} \n" /* Read fourth set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n" /* Write fourth set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */
" \n" " \n"
" ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r4, #1 \n" /* r4 = 1. */ " movs r4, #1 \n"/* r4 = 1. */
" orrs r3, r4 \n" /* r3 = r3 | r4 i.e. Set the bit 0 in r3. */ " orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
" str r3, [r2] \n" /* Enable MPU. */ " str r3, [r2] \n"/* Enable MPU. */
" dsb \n" /* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" adds r0, r0, #28 \n" /* Move to the high registers. */ " adds r0, r0, #28 \n"/* Move to the high registers. */
" ldmia r0!, {r4-r7} \n" /* Restore the high registers that are not automatically restored. */ " ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
" mov r8, r4 \n" /* r8 = r4. */ " mov r8, r4 \n"/* r8 = r4. */
" mov r9, r5 \n" /* r9 = r5. */ " mov r9, r5 \n"/* r9 = r5. */
" mov r10, r6 \n" /* r10 = r6. */ " mov r10, r6 \n"/* r10 = r6. */
" mov r11, r7 \n" /* r11 = r7. */ " mov r11, r7 \n"/* r11 = r7. */
" msr psp, r0 \n" /* Remember the new top of stack for the task. */ " msr psp, r0 \n"/* Remember the new top of stack for the task. */
" subs r0, r0, #44 \n" /* Move to the starting of the saved context. */ " subs r0, r0, #44 \n"/* Move to the starting of the saved context. */
" ldmia r0!, {r1-r7} \n" /* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */ " ldmia r0!, {r1-r7} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */
" msr psplim, r1 \n" /* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r2 \n" /* Restore the CONTROL register value for the task. */ " msr control, r2 \n"/* Restore the CONTROL register value for the task. */
" bx r3 \n" " bx r3 \n"
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" adds r0, r0, #24 \n" /* Move to the high registers. */ " adds r0, r0, #24 \n"/* Move to the high registers. */
" ldmia r0!, {r4-r7} \n" /* Restore the high registers that are not automatically restored. */ " ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
" mov r8, r4 \n" /* r8 = r4. */ " mov r8, r4 \n"/* r8 = r4. */
" mov r9, r5 \n" /* r9 = r5. */ " mov r9, r5 \n"/* r9 = r5. */
" mov r10, r6 \n" /* r10 = r6. */ " mov r10, r6 \n"/* r10 = r6. */
" mov r11, r7 \n" /* r11 = r7. */ " mov r11, r7 \n"/* r11 = r7. */
" msr psp, r0 \n" /* Remember the new top of stack for the task. */ " msr psp, r0 \n"/* Remember the new top of stack for the task. */
" subs r0, r0, #40 \n" /* Move to the starting of the saved context. */ " subs r0, r0, #40 \n"/* Move to the starting of the saved context. */
" ldmia r0!, {r2-r7} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */ " ldmia r0!, {r2-r7} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */
" msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */ " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
" bx r3 \n" " bx r3 \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
#if( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n" "xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n" "xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n" "xRNRConst: .word 0xe000ed98 \n"

Some files were not shown because too many files have changed in this diff Show more