1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-11-29 07:24:13 +01:00

OP-1274 update freertos files. Architecture specific files are left into their original FreeRTOS folder structure

This commit is contained in:
Alessio Morale 2014-03-23 18:44:06 +01:00
parent 124a31f0b5
commit 921abb5131
36 changed files with 7086 additions and 1987 deletions

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -76,17 +77,17 @@
/* Lists for ready and blocked co-routines. --------------------*/ /* Lists for ready and blocked co-routines. --------------------*/
static xList pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */ static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */
static xList xDelayedCoRoutineList1; /*< Delayed co-routines. */ static List_t xDelayedCoRoutineList1; /*< Delayed co-routines. */
static xList 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 xList * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */ static List_t * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */
static xList * pxOverflowDelayedCoRoutineList; /*< 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; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */
static xList 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. --------------------------------*/
corCRCB * pxCurrentCoRoutine = NULL; CRCB_t * pxCurrentCoRoutine = NULL;
static unsigned portBASE_TYPE uxTopCoRoutineReadyPriority = 0; static UBaseType_t uxTopCoRoutineReadyPriority = 0;
static portTickType 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 )
@ -104,7 +105,7 @@ static portTickType xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks =
{ \ { \
uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \ uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \
} \ } \
vListInsertEnd( ( xList * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \ vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \
} }
/* /*
@ -133,13 +134,13 @@ static void prvCheckDelayedList( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
signed portBASE_TYPE xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex ) BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex )
{ {
signed portBASE_TYPE xReturn; BaseType_t xReturn;
corCRCB *pxCoRoutine; 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 = ( corCRCB * ) pvPortMalloc( sizeof( corCRCB ) ); 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
@ -166,14 +167,14 @@ corCRCB *pxCoRoutine;
vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) ); vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) );
vListInitialiseItem( &( pxCoRoutine->xEventListItem ) ); vListInitialiseItem( &( pxCoRoutine->xEventListItem ) );
/* Set the co-routine control block as a link back from the xListItem. /* 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 );
/* Event lists are always in priority order. */ /* Event lists are always in priority order. */
listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) 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. */
@ -190,9 +191,9 @@ corCRCB *pxCoRoutine;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vCoRoutineAddToDelayedList( portTickType xTicksToDelay, xList *pxEventList ) void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList )
{ {
portTickType 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. */
@ -201,7 +202,7 @@ portTickType xTimeToWake;
/* 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( ( xListItem * ) &( 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. */
listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake ); listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake );
@ -210,13 +211,13 @@ portTickType xTimeToWake;
{ {
/* Wake time has overflowed. Place this item in the /* Wake time has overflowed. Place this item in the
overflow list. */ overflow list. */
vListInsert( ( xList * ) pxOverflowDelayedCoRoutineList, ( xListItem * ) &( 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( ( xList * ) pxDelayedCoRoutineList, ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) ); vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
} }
if( pxEventList ) if( pxEventList )
@ -235,12 +236,12 @@ static void prvCheckPendingReadyList( void )
the ready lists itself. */ the ready lists itself. */
while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE ) while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE )
{ {
corCRCB *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 = ( corCRCB * ) 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();
@ -253,7 +254,7 @@ static void prvCheckPendingReadyList( void )
static void prvCheckDelayedList( void ) static void prvCheckDelayedList( void )
{ {
corCRCB *pxCRCB; CRCB_t *pxCRCB;
xPassedTicks = xTaskGetTickCount() - xLastTickCount; xPassedTicks = xTaskGetTickCount() - xLastTickCount;
while( xPassedTicks ) while( xPassedTicks )
@ -264,7 +265,7 @@ corCRCB *pxCRCB;
/* If the tick count has overflowed we need to swap the ready lists. */ /* If the tick count has overflowed we need to swap the ready lists. */
if( xCoRoutineTickCount == 0 ) if( xCoRoutineTickCount == 0 )
{ {
xList * 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! */
@ -276,7 +277,7 @@ corCRCB *pxCRCB;
/* See if this tick has made a timeout expire. */ /* See if this tick has made a timeout expire. */
while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE ) while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE )
{ {
pxCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList ); pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList );
if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) ) if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) )
{ {
@ -341,16 +342,16 @@ void vCoRoutineSchedule( void )
static void prvInitialiseCoRoutineLists( void ) static void prvInitialiseCoRoutineLists( void )
{ {
unsigned portBASE_TYPE uxPriority; UBaseType_t uxPriority;
for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ ) for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ )
{ {
vListInitialise( ( xList * ) &( pxReadyCoRoutineLists[ uxPriority ] ) ); vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) );
} }
vListInitialise( ( xList * ) &xDelayedCoRoutineList1 ); vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 );
vListInitialise( ( xList * ) &xDelayedCoRoutineList2 ); vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 );
vListInitialise( ( xList * ) &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. */
@ -359,17 +360,17 @@ unsigned portBASE_TYPE uxPriority;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
signed portBASE_TYPE xCoRoutineRemoveFromEventList( const xList *pxEventList ) BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList )
{ {
corCRCB *pxUnblockedCRCB; CRCB_t *pxUnblockedCRCB;
signed portBASE_TYPE 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 = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
vListInsertEnd( ( xList * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) ); vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );
if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority ) if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority )
{ {

View File

@ -0,0 +1,654 @@
/*
FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that has become a de facto standard. *
* *
* Help yourself get started quickly and support the FreeRTOS *
* project by purchasing a FreeRTOS tutorial book, reference *
* manual, or both from: http://www.FreeRTOS.org/Documentation *
* *
* Thank you! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
>>! NOTE: The modification to the GPL is included to allow you to distribute
>>! a combined work that includes FreeRTOS without being obliged to provide
>>! the source code for proprietary components outside of the FreeRTOS
>>! kernel.
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available from the following
link: http://www.freertos.org/a00114.html
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong?" *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
license and Real Time Engineers Ltd. contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
/* Standard includes. */
#include <stdlib.h>
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
all the API functions to use the MPU wrappers. That should only be done when
task.h is included from an application file. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "event_groups.h"
/* Lint e961 and e750 are suppressed as a MISRA exception justified because the
MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
header files above, but not in this file, in order to generate the correct
privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
#if ( INCLUDE_xEventGroupSetBitFromISR == 1 ) && ( configUSE_TIMERS == 0 )
#error configUSE_TIMERS must be set to 1 to make the xEventGroupSetBitFromISR() function available.
#endif
#if ( INCLUDE_xEventGroupSetBitFromISR == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 0 )
#error INCLUDE_xTimerPendFunctionCall must also be set to one to make the xEventGroupSetBitFromISR() function available.
#endif
/* The following bit fields convey control information in a task's event list
item value. It is important they don't clash with the
taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
#if configUSE_16_BIT_TICKS == 1
#define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
#define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U
#define eventWAIT_FOR_ALL_BITS 0x0400U
#define eventEVENT_BITS_CONTROL_BYTES 0xff00U
#else
#define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL
#define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL
#define eventWAIT_FOR_ALL_BITS 0x04000000UL
#define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL
#endif
typedef struct xEventGroupDefinition
{
EventBits_t uxEventBits;
List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */
#if( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxEventGroupNumber;
#endif
} EventGroup_t;
/*-----------------------------------------------------------*/
/*
* Test the bits set in uxCurrentEventBits to see if the wait condition is met.
* The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is
* pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
* are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the
* wait condition is met if any of the bits set in uxBitsToWait for are also set
* in uxCurrentEventBits.
*/
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits );
/*-----------------------------------------------------------*/
EventGroupHandle_t xEventGroupCreate( void )
{
EventGroup_t *pxEventBits;
pxEventBits = pvPortMalloc( sizeof( EventGroup_t ) );
if( pxEventBits != NULL )
{
pxEventBits->uxEventBits = 0;
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
traceEVENT_GROUP_CREATE( pxEventBits );
}
else
{
traceEVENT_GROUP_CREATE_FAILED();
}
return ( EventGroupHandle_t ) pxEventBits;
}
/*-----------------------------------------------------------*/
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait )
{
EventBits_t uxOriginalBitValue, uxReturn;
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
BaseType_t xAlreadyYielded;
BaseType_t xTimeoutOccurred = pdFALSE;
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
configASSERT( uxBitsToWaitFor != 0 );
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
{
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
}
#endif
vTaskSuspendAll();
{
uxOriginalBitValue = pxEventBits->uxEventBits;
( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
{
/* All the rendezvous bits are now set - no need to block. */
uxReturn = ( uxOriginalBitValue | uxBitsToSet );
/* Rendezvous always clear the bits. They will have been cleared
already unless this is the only task in the rendezvous. */
pxEventBits->uxEventBits &= uxBitsToWaitFor;
xTicksToWait = 0;
}
else
{
if( xTicksToWait != ( TickType_t ) 0 )
{
traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
/* Store the bits that the calling task is waiting for in the
task's event list item so the kernel knows when a match is
found. Then enter the blocked state. */
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
/* This assignment is obsolete as uxReturn will get set after
the task unblocks, but some compilers mistakenly generate a
warning about uxReturn being returned without being set if the
assignment is omitted. */
uxReturn = 0;
}
else
{
/* The rendezvous bits were not set, but no block time was
specified - just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits;
}
}
}
xAlreadyYielded = xTaskResumeAll();
if( xTicksToWait != ( TickType_t ) 0 )
{
if( xAlreadyYielded == pdFALSE )
{
portYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* The task blocked to wait for its required bits to be set - at this
point either the required bits were set or the block time expired. If
the required bits were set they will have been stored in the task's
event list item, and they should now be retrieved then cleared. */
uxReturn = uxTaskResetEventItemValue();
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
{
/* The task timed out, just return the current event bit value. */
taskENTER_CRITICAL();
{
uxReturn = pxEventBits->uxEventBits;
/* Although the task got here because it timed out before the
bits it was waiting for were set, it is possible that since it
unblocked another task has set the bits. If this is the case
then it may be required to clear the bits before exiting. */
if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
{
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
taskEXIT_CRITICAL();
xTimeoutOccurred = pdTRUE;
}
else
{
/* The task unblocked because the bits were set. Clear the control
bits before returning the value. */
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
}
}
traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
return uxReturn;
}
/*-----------------------------------------------------------*/
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
{
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
EventBits_t uxReturn, uxControlBits = 0;
BaseType_t xWaitConditionMet, xAlreadyYielded;
BaseType_t xTimeoutOccurred = pdFALSE;
/* Check the user is not attempting to wait on the bits used by the kernel
itself, and that at least one bit is being requested. */
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
configASSERT( uxBitsToWaitFor != 0 );
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
{
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
}
#endif
vTaskSuspendAll();
{
const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
/* Check to see if the wait condition is already met or not. */
xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
if( xWaitConditionMet != pdFALSE )
{
/* The wait condition has already been met so there is no need to
block. */
uxReturn = uxCurrentEventBits;
xTicksToWait = ( TickType_t ) 0;
/* Clear the wait bits if requested to do so. */
if( xClearOnExit != pdFALSE )
{
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else if( xTicksToWait == ( TickType_t ) 0 )
{
/* The wait condition has not been met, but no block time was
specified, so just return the current value. */
uxReturn = uxCurrentEventBits;
}
else
{
/* The task is going to block to wait for its required bits to be
set. uxControlBits are used to remember the specified behaviour of
this call to xEventGroupWaitBits() - for use when the event bits
unblock the task. */
if( xClearOnExit != pdFALSE )
{
uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
if( xWaitForAllBits != pdFALSE )
{
uxControlBits |= eventWAIT_FOR_ALL_BITS;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Store the bits that the calling task is waiting for in the
task's event list item so the kernel knows when a match is
found. Then enter the blocked state. */
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
/* This is obsolete as it will get set after the task unblocks, but
some compilers mistakenly generate a warning about the variable
being returned without being set if it is not done. */
uxReturn = 0;
traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
}
}
xAlreadyYielded = xTaskResumeAll();
if( xTicksToWait != ( TickType_t ) 0 )
{
if( xAlreadyYielded == pdFALSE )
{
portYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* The task blocked to wait for its required bits to be set - at this
point either the required bits were set or the block time expired. If
the required bits were set they will have been stored in the task's
event list item, and they should now be retrieved then cleared. */
uxReturn = uxTaskResetEventItemValue();
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
{
taskENTER_CRITICAL();
{
/* The task timed out, just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits;
/* It is possible that the event bits were updated between this
task leaving the Blocked state and running again. */
if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
{
if( xClearOnExit != pdFALSE )
{
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
taskEXIT_CRITICAL();
xTimeoutOccurred = pdFALSE;
}
else
{
/* The task unblocked because the bits were set. Clear the control
bits before returning the value. */
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
}
}
traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
return uxReturn;
}
/*-----------------------------------------------------------*/
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
{
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
EventBits_t uxReturn;
/* Check the user is not attempting to clear the bits used by the kernel
itself. */
configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
taskENTER_CRITICAL();
{
traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
/* The value returned is the event group value prior to the bits being
cleared. */
uxReturn = pxEventBits->uxEventBits;
/* Clear the bits. */
pxEventBits->uxEventBits &= ~uxBitsToClear;
}
taskEXIT_CRITICAL();
return uxReturn;
}
/*-----------------------------------------------------------*/
EventBits_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
{
UBaseType_t uxSavedInterruptStatus;
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
EventBits_t uxReturn;
/* Check the user is not attempting to clear the bits used by the kernel
itself. */
configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
/* The value returned is the event group value prior to the bits being
cleared. */
uxReturn = pxEventBits->uxEventBits;
/* Clear the bits. */
pxEventBits->uxEventBits &= ~uxBitsToClear;
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
return uxReturn;
}
/*-----------------------------------------------------------*/
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
{
ListItem_t *pxListItem, *pxNext;
ListItem_t const *pxListEnd;
List_t *pxList;
EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
BaseType_t xMatchFound = pdFALSE;
/* Check the user is not attempting to set the bits used by the kernel
itself. */
configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
pxList = &( pxEventBits->xTasksWaitingForBits );
pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
vTaskSuspendAll();
{
traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
pxListItem = listGET_HEAD_ENTRY( pxList );
/* Set the bits. */
pxEventBits->uxEventBits |= uxBitsToSet;
/* See if the new bit value should unblock any tasks. */
while( pxListItem != pxListEnd )
{
pxNext = listGET_NEXT( pxListItem );
uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
xMatchFound = pdFALSE;
/* Split the bits waited for from the control bits. */
uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
{
/* Just looking for single bit being set. */
if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
{
xMatchFound = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
{
/* All bits are set. */
xMatchFound = pdTRUE;
}
else
{
/* Need all bits to be set, but not all the bits were set. */
}
if( xMatchFound != pdFALSE )
{
/* The bits match. Should the bits be cleared on exit? */
if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
{
uxBitsToClear |= uxBitsWaitedFor;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Store the actual event flag value in the task's event list
item before removing the task from the event list. The
eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
that is was unblocked due to its required bits matching, rather
than because it timed out. */
( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
}
/* Move onto the next list item. Note pxListItem->pxNext is not
used here as the list item may have been removed from the event list
and inserted into the ready/pending reading list. */
pxListItem = pxNext;
}
/* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
bit was set in the control word. */
pxEventBits->uxEventBits &= ~uxBitsToClear;
}
( void ) xTaskResumeAll();
return pxEventBits->uxEventBits;
}
/*-----------------------------------------------------------*/
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
{
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
vTaskSuspendAll();
{
traceEVENT_GROUP_DELETE( xEventGroup );
while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
{
/* Unblock the task, returning 0 as the event list is being deleted
and cannot therefore have any bits set. */
configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
}
vPortFree( pxEventBits );
}
( void ) xTaskResumeAll();
}
/*-----------------------------------------------------------*/
/* For internal use only - execute a 'set bits' command that was pended from
an interrupt. */
void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet )
{
( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet );
}
/*-----------------------------------------------------------*/
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits )
{
BaseType_t xWaitConditionMet = pdFALSE;
if( xWaitForAllBits == pdFALSE )
{
/* Task only has to wait for one bit within uxBitsToWaitFor to be
set. Is one already set? */
if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
{
xWaitConditionMet = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
/* Task has to wait for all the bits in uxBitsToWaitFor to be set.
Are they set already? */
if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
{
xWaitConditionMet = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
return xWaitConditionMet;
}
/*-----------------------------------------------------------*/
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken )
{
BaseType_t xReturn;
traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if (configUSE_TRACE_FACILITY == 1)
UBaseType_t uxEventGroupGetNumber( void* xEventGroup )
{
UBaseType_t xReturn;
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
if( xEventGroup == NULL )
{
xReturn = 0;
}
else
{
xReturn = pxEventBits->uxEventGroupNumber;
}
return xReturn;
}
#endif

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -65,12 +66,30 @@
#ifndef INC_FREERTOS_H #ifndef INC_FREERTOS_H
#define INC_FREERTOS_H #define INC_FREERTOS_H
/* /*
* Include the generic headers required for the FreeRTOS port being used. * Include the generic headers required for the FreeRTOS port being used.
*/ */
#include <stddef.h> #include <stddef.h>
/*
* If stdint.h cannot be located then:
* + If using GCC ensure the -nostdint options is *not* being used.
* + Ensure the project's include path includes the directory in which your
* compiler stores stdint.h.
* + Set any compiler options necessary for it to support C99, as technically
* stdint.h is only mandatory with C99 (FreeRTOS does not require C99 in any
* other way).
* + The FreeRTOS download includes a simple stdint.h definition that can be
* used in cases where none is provided by the compiler. The files only
* contains the typedefs required to build FreeRTOS. Read the instructions
* in FreeRTOS/source/stdint.readme for more information.
*/
#include <stdint.h> /* READ COMMENT ABOVE. */
#ifdef __cplusplus
extern "C" {
#endif
/* Basic FreeRTOS definitions. */ /* Basic FreeRTOS definitions. */
#include "projdefs.h" #include "projdefs.h"
@ -86,63 +105,72 @@ is included as it is used by the port layer. */
/* Definitions specific to the port being used. */ /* Definitions specific to the port being used. */
#include "portable.h" #include "portable.h"
/* Defines the prototype to which the application task hook function must
conform. */
typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
/* /*
* Check all the required application specific macros have been defined. * Check all the required application specific macros have been defined.
* These macros are application specific and (as downloaded) are defined * These macros are application specific and (as downloaded) are defined
* within FreeRTOSConfig.h. * within FreeRTOSConfig.h.
*/ */
#ifndef configMINIMAL_STACK_SIZE
#error Missing definition: configMINIMAL_STACK_SIZE must be defined in FreeRTOSConfig.h. configMINIMAL_STACK_SIZE defines the size (in words) of the stack allocated to the idle task. Refer to the demo project provided for your port for a suitable value.
#endif
#ifndef configMAX_PRIORITIES
#error Missing definition: configMAX_PRIORITIES must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details.
#endif
#ifndef configUSE_PREEMPTION #ifndef configUSE_PREEMPTION
#error Missing definition: configUSE_PREEMPTION should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #error Missing definition: configUSE_PREEMPTION must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif #endif
#ifndef configUSE_IDLE_HOOK #ifndef configUSE_IDLE_HOOK
#error Missing definition: configUSE_IDLE_HOOK should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #error Missing definition: configUSE_IDLE_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif #endif
#ifndef configUSE_TICK_HOOK #ifndef configUSE_TICK_HOOK
#error Missing definition: configUSE_TICK_HOOK should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #error Missing definition: configUSE_TICK_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif #endif
#ifndef configUSE_CO_ROUTINES #ifndef configUSE_CO_ROUTINES
#error Missing definition: configUSE_CO_ROUTINES should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #error Missing definition: configUSE_CO_ROUTINES must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif #endif
#ifndef INCLUDE_vTaskPrioritySet #ifndef INCLUDE_vTaskPrioritySet
#error Missing definition: INCLUDE_vTaskPrioritySet should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #error Missing definition: INCLUDE_vTaskPrioritySet must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif #endif
#ifndef INCLUDE_uxTaskPriorityGet #ifndef INCLUDE_uxTaskPriorityGet
#error Missing definition: INCLUDE_uxTaskPriorityGet should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #error Missing definition: INCLUDE_uxTaskPriorityGet must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif #endif
#ifndef INCLUDE_vTaskDelete #ifndef INCLUDE_vTaskDelete
#error Missing definition: INCLUDE_vTaskDelete should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #error Missing definition: INCLUDE_vTaskDelete must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif #endif
#ifndef INCLUDE_vTaskSuspend #ifndef INCLUDE_vTaskSuspend
#error Missing definition: INCLUDE_vTaskSuspend should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #error Missing definition: INCLUDE_vTaskSuspend must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif #endif
#ifndef INCLUDE_vTaskDelayUntil #ifndef INCLUDE_vTaskDelayUntil
#error Missing definition: INCLUDE_vTaskDelayUntil should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #error Missing definition: INCLUDE_vTaskDelayUntil must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif #endif
#ifndef INCLUDE_vTaskDelay #ifndef INCLUDE_vTaskDelay
#error Missing definition: INCLUDE_vTaskDelay should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #error Missing definition: INCLUDE_vTaskDelay must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif #endif
#ifndef configUSE_16_BIT_TICKS #ifndef configUSE_16_BIT_TICKS
#error Missing definition: configUSE_16_BIT_TICKS should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif
#if configUSE_CO_ROUTINES != 0
#ifndef configMAX_CO_ROUTINE_PRIORITIES
#error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1.
#endif
#endif
#ifndef configMAX_PRIORITIES
#error configMAX_PRIORITIES must be defined to be greater than or equal to 1.
#endif #endif
#ifndef INCLUDE_xTaskGetIdleTaskHandle #ifndef INCLUDE_xTaskGetIdleTaskHandle
@ -217,6 +245,14 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
#define INCLUDE_xTaskResumeFromISR 1 #define INCLUDE_xTaskResumeFromISR 1
#endif #endif
#ifndef INCLUDE_xEventGroupSetBitFromISR
#define INCLUDE_xEventGroupSetBitFromISR 0
#endif
#ifndef INCLUDE_xTimerPendFunctionCall
#define INCLUDE_xTimerPendFunctionCall 0
#endif
#ifndef configASSERT #ifndef configASSERT
#define configASSERT( x ) #define configASSERT( x )
#define configASSERT_DEFINED 0 #define configASSERT_DEFINED 0
@ -262,6 +298,10 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
#define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB #define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB
#endif #endif
#ifndef portPRE_TASK_DELETE_HOOK
#define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxYieldPending )
#endif
#ifndef portSETUP_TCB #ifndef portSETUP_TCB
#define portSETUP_TCB( pxTCB ) ( void ) pxTCB #define portSETUP_TCB( pxTCB ) ( void ) pxTCB
#endif #endif
@ -276,7 +316,7 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
#endif #endif
#ifndef portPOINTER_SIZE_TYPE #ifndef portPOINTER_SIZE_TYPE
#define portPOINTER_SIZE_TYPE unsigned long #define portPOINTER_SIZE_TYPE uint32_t
#endif #endif
/* Remove any unused trace macros. */ /* Remove any unused trace macros. */
@ -511,6 +551,70 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
#define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue ) #define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue )
#endif #endif
#ifndef traceMALLOC
#define traceMALLOC( pvAddress, uiSize )
#endif
#ifndef traceFREE
#define traceFREE( pvAddress, uiSize )
#endif
#ifndef traceEVENT_GROUP_CREATE
#define traceEVENT_GROUP_CREATE( xEventGroup )
#endif
#ifndef traceEVENT_GROUP_CREATE_FAILED
#define traceEVENT_GROUP_CREATE_FAILED()
#endif
#ifndef traceEVENT_GROUP_SYNC_BLOCK
#define traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor )
#endif
#ifndef traceEVENT_GROUP_SYNC_END
#define traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred
#endif
#ifndef traceEVENT_GROUP_WAIT_BITS_BLOCK
#define traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor )
#endif
#ifndef traceEVENT_GROUP_WAIT_BITS_END
#define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred
#endif
#ifndef traceEVENT_GROUP_CLEAR_BITS
#define traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear )
#endif
#ifndef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR
#define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear )
#endif
#ifndef traceEVENT_GROUP_SET_BITS
#define traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet )
#endif
#ifndef traceEVENT_GROUP_SET_BITS_FROM_ISR
#define traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet )
#endif
#ifndef traceEVENT_GROUP_DELETE
#define traceEVENT_GROUP_DELETE( xEventGroup )
#endif
#ifndef tracePEND_FUNC_CALL
#define tracePEND_FUNC_CALL(xFunctionToPend, pvParameter1, ulParameter2, ret)
#endif
#ifndef tracePEND_FUNC_CALL_FROM_ISR
#define tracePEND_FUNC_CALL_FROM_ISR(xFunctionToPend, pvParameter1, ulParameter2, ret)
#endif
#ifndef traceQUEUE_REGISTRY_ADD
#define traceQUEUE_REGISTRY_ADD(xQueue, pcQueueName)
#endif
#ifndef configGENERATE_RUN_TIME_STATS #ifndef configGENERATE_RUN_TIME_STATS
#define configGENERATE_RUN_TIME_STATS 0 #define configGENERATE_RUN_TIME_STATS 0
#endif #endif
@ -538,7 +642,7 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
#endif #endif
#ifndef portPRIVILEGE_BIT #ifndef portPRIVILEGE_BIT
#define portPRIVILEGE_BIT ( ( unsigned portBASE_TYPE ) 0x00 ) #define portPRIVILEGE_BIT ( ( UBaseType_t ) 0x00 )
#endif #endif
#ifndef portYIELD_WITHIN_API #ifndef portYIELD_WITHIN_API
@ -605,8 +709,48 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
#endif #endif
/* For backward compatability. */ #ifndef configUSE_TRACE_FACILITY
#define eTaskStateGet eTaskGetState #define configUSE_TRACE_FACILITY 0
#endif
#ifndef mtCOVERAGE_TEST_MARKER
#define mtCOVERAGE_TEST_MARKER()
#endif
/* Definitions to allow backward compatibility with FreeRTOS versions prior to
V8 if desired. */
#ifndef configENABLE_BACKWARD_COMPATIBILITY
#define configENABLE_BACKWARD_COMPATIBILITY 1
#endif
#if configENABLE_BACKWARD_COMPATIBILITY == 1
#define eTaskStateGet eTaskGetState
#define portTickType TickType_t
#define xTaskHandle TaskHandle_t
#define xQueueHandle QueueHandle_t
#define xSemaphoreHandle SemaphoreHandle_t
#define xQueueSetHandle QueueSetHandle_t
#define xQueueSetMemberHandle QueueSetMemberHandle_t
#define xTimeOutType TimeOut_t
#define xMemoryRegion MemoryRegion_t
#define xTaskParameters TaskParameters_t
#define xTaskStatusType TaskStatus_t
#define xTimerHandle TimerHandle_t
#define xCoRoutineHandle CoRoutineHandle_t
#define pdTASK_HOOK_CODE TaskHookFunction_t
#define portTICK_RATE_MS portTICK_PERIOD_MS
/* Backward compatibility within the scheduler code only - these definitions
are not really required but are included for completeness. */
#define tmrTIMER_CALLBACK TimerCallbackFunction_t
#define pdTASK_CODE TaskFunction_t
#define xListItem ListItem_t
#define xList List_t
#endif /* configENABLE_BACKWARD_COMPATIBILITY */
#ifdef __cplusplus
}
#endif
#endif /* INC_FREERTOS_H */ #endif /* INC_FREERTOS_H */

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -107,7 +108,7 @@
/* Is the currently saved stack pointer within the stack limit? */ \ /* Is the currently saved stack pointer within the stack limit? */ \
if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \ if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \
{ \ { \
vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
} \ } \
} }
@ -123,7 +124,7 @@
/* Is the currently saved stack pointer within the stack limit? */ \ /* Is the currently saved stack pointer within the stack limit? */ \
if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \ if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \
{ \ { \
vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
} \ } \
} }
@ -132,20 +133,20 @@
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) )
#define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \
{ \ { \
static const unsigned char 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, \
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 }; \
\ \
\ \
/* Has the extremity of the task stack ever been written over? */ \ /* Has the extremity of the task stack ever been written over? */ \
if( memcmp( ( void * ) pxCurrentTCB->pxStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ if( memcmp( ( void * ) pxCurrentTCB->pxStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \
{ \ { \
vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
} \ } \
} }
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
@ -153,23 +154,23 @@
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) )
#define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \
{ \ { \
char *pcEndOfStack = ( char * ) pxCurrentTCB->pxEndOfStack; \ int8_t *pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \
static const unsigned char 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, \
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \
\ \
\ \
pcEndOfStack -= sizeof( ucExpectedStackBytes ); \ pcEndOfStack -= sizeof( ucExpectedStackBytes ); \
\ \
/* Has the extremity of the task stack ever been written over? */ \ /* Has the extremity of the task stack ever been written over? */ \
if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \
{ \ { \
vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
} \ } \
} }
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -78,28 +79,28 @@ extern "C" {
/* 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 * xCoRoutineHandle; 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)( xCoRoutineHandle, unsigned portBASE_TYPE ); typedef void (*crCOROUTINE_CODE)( CoRoutineHandle_t, UBaseType_t );
typedef struct corCoRoutineControlBlock typedef struct corCoRoutineControlBlock
{ {
crCOROUTINE_CODE pxCoRoutineFunction; crCOROUTINE_CODE pxCoRoutineFunction;
xListItem 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. */
xListItem xEventListItem; /*< List item used to place the CRCB in event lists. */ ListItem_t xEventListItem; /*< List item used to place the CRCB in event lists. */
unsigned portBASE_TYPE 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. */
unsigned portBASE_TYPE 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. */
unsigned short uxState; /*< Used internally by the co-routine implementation. */ uint16_t uxState; /*< Used internally by the co-routine implementation. */
} corCRCB; /* Co-routine control block. Note must be identical in size down to uxPriority with tskTCB. */ } CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */
/** /**
* croutine. h * croutine. h
*<pre> *<pre>
portBASE_TYPE xCoRoutineCreate( BaseType_t xCoRoutineCreate(
crCOROUTINE_CODE pxCoRoutineCode, crCOROUTINE_CODE pxCoRoutineCode,
unsigned portBASE_TYPE uxPriority, UBaseType_t uxPriority,
unsigned portBASE_TYPE 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
@ -122,12 +123,12 @@ typedef struct corCoRoutineControlBlock
* Example usage: * Example usage:
<pre> <pre>
// Co-routine to be created. // Co-routine to be created.
void vFlashCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE 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 portTickType 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 );
@ -137,7 +138,7 @@ typedef struct corCoRoutineControlBlock
// 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 long 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 ] );
@ -150,9 +151,9 @@ typedef struct corCoRoutineControlBlock
// Function that creates two co-routines. // Function that creates two co-routines.
void vOtherFunction( void ) void vOtherFunction( void )
{ {
unsigned char ucParameterToPass; uint8_t ucParameterToPass;
xTaskHandle 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.
@ -165,7 +166,7 @@ typedef struct corCoRoutineControlBlock
* \defgroup xCoRoutineCreate xCoRoutineCreate * \defgroup xCoRoutineCreate xCoRoutineCreate
* \ingroup Tasks * \ingroup Tasks
*/ */
signed portBASE_TYPE xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex ); BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex );
/** /**
@ -212,17 +213,17 @@ void vCoRoutineSchedule( void );
/** /**
* croutine. h * croutine. h
* <pre> * <pre>
crSTART( xCoRoutineHandle 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( xCoRoutineHandle xHandle, unsigned portBASE_TYPE 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 long 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 );
@ -238,7 +239,7 @@ void vCoRoutineSchedule( void );
* \defgroup crSTART crSTART * \defgroup crSTART crSTART
* \ingroup Tasks * \ingroup Tasks
*/ */
#define crSTART( pxCRCB ) switch( ( ( corCRCB * )( pxCRCB ) )->uxState ) { case 0: #define crSTART( pxCRCB ) switch( ( ( CRCB_t * )( pxCRCB ) )->uxState ) { case 0:
/** /**
* croutine. h * croutine. h
@ -250,10 +251,10 @@ void vCoRoutineSchedule( void );
* Example usage: * Example usage:
<pre> <pre>
// Co-routine to be created. // Co-routine to be created.
void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE 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 long 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 );
@ -275,13 +276,13 @@ void vCoRoutineSchedule( void );
* 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 ) ( ( corCRCB * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2): #define crSET_STATE0( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2):
#define crSET_STATE1( xHandle ) ( ( corCRCB * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1): #define crSET_STATE1( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1):
/** /**
* croutine. h * croutine. h
*<pre> *<pre>
crDELAY( xCoRoutineHandle xHandle, portTickType 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.
* *
@ -294,18 +295,18 @@ void vCoRoutineSchedule( void );
* *
* @param xTickToDelay The number of ticks that the co-routine should delay * @param xTickToDelay The number of ticks that the co-routine should delay
* for. The actual amount of time this equates to is defined by * for. The actual amount of time this equates to is defined by
* configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_RATE_MS * configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_PERIOD_MS
* 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( xCoRoutineHandle xHandle, unsigned portBASE_TYPE 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_RATE_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 );
@ -334,11 +335,11 @@ void vCoRoutineSchedule( void );
/** /**
* <pre> * <pre>
crQUEUE_SEND( crQUEUE_SEND(
xCoRoutineHandle xHandle, CoRoutineHandle_t xHandle,
xQueueHandle pxQueue, QueueHandle_t pxQueue,
void *pvItemToQueue, void *pvItemToQueue,
portTickType xTicksToWait, TickType_t xTicksToWait,
portBASE_TYPE *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
@ -371,7 +372,7 @@ void vCoRoutineSchedule( void );
* to wait for space to become available on the queue, should space not be * to wait for space to become available on the queue, should space not be
* available immediately. The actual amount of time this equates to is defined * available immediately. The actual amount of time this equates to is defined
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
* portTICK_RATE_MS can be used to convert ticks to milliseconds (see example * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see example
* below). * below).
* *
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if * @param pxResult The variable pointed to by pxResult will be set to pdPASS if
@ -382,11 +383,11 @@ void vCoRoutineSchedule( void );
<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( xCoRoutineHandle xHandle, unsigned portBASE_TYPE 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 portBASE_TYPE xNumberToPost = 0; static BaseType_t xNumberToPost = 0;
static portBASE_TYPE 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 );
@ -433,11 +434,11 @@ void vCoRoutineSchedule( void );
* croutine. h * croutine. h
* <pre> * <pre>
crQUEUE_RECEIVE( crQUEUE_RECEIVE(
xCoRoutineHandle xHandle, CoRoutineHandle_t xHandle,
xQueueHandle pxQueue, QueueHandle_t pxQueue,
void *pvBuffer, void *pvBuffer,
portTickType xTicksToWait, TickType_t xTicksToWait,
portBASE_TYPE *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
@ -469,7 +470,7 @@ void vCoRoutineSchedule( void );
* to wait for data to become available from the queue, should data not be * to wait for data to become available from the queue, should data not be
* available immediately. The actual amount of time this equates to is defined * available immediately. The actual amount of time this equates to is defined
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
* portTICK_RATE_MS can be used to convert ticks to milliseconds (see the * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see the
* crQUEUE_SEND example). * crQUEUE_SEND example).
* *
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if * @param pxResult The variable pointed to by pxResult will be set to pdPASS if
@ -480,11 +481,11 @@ void vCoRoutineSchedule( void );
<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( xCoRoutineHandle xHandle, unsigned portBASE_TYPE 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 portBASE_TYPE xResult; static BaseType_t xResult;
static unsigned portBASE_TYPE 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 );
@ -525,9 +526,9 @@ void vCoRoutineSchedule( void );
* croutine. h * croutine. h
* <pre> * <pre>
crQUEUE_SEND_FROM_ISR( crQUEUE_SEND_FROM_ISR(
xQueueHandle pxQueue, QueueHandle_t pxQueue,
void *pvItemToQueue, void *pvItemToQueue,
portBASE_TYPE 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
@ -565,10 +566,10 @@ void vCoRoutineSchedule( void );
* 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( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
{ {
char cRxedChar; char cRxedChar;
portBASE_TYPE 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 );
@ -595,7 +596,7 @@ void vCoRoutineSchedule( void );
void vUART_ISR( void ) void vUART_ISR( void )
{ {
char cRxedChar; char cRxedChar;
portBASE_TYPE 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() )
@ -622,9 +623,9 @@ void vCoRoutineSchedule( void );
* croutine. h * croutine. h
* <pre> * <pre>
crQUEUE_SEND_FROM_ISR( crQUEUE_SEND_FROM_ISR(
xQueueHandle pxQueue, QueueHandle_t pxQueue,
void *pvBuffer, void *pvBuffer,
portBASE_TYPE * 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
@ -663,12 +664,12 @@ void vCoRoutineSchedule( void );
<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( xCoRoutineHandle xHandle, unsigned portBASE_TYPE 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';
portBASE_TYPE 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 );
@ -711,7 +712,7 @@ void vCoRoutineSchedule( void );
void vUART_ISR( void ) void vUART_ISR( void )
{ {
char cCharToTx; char cCharToTx;
portBASE_TYPE xCRWokenByPost = pdFALSE; BaseType_t xCRWokenByPost = pdFALSE;
while( UART_TX_REG_EMPTY() ) while( UART_TX_REG_EMPTY() )
{ {
@ -739,7 +740,7 @@ 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( portTickType xTicksToDelay, xList *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.
@ -748,7 +749,7 @@ void vCoRoutineAddToDelayedList( portTickType xTicksToDelay, xList *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.
*/ */
signed portBASE_TYPE xCoRoutineRemoveFromEventList( const xList *pxEventList ); BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList );
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -0,0 +1,680 @@
/*
FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that has become a de facto standard. *
* *
* Help yourself get started quickly and support the FreeRTOS *
* project by purchasing a FreeRTOS tutorial book, reference *
* manual, or both from: http://www.FreeRTOS.org/Documentation *
* *
* Thank you! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
>>! NOTE: The modification to the GPL is included to allow you to distribute
>>! a combined work that includes FreeRTOS without being obliged to provide
>>! the source code for proprietary components outside of the FreeRTOS
>>! kernel.
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available from the following
link: http://www.freertos.org/a00114.html
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong?" *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
license and Real Time Engineers Ltd. contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
#ifndef EVENT_GROUPS_H
#define EVENT_GROUPS_H
#ifndef INC_FREERTOS_H
#error "include FreeRTOS.h" must appear in source files before "include event_groups.h"
#endif
#include "timers.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* An event group is a collection of bits to which an application can assign a
* meaning. For example, an application may create an event group to convey
* the status of various CAN bus related events in which bit 0 might mean "A CAN
* message has been received and is ready for processing", bit 1 might mean "The
* application has queued a message that is ready for sending onto the CAN
* network", and bit 2 might mean "It is time to send a SYNC message onto the
* CAN network" etc. A task can then test the bit values to see which events
* are active, and optionally enter the Blocked state to wait for a specified
* bit or a group of specified bits to be active. To continue the CAN bus
* example, a CAN controlling task can enter the Blocked state (and therefore
* not consume any processing time) until either bit 0, bit 1 or bit 2 are
* active, at which time the bit that was actually active would inform the task
* which action it had to take (process a received message, send a message, or
* send a SYNC).
*
* The event groups implementation contains intelligence to avoid race
* conditions that would otherwise occur were an application to use a simple
* variable for the same purpose. This is particularly important with respect
* to when a bit within an event group is to be cleared, and when bits have to
* be set and then tested atomically - as is the case where event groups are
* used to create a synchronisation point between multiple tasks (a
* 'rendezvous').
*
* \defgroup EventGroup
*/
/**
* event_groups.h
*
* Type by which event groups are referenced. For example, a call to
* xEventGroupCreate() returns an EventGroupHandle_t variable that can then
* be used as a parameter to other event group functions.
*
* \defgroup EventGroupHandle_t EventGroupHandle_t
* \ingroup EventGroup
*/
typedef void * EventGroupHandle_t;
/*
* The type that holds event bits always matches TickType_t - therefore the
* number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to 1,
* 32 bits if set to 0.
*
* \defgroup EventBits_t EventBits_t
* \ingroup EventGroup
*/
typedef TickType_t EventBits_t;
/**
* event_groups.h
*<pre>
EventGroupHandle_t xEventGroupCreate( void );
</pre>
*
* Create a new event group. This function cannot be called from an interrupt.
*
* Although event groups are not related to ticks, for internal implementation
* reasons the number of bits available for use in an event group is dependent
* on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If
* configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit
* 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has
* 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store
* event bits within an event group.
*
* @return If the event group was created then a handle to the event group is
* returned. If there was insufficient FreeRTOS heap available to create the
* event group then NULL is returned. See http://www.freertos.org/a00111.html
*
* Example usage:
<pre>
// Declare a variable to hold the created event group.
EventGroupHandle_t xCreatedEventGroup;
// Attempt to create the event group.
xCreatedEventGroup = xEventGroupCreate();
// Was the event group created successfully?
if( xCreatedEventGroup == NULL )
{
// The event group was not created because there was insufficient
// FreeRTOS heap available.
}
else
{
// The event group was created.
}
</pre>
* \defgroup xEventGroupCreate xEventGroupCreate
* \ingroup EventGroup
*/
EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
*<pre>
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits,
const TickType_t xTicksToWait );
</pre>
*
* [Potentially] block to wait for one or more bits to be set within a
* previously created event group.
*
* This function cannot be called from an interrupt.
*
* @param xEventGroup The event group in which the bits are being tested. The
* event group must have previously been created using a call to
* xEventGroupCreate().
*
* @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
* inside the event group. For example, to wait for bit 0 and/or bit 2 set
* uxBitsToWaitFor to 0x05. To wait for bits 0 and/or bit 1 and/or bit 2 set
* uxBitsToWaitFor to 0x07. Etc.
*
* @param xClearOnExit If xClearOnExit is set to pdTRUE then any bits within
* uxBitsToWaitFor that are set within the event group will be cleared before
* xEventGroupWaitBits() returns if the wait condition was met (if the function
* returns for a reason other than a timeout). If xClearOnExit is set to
* pdFALSE then the bits set in the event group are not altered when the call to
* xEventGroupWaitBits() returns.
*
* @param xWaitForAllBits If xWaitForAllBits is set to pdTRUE then
* xEventGroupWaitBits() will return when either all the bits in uxBitsToWaitFor
* are set or the specified block time expires. If xWaitForAllBits is set to
* pdFALSE then xEventGroupWaitBits() will return when any one of the bits set
* in uxBitsToWaitFor is set or the specified block time expires. The block
* time is specified by the xTicksToWait parameter.
*
* @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
* for one/all (depending on the xWaitForAllBits value) of the bits specified by
* uxBitsToWaitFor to become set.
*
* @return The value of the event group at the time either the bits being waited
* for became set, or the block time expired. Test the return value to know
* which bits were set. If xEventGroupWaitBits() returned because its timeout
* expired then not all the bits being waited for will be set. If
* xEventGroupWaitBits() returned because the bits it was waiting for were set
* then the returned value is the event group value before any bits were
* automatically cleared in the case that xClearOnExit parameter was set to
* pdTRUE.
*
* Example usage:
<pre>
#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )
void aFunction( EventGroupHandle_t xEventGroup )
{
EventBits_t uxBits;
const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
// Wait a maximum of 100ms for either bit 0 or bit 4 to be set within
// the event group. Clear the bits before exiting.
uxBits = xEventGroupWaitBits(
xEventGroup, // The event group being tested.
BIT_0 | BIT_4, // The bits within the event group to wait for.
pdTRUE, // BIT_0 and BIT_4 should be cleared before returning.
pdFALSE, // Don't wait for both bits, either bit will do.
xTicksToWait ); // Wait a maximum of 100ms for either bit to be set.
if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
{
// xEventGroupWaitBits() returned because both bits were set.
}
else if( ( uxBits & BIT_0 ) != 0 )
{
// xEventGroupWaitBits() returned because just BIT_0 was set.
}
else if( ( uxBits & BIT_4 ) != 0 )
{
// xEventGroupWaitBits() returned because just BIT_4 was set.
}
else
{
// xEventGroupWaitBits() returned because xTicksToWait ticks passed
// without either BIT_0 or BIT_4 becoming set.
}
}
</pre>
* \defgroup xEventGroupWaitBits xEventGroupWaitBits
* \ingroup EventGroup
*/
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
*<pre>
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
</pre>
*
* Clear bits within an event group. This function cannot be called from an
* interrupt.
*
* @param xEventGroup The event group in which the bits are to be cleared.
*
* @param uxBitsToClear A bitwise value that indicates the bit or bits to clear
* in the event group. For example, to clear bit 3 only, set uxBitsToClear to
* 0x08. To clear bit 3 and bit 0 set uxBitsToClear to 0x09.
*
* @return The value of the event group before the specified bits were cleared.
*
* Example usage:
<pre>
#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )
void aFunction( EventGroupHandle_t xEventGroup )
{
EventBits_t uxBits;
// Clear bit 0 and bit 4 in xEventGroup.
uxBits = xEventGroupClearBits(
xEventGroup, // The event group being updated.
BIT_0 | BIT_4 );// The bits being cleared.
if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
{
// Both bit 0 and bit 4 were set before xEventGroupClearBits() was
// called. Both will now be clear (not set).
}
else if( ( uxBits & BIT_0 ) != 0 )
{
// Bit 0 was set before xEventGroupClearBits() was called. It will
// now be clear.
}
else if( ( uxBits & BIT_4 ) != 0 )
{
// Bit 4 was set before xEventGroupClearBits() was called. It will
// now be clear.
}
else
{
// Neither bit 0 nor bit 4 were set in the first place.
}
}
</pre>
* \defgroup xEventGroupClearBits xEventGroupClearBits
* \ingroup EventGroup
*/
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
*<pre>
EventBits_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
</pre>
*
* A version of xEventGroupClearBits() that can be called from an interrupt
* service routine. See the xEventGroupClearBits() documentation.
*
* \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR
* \ingroup EventGroup
*/
EventBits_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
*<pre>
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
</pre>
*
* Set bits within an event group.
* This function cannot be called from an interrupt. xEventGroupSetBitsFromISR()
* is a version that can be called from an interrupt.
*
* Setting bits in an event group will automatically unblock tasks that are
* blocked waiting for the bits.
*
* @param xEventGroup The event group in which the bits are to be set.
*
* @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
* For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3
* and bit 0 set uxBitsToSet to 0x09.
*
* @return The value of the event group at the time the call to
* xEventGroupSetBits() returns. There are two reasons why the returned value
* might have the bits specified by the uxBitsToSet parameter cleared. First,
* if setting a bit results in a task that was waiting for the bit leaving the
* blocked state then it is possible the bit will be cleared automatically
* (see the xClearBitOnExit parameter of xEventGroupWaitBits()). Second, any
* unblocked (or otherwise Ready state) task that has a priority above that of
* the task that called xEventGroupSetBits() will execute and may change the
* event group value before the call to xEventGroupSetBits() returns.
*
* Example usage:
<pre>
#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )
void aFunction( EventGroupHandle_t xEventGroup )
{
EventBits_t uxBits;
// Set bit 0 and bit 4 in xEventGroup.
uxBits = xEventGroupSetBits(
xEventGroup, // The event group being updated.
BIT_0 | BIT_4 );// The bits being set.
if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
{
// Both bit 0 and bit 4 remained set when the function returned.
}
else if( ( uxBits & BIT_0 ) != 0 )
{
// Bit 0 remained set when the function returned, but bit 4 was
// cleared. It might be that bit 4 was cleared automatically as a
// task that was waiting for bit 4 was removed from the Blocked
// state.
}
else if( ( uxBits & BIT_4 ) != 0 )
{
// Bit 4 remained set when the function returned, but bit 0 was
// cleared. It might be that bit 0 was cleared automatically as a
// task that was waiting for bit 0 was removed from the Blocked
// state.
}
else
{
// Neither bit 0 nor bit 4 remained set. It might be that a task
// was waiting for both of the bits to be set, and the bits were
// cleared as the task left the Blocked state.
}
}
</pre>
* \defgroup xEventGroupSetBits xEventGroupSetBits
* \ingroup EventGroup
*/
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
*<pre>
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
</pre>
*
* A version of xEventGroupSetBits() that can be called from an interrupt.
*
* Setting bits in an event group is not a deterministic operation because there
* are an unknown number of tasks that may be waiting for the bit or bits being
* set. FreeRTOS does not allow nondeterministic operations to be performed in
* interrupts or from critical sections. Therefore xEventGroupSetBitFromISR()
* sends a message to the timer task to have the set operation performed in the
* context of the timer task - where a scheduler lock is used in place of a
* critical section.
*
* @param xEventGroup The event group in which the bits are to be set.
*
* @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
* For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3
* and bit 0 set uxBitsToSet to 0x09.
*
* @param pxHigherPriorityTaskWoken As mentioned above, calling this function
* will result in a message being sent to the timer daemon task. If the
* priority of the timer daemon task is higher than the priority of the
* currently running task (the task the interrupt interrupted) then
* *pxHigherPriorityTaskWoken will be set to pdTRUE by
* xEventGroupSetBitsFromISR(), indicating that a context switch should be
* requested before the interrupt exits. For that reason
* *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the
* example code below.
*
* @return If the request to execute the function was posted successfully then
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
* if the timer service queue was full.
*
* Example usage:
<pre>
#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )
// An event group which it is assumed has already been created by a call to
// xEventGroupCreate().
EventGroupHandle_t xEventGroup;
void anInterruptHandler( void )
{
BaseType_t xHigherPriorityTaskWoken, xResult;
// xHigherPriorityTaskWoken must be initialised to pdFALSE.
xHigherPriorityTaskWoken = pdFALSE;
// Set bit 0 and bit 4 in xEventGroup.
xResult = xEventGroupSetBitsFromISR(
xEventGroup, // The event group being updated.
BIT_0 | BIT_4 // The bits being set.
&xHigherPriorityTaskWoken );
// Was the message posted successfully?
if( xResult == pdPASS )
{
// If xHigherPriorityTaskWoken is now set to pdTRUE then a context
// switch should be requested. The macro used is port specific and
// will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
// refer to the documentation page for the port being used.
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
}
</pre>
* \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR
* \ingroup EventGroup
*/
#if( configUSE_TRACE_FACILITY == 1 )
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
#else
#define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken )
#endif
/**
* event_groups.h
*<pre>
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
const EventBits_t uxBitsToWaitFor,
TickType_t xTicksToWait );
</pre>
*
* Atomically set bits within an event group, then wait for a combination of
* bits to be set within the same event group. This functionality is typically
* used to synchronise multiple tasks, where each task has to wait for the other
* tasks to reach a synchronisation point before proceeding.
*
* This function cannot be used from an interrupt.
*
* The function will return before its block time expires if the bits specified
* by the uxBitsToWait parameter are set, or become set within that time. In
* this case all the bits specified by uxBitsToWait will be automatically
* cleared before the function returns.
*
* @param xEventGroup The event group in which the bits are being tested. The
* event group must have previously been created using a call to
* xEventGroupCreate().
*
* @param uxBitsToSet The bits to set in the event group before determining
* if, and possibly waiting for, all the bits specified by the uxBitsToWait
* parameter are set.
*
* @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
* inside the event group. For example, to wait for bit 0 and bit 2 set
* uxBitsToWaitFor to 0x05. To wait for bits 0 and bit 1 and bit 2 set
* uxBitsToWaitFor to 0x07. Etc.
*
* @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
* for all of the bits specified by uxBitsToWaitFor to become set.
*
* @return The value of the event group at the time either the bits being waited
* for became set, or the block time expired. Test the return value to know
* which bits were set. If xEventGroupSync() returned because its timeout
* expired then not all the bits being waited for will be set. If
* xEventGroupSync() returned because all the bits it was waiting for were
* set then the returned value is the event group value before any bits were
* automatically cleared.
*
* Example usage:
<pre>
// Bits used by the three tasks.
#define TASK_0_BIT ( 1 << 0 )
#define TASK_1_BIT ( 1 << 1 )
#define TASK_2_BIT ( 1 << 2 )
#define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )
// Use an event group to synchronise three tasks. It is assumed this event
// group has already been created elsewhere.
EventGroupHandle_t xEventBits;
void vTask0( void *pvParameters )
{
EventBits_t uxReturn;
TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
for( ;; )
{
// Perform task functionality here.
// Set bit 0 in the event flag to note this task has reached the
// sync point. The other two tasks will set the other two bits defined
// by ALL_SYNC_BITS. All three tasks have reached the synchronisation
// point when all the ALL_SYNC_BITS are set. Wait a maximum of 100ms
// for this to happen.
uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait );
if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
{
// All three tasks reached the synchronisation point before the call
// to xEventGroupSync() timed out.
}
}
}
void vTask1( void *pvParameters )
{
for( ;; )
{
// Perform task functionality here.
// Set bit 1 in the event flag to note this task has reached the
// synchronisation point. The other two tasks will set the other two
// bits defined by ALL_SYNC_BITS. All three tasks have reached the
// synchronisation point when all the ALL_SYNC_BITS are set. Wait
// indefinitely for this to happen.
xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );
// xEventGroupSync() was called with an indefinite block time, so
// this task will only reach here if the syncrhonisation was made by all
// three tasks, so there is no need to test the return value.
}
}
void vTask2( void *pvParameters )
{
for( ;; )
{
// Perform task functionality here.
// Set bit 2 in the event flag to note this task has reached the
// synchronisation point. The other two tasks will set the other two
// bits defined by ALL_SYNC_BITS. All three tasks have reached the
// synchronisation point when all the ALL_SYNC_BITS are set. Wait
// indefinitely for this to happen.
xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );
// xEventGroupSync() was called with an indefinite block time, so
// this task will only reach here if the syncrhonisation was made by all
// three tasks, so there is no need to test the return value.
}
}
</pre>
* \defgroup xEventGroupSync xEventGroupSync
* \ingroup EventGroup
*/
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
*<pre>
EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
</pre>
*
* Returns the current value of the bits in an event group. This function
* cannot be used from an interrupt.
*
* @param xEventGroup The event group being queried.
*
* @return The event group bits at the time xEventGroupGetBits() was called.
*
* \defgroup xEventGroupGetBits xEventGroupGetBits
* \ingroup EventGroup
*/
#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 )
/**
* event_groups.h
*<pre>
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
</pre>
*
* A version of xEventGroupGetBits() that can be called from an ISR.
*
* @param xEventGroup The event group being queried.
*
* @return The event group bits at the time xEventGroupGetBitsFromISR() was called.
*
* \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR
* \ingroup EventGroup
*/
#define xEventGroupGetBitsFromISR( xEventGroup ) xEventGroupClearBitsFromISR( xEventGroup, 0 )
/**
* event_groups.h
*<pre>
void xEventGroupDelete( EventGroupHandle_t xEventGroup );
</pre>
*
* Delete an event group that was previously created by a call to
* xEventGroupCreate(). Tasks that are blocked on the event group will be
* unblocked and obtain 0 as the event group's value.
*
* @param xEventGroup The event group being deleted.
*/
void vEventGroupDelete( EventGroupHandle_t xEventGroup );
/* For internal use only. */
void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet );
#if (configUSE_TRACE_FACILITY == 1)
UBaseType_t uxEventGroupGetNumber( void* xEventGroup );
#endif
#ifdef __cplusplus
}
#endif
#endif /* EVENT_GROUPS_H */

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -67,7 +68,7 @@
* heavily for the schedulers needs, it is also available for use by * heavily for the schedulers needs, it is also available for use by
* application code. * application code.
* *
* xLists can only store pointers to xListItems. Each xListItem contains a * list_ts can only store pointers to list_item_ts. Each ListItem_t contains a
* numeric value (xItemValue). Most of the time the lists are sorted in * numeric value (xItemValue). Most of the time the lists are sorted in
* descending item value order. * descending item value order.
* *
@ -114,8 +115,8 @@
* complete and obvious failure of the scheduler. If this is ever experienced * complete and obvious failure of the scheduler. If this is ever experienced
* then the volatile qualifier can be inserted in the relevant places within the * then the volatile qualifier can be inserted in the relevant places within the
* list structures by simply defining configLIST_VOLATILE to volatile in * list structures by simply defining configLIST_VOLATILE to volatile in
* FreeRTOSConfig.h (as per the example at the bottom of this comment block). * FreeRTOSConfig.h (as per the example at the bottom of this comment block).
* If configLIST_VOLATILE is not defined then the preprocessor directives below * If configLIST_VOLATILE is not defined then the preprocessor directives below
* will simply #define configLIST_VOLATILE away completely. * will simply #define configLIST_VOLATILE away completely.
* *
* To use volatile list structure members then add the following line to * To use volatile list structure members then add the following line to
@ -134,31 +135,31 @@ extern "C" {
*/ */
struct xLIST_ITEM struct xLIST_ITEM
{ {
configLIST_VOLATILE portTickType 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 xListItem in the list. */ struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;/*< Pointer to the previous xListItem in the list. */ struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */
void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */
void * configLIST_VOLATILE pvContainer; /*< Pointer to the list in which this list item is placed (if any). */ void * configLIST_VOLATILE pvContainer; /*< Pointer to the list in which this list item is placed (if any). */
}; };
typedef struct xLIST_ITEM xListItem; /* 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
{ {
configLIST_VOLATILE portTickType 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 xMiniListItem; 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
{ {
configLIST_VOLATILE unsigned portBASE_TYPE uxNumberOfItems; configLIST_VOLATILE UBaseType_t uxNumberOfItems;
xListItem * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to pvListGetOwnerOfNextEntry (). */ 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 (). */
xMiniListItem 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. */
} xList; } 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 +177,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 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
@ -185,26 +186,50 @@ 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
* represent anything - for example a the priority of a task, or the time at * represent anything - for example the priority of a task, or the time at
* which a task should be unblocked. * which a task should be unblocked.
* *
* \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 the 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
* list. * list.
* *
* \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.
*
* \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY
* \ingroup LinkedList
*/
#define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext )
/*
* Return the list item at the head of the list.
*
* \page listGET_NEXT listGET_NEXT
* \ingroup LinkedList
*/
#define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext )
/*
* Return the list item that marks the end of the list
*
* \page listGET_END_MARKER listGET_END_MARKER
* \ingroup LinkedList
*/
#define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )
/* /*
* Access macro to determine if a list contains any items. The macro will * Access macro to determine if a list contains any items. The macro will
@ -213,19 +238,19 @@ 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 ) ( ( portBASE_TYPE ) ( ( pxList )->uxNumberOfItems == ( unsigned portBASE_TYPE ) 0 ) ) #define listLIST_IS_EMPTY( pxList ) ( ( BaseType_t ) ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) )
/* /*
* 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.
* *
* The list member pxIndex is used to walk through a list. Calling * The list member pxIndex is used to walk through a list. Calling
* listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list
* and returns that entries pxOwner parameter. Using multiple calls to this * and returns that entry's pxOwner parameter. Using multiple calls to this
* function it is therefore possible to move through every item contained in * function it is therefore possible to move through every item contained in
* a list. * a list.
* *
@ -234,6 +259,7 @@ typedef struct xLIST
* The pxOwner parameter effectively creates a two way link between the list * The pxOwner parameter effectively creates a two way link between the list
* item and its owner. * item and its owner.
* *
* @param pxTCB pxTCB is set to the address of the owner of the next list item.
* @param pxList The list from which the next item owner is to be returned. * @param pxList The list from which the next item owner is to be returned.
* *
* \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY
@ -241,7 +267,7 @@ typedef struct xLIST
*/ */
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ #define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \
{ \ { \
xList * 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; \
@ -278,16 +304,15 @@ xList * const pxConstList = ( pxList ); \
* *
* @param pxList The list we want to know if the list item is within. * @param pxList The list we want to know if the list item is within.
* @param pxListItem The list item we want to know if is in the list. * @param pxListItem The list item we want to know if is in the list.
* @return pdTRUE is the list item is in the list, otherwise pdFALSE. * @return pdTRUE if the list item is in the list, otherwise pdFALSE.
* pointer against
*/ */
#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( portBASE_TYPE ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) ) #define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( BaseType_t ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) )
/* /*
* Return the list a list item is contained within (referenced from). * Return the list a list item is contained within (referenced from).
* *
* @param pxListItem The list item being queried. * @param pxListItem The list item being queried.
* @return A pointer to the xList object that references the pxListItem * @return A pointer to the List_t object that references the pxListItem
*/ */
#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pvContainer ) #define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pvContainer )
@ -308,7 +333,7 @@ xList * const pxConstList = ( pxList ); \
* \page vListInitialise vListInitialise * \page vListInitialise vListInitialise
* \ingroup LinkedList * \ingroup LinkedList
*/ */
void vListInitialise( xList * const pxList ); void vListInitialise( List_t * const pxList );
/* /*
* 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
@ -319,7 +344,7 @@ void vListInitialise( xList * const pxList );
* \page vListInitialiseItem vListInitialiseItem * \page vListInitialiseItem vListInitialiseItem
* \ingroup LinkedList * \ingroup LinkedList
*/ */
void vListInitialiseItem( xListItem * const pxItem ); void vListInitialiseItem( ListItem_t * const pxItem );
/* /*
* 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
@ -327,12 +352,12 @@ void vListInitialiseItem( xListItem * const pxItem );
* *
* @param pxList The list into which the item is to be inserted. * @param pxList The list into which the item is to be inserted.
* *
* @param pxNewListItem The item to that is to be placed in the list. * @param pxNewListItem The item that is to be placed in the list.
* *
* \page vListInsert vListInsert * \page vListInsert vListInsert
* \ingroup LinkedList * \ingroup LinkedList
*/ */
void vListInsert( xList * const pxList, xListItem * const pxNewListItem ); void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem );
/* /*
* 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
@ -353,7 +378,7 @@ void vListInsert( xList * const pxList, xListItem * const pxNewListItem );
* \page vListInsertEnd vListInsertEnd * \page vListInsertEnd vListInsertEnd
* \ingroup LinkedList * \ingroup LinkedList
*/ */
void vListInsertEnd( xList * const pxList, xListItem * const pxNewListItem ); void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem );
/* /*
* 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
@ -368,7 +393,7 @@ void vListInsertEnd( xList * const pxList, xListItem * const pxNewListItem );
* \page uxListRemove uxListRemove * \page uxListRemove uxListRemove
* \ingroup LinkedList * \ingroup LinkedList
*/ */
unsigned portBASE_TYPE uxListRemove( xListItem * const pxItemToRemove ); UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove );
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -83,7 +84,6 @@ only for ports that are using the MPU. */
#define vTaskPrioritySet MPU_vTaskPrioritySet #define vTaskPrioritySet MPU_vTaskPrioritySet
#define eTaskGetState MPU_eTaskGetState #define eTaskGetState MPU_eTaskGetState
#define vTaskSuspend MPU_vTaskSuspend #define vTaskSuspend MPU_vTaskSuspend
#define xTaskIsTaskSuspended MPU_xTaskIsTaskSuspended
#define vTaskResume MPU_vTaskResume #define vTaskResume MPU_vTaskResume
#define vTaskSuspendAll MPU_vTaskSuspendAll #define vTaskSuspendAll MPU_vTaskSuspendAll
#define xTaskResumeAll MPU_xTaskResumeAll #define xTaskResumeAll MPU_xTaskResumeAll

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -69,8 +70,10 @@
#ifndef PORTABLE_H #ifndef PORTABLE_H
#define PORTABLE_H #define PORTABLE_H
/* Include the macro file relevant to the port being used. */ /* Include the macro file relevant to the port being used.
NOTE: The following definitions are *DEPRECATED* as it is preferred to instead
just add the path to the correct portmacro.h header file to the compiler's
include path. */
#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 )();
@ -90,19 +93,19 @@
#endif #endif
#ifdef MPLAB_PIC24_PORT #ifdef MPLAB_PIC24_PORT
#include "..\..\Source\portable\MPLAB\PIC24_dsPIC\portmacro.h" #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
#endif #endif
#ifdef MPLAB_DSPIC_PORT #ifdef MPLAB_DSPIC_PORT
#include "..\..\Source\portable\MPLAB\PIC24_dsPIC\portmacro.h" #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
#endif #endif
#ifdef MPLAB_PIC18F_PORT #ifdef MPLAB_PIC18F_PORT
#include "..\..\Source\portable\MPLAB\PIC18F\portmacro.h" #include "../../Source/portable/MPLAB/PIC18F/portmacro.h"
#endif #endif
#ifdef MPLAB_PIC32MX_PORT #ifdef MPLAB_PIC32MX_PORT
#include "..\..\Source\portable\MPLAB\PIC32MX\portmacro.h" #include "../../Source/portable/MPLAB/PIC32MX/portmacro.h"
#endif #endif
#ifdef _FEDPICC #ifdef _FEDPICC
@ -355,9 +358,9 @@ extern "C" {
* *
*/ */
#if( portUSING_MPU_WRAPPERS == 1 ) #if( portUSING_MPU_WRAPPERS == 1 )
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters, portBASE_TYPE xRunPrivileged ) PRIVILEGED_FUNCTION; StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION;
#else #else
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) PRIVILEGED_FUNCTION; StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION;
#endif #endif
/* /*
@ -367,12 +370,13 @@ 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;
/* /*
* 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.
*/ */
portBASE_TYPE 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
@ -390,7 +394,7 @@ void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
*/ */
#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, portSTACK_TYPE *pxBottomOfStack, unsigned short usStackDepth ) PRIVILEGED_FUNCTION; void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint16_t usStackDepth ) PRIVILEGED_FUNCTION;
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -65,20 +66,22 @@
#ifndef PROJDEFS_H #ifndef PROJDEFS_H
#define PROJDEFS_H #define PROJDEFS_H
/* Defines the prototype to which task functions must conform. */ /*
typedef void (*pdTASK_CODE)( void * ); * Defines the prototype to which task functions must conform. Defined in this
* file to ensure the type is known before portable.h is included.
*/
typedef void (*TaskFunction_t)( void * );
#define pdFALSE ( ( portBASE_TYPE ) 0 ) #define pdFALSE ( ( BaseType_t ) 0 )
#define pdTRUE ( ( portBASE_TYPE ) 1 ) #define pdTRUE ( ( BaseType_t ) 1 )
#define pdPASS ( pdTRUE ) #define pdPASS ( pdTRUE )
#define pdFAIL ( pdFALSE ) #define pdFAIL ( pdFALSE )
#define errQUEUE_EMPTY ( ( portBASE_TYPE ) 0 ) #define errQUEUE_EMPTY ( ( BaseType_t ) 0 )
#define errQUEUE_FULL ( ( portBASE_TYPE ) 0 ) #define errQUEUE_FULL ( ( BaseType_t ) 0 )
/* Error definitions. */ /* Error definitions. */
#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 ) #define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 )
#define errNO_TASK_TO_RUN ( -2 )
#define errQUEUE_BLOCKED ( -4 ) #define errQUEUE_BLOCKED ( -4 )
#define errQUEUE_YIELD ( -5 ) #define errQUEUE_YIELD ( -5 )

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -77,44 +78,44 @@ extern "C" {
/** /**
* Type by which queues are referenced. For example, a call to xQueueCreate() * Type by which queues are referenced. For example, a call to xQueueCreate()
* returns an xQueueHandle variable that can then be used as a parameter to * returns an QueueHandle_t variable that can then be used as a parameter to
* xQueueSend(), xQueueReceive(), etc. * xQueueSend(), xQueueReceive(), etc.
*/ */
typedef void * xQueueHandle; typedef void * QueueHandle_t;
/** /**
* Type by which queue sets are referenced. For example, a call to * Type by which queue sets are referenced. For example, a call to
* xQueueCreateSet() returns an xQueueSet variable that can then be used as a * xQueueCreateSet() returns an xQueueSet variable that can then be used as a
* parameter to xQueueSelectFromSet(), xQueueAddToSet(), etc. * parameter to xQueueSelectFromSet(), xQueueAddToSet(), etc.
*/ */
typedef void * xQueueSetHandle; typedef void * QueueSetHandle_t;
/** /**
* Queue sets can contain both queues and semaphores, so the * Queue sets can contain both queues and semaphores, so the
* xQueueSetMemberHandle is defined as a type to be used where a parameter or * QueueSetMemberHandle_t is defined as a type to be used where a parameter or
* return value can be either an xQueueHandle or an xSemaphoreHandle. * return value can be either an QueueHandle_t or an SemaphoreHandle_t.
*/ */
typedef void * xQueueSetMemberHandle; typedef void * QueueSetMemberHandle_t;
/* For internal use only. */ /* For internal use only. */
#define queueSEND_TO_BACK ( ( portBASE_TYPE ) 0 ) #define queueSEND_TO_BACK ( ( BaseType_t ) 0 )
#define queueSEND_TO_FRONT ( ( portBASE_TYPE ) 1 ) #define queueSEND_TO_FRONT ( ( BaseType_t ) 1 )
#define queueOVERWRITE ( ( portBASE_TYPE ) 2 ) #define queueOVERWRITE ( ( BaseType_t ) 2 )
/* For internal use only. These definitions *must* match those in queue.c. */ /* For internal use only. These definitions *must* match those in queue.c. */
#define queueQUEUE_TYPE_BASE ( ( unsigned char ) 0U ) #define queueQUEUE_TYPE_BASE ( ( uint8_t ) 0U )
#define queueQUEUE_TYPE_SET ( ( unsigned char ) 0U ) #define queueQUEUE_TYPE_SET ( ( uint8_t ) 0U )
#define queueQUEUE_TYPE_MUTEX ( ( unsigned char ) 1U ) #define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U )
#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( unsigned char ) 2U ) #define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( uint8_t ) 2U )
#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( unsigned char ) 3U ) #define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U )
#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( unsigned char ) 4U ) #define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( uint8_t ) 4U )
/** /**
* queue. h * queue. h
* <pre> * <pre>
xQueueHandle xQueueCreate( QueueHandle_t xQueueCreate(
unsigned portBASE_TYPE uxQueueLength, UBaseType_t uxQueueLength,
unsigned portBASE_TYPE uxItemSize UBaseType_t uxItemSize
); );
* </pre> * </pre>
* *
@ -142,10 +143,10 @@ typedef void * xQueueSetMemberHandle;
void vATask( void *pvParameters ) void vATask( void *pvParameters )
{ {
xQueueHandle xQueue1, xQueue2; QueueHandle_t xQueue1, xQueue2;
// Create a queue capable of containing 10 unsigned long values. // Create a queue capable of containing 10 uint32_t values.
xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) ); xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
if( xQueue1 == 0 ) if( xQueue1 == 0 )
{ {
// Queue was not created and must not be used. // Queue was not created and must not be used.
@ -170,10 +171,10 @@ typedef void * xQueueSetMemberHandle;
/** /**
* queue. h * queue. h
* <pre> * <pre>
portBASE_TYPE xQueueSendToToFront( BaseType_t xQueueSendToToFront(
xQueueHandle xQueue, QueueHandle_t xQueue,
const void * pvItemToQueue, const void *pvItemToQueue,
portTickType xTicksToWait TickType_t xTicksToWait
); );
* </pre> * </pre>
* *
@ -195,7 +196,7 @@ typedef void * xQueueSetMemberHandle;
* waiting for space to become available on the queue, should it already * waiting for space to become available on the queue, should it already
* be full. The call will return immediately if this is set to 0 and the * be full. The call will return immediately if this is set to 0 and the
* queue is full. The time is defined in tick periods so the constant * queue is full. The time is defined in tick periods so the constant
* portTICK_RATE_MS should be used to convert to real time if this is required. * portTICK_PERIOD_MS should be used to convert to real time if this is required.
* *
* @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
* *
@ -207,15 +208,15 @@ typedef void * xQueueSetMemberHandle;
char ucData[ 20 ]; char ucData[ 20 ];
} xMessage; } xMessage;
unsigned long ulVar = 10UL; uint32_t ulVar = 10UL;
void vATask( void *pvParameters ) void vATask( void *pvParameters )
{ {
xQueueHandle xQueue1, xQueue2; QueueHandle_t xQueue1, xQueue2;
struct AMessage *pxMessage; struct AMessage *pxMessage;
// Create a queue capable of containing 10 unsigned long values. // Create a queue capable of containing 10 uint32_t values.
xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) ); xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
// Create a queue capable of containing 10 pointers to AMessage structures. // Create a queue capable of containing 10 pointers to AMessage structures.
// These should be passed by pointer as they contain a lot of data. // These should be passed by pointer as they contain a lot of data.
@ -225,9 +226,9 @@ typedef void * xQueueSetMemberHandle;
if( xQueue1 != 0 ) if( xQueue1 != 0 )
{ {
// Send an unsigned long. Wait for 10 ticks for space to become // Send an uint32_t. Wait for 10 ticks for space to become
// available if necessary. // available if necessary.
if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS ) if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
{ {
// Failed to post the message, even after 10 ticks. // Failed to post the message, even after 10 ticks.
} }
@ -238,7 +239,7 @@ typedef void * xQueueSetMemberHandle;
// Send a pointer to a struct AMessage object. Don't block if the // Send a pointer to a struct AMessage object. Don't block if the
// queue is already full. // queue is already full.
pxMessage = & xMessage; pxMessage = & xMessage;
xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 ); xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
} }
// ... Rest of task code. // ... Rest of task code.
@ -252,10 +253,10 @@ typedef void * xQueueSetMemberHandle;
/** /**
* queue. h * queue. h
* <pre> * <pre>
portBASE_TYPE xQueueSendToBack( BaseType_t xQueueSendToBack(
xQueueHandle xQueue, QueueHandle_t xQueue,
const void * pvItemToQueue, const void *pvItemToQueue,
portTickType xTicksToWait TickType_t xTicksToWait
); );
* </pre> * </pre>
* *
@ -277,7 +278,7 @@ typedef void * xQueueSetMemberHandle;
* waiting for space to become available on the queue, should it already * waiting for space to become available on the queue, should it already
* be full. The call will return immediately if this is set to 0 and the queue * be full. The call will return immediately if this is set to 0 and the queue
* is full. The time is defined in tick periods so the constant * is full. The time is defined in tick periods so the constant
* portTICK_RATE_MS should be used to convert to real time if this is required. * portTICK_PERIOD_MS should be used to convert to real time if this is required.
* *
* @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
* *
@ -289,15 +290,15 @@ typedef void * xQueueSetMemberHandle;
char ucData[ 20 ]; char ucData[ 20 ];
} xMessage; } xMessage;
unsigned long ulVar = 10UL; uint32_t ulVar = 10UL;
void vATask( void *pvParameters ) void vATask( void *pvParameters )
{ {
xQueueHandle xQueue1, xQueue2; QueueHandle_t xQueue1, xQueue2;
struct AMessage *pxMessage; struct AMessage *pxMessage;
// Create a queue capable of containing 10 unsigned long values. // Create a queue capable of containing 10 uint32_t values.
xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) ); xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
// Create a queue capable of containing 10 pointers to AMessage structures. // Create a queue capable of containing 10 pointers to AMessage structures.
// These should be passed by pointer as they contain a lot of data. // These should be passed by pointer as they contain a lot of data.
@ -307,9 +308,9 @@ typedef void * xQueueSetMemberHandle;
if( xQueue1 != 0 ) if( xQueue1 != 0 )
{ {
// Send an unsigned long. Wait for 10 ticks for space to become // Send an uint32_t. Wait for 10 ticks for space to become
// available if necessary. // available if necessary.
if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS ) if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
{ {
// Failed to post the message, even after 10 ticks. // Failed to post the message, even after 10 ticks.
} }
@ -320,7 +321,7 @@ typedef void * xQueueSetMemberHandle;
// Send a pointer to a struct AMessage object. Don't block if the // Send a pointer to a struct AMessage object. Don't block if the
// queue is already full. // queue is already full.
pxMessage = & xMessage; pxMessage = & xMessage;
xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 ); xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
} }
// ... Rest of task code. // ... Rest of task code.
@ -334,10 +335,10 @@ typedef void * xQueueSetMemberHandle;
/** /**
* queue. h * queue. h
* <pre> * <pre>
portBASE_TYPE xQueueSend( BaseType_t xQueueSend(
xQueueHandle xQueue, QueueHandle_t xQueue,
const void * pvItemToQueue, const void * pvItemToQueue,
portTickType xTicksToWait TickType_t xTicksToWait
); );
* </pre> * </pre>
* *
@ -361,7 +362,7 @@ typedef void * xQueueSetMemberHandle;
* waiting for space to become available on the queue, should it already * waiting for space to become available on the queue, should it already
* be full. The call will return immediately if this is set to 0 and the * be full. The call will return immediately if this is set to 0 and the
* queue is full. The time is defined in tick periods so the constant * queue is full. The time is defined in tick periods so the constant
* portTICK_RATE_MS should be used to convert to real time if this is required. * portTICK_PERIOD_MS should be used to convert to real time if this is required.
* *
* @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
* *
@ -373,15 +374,15 @@ typedef void * xQueueSetMemberHandle;
char ucData[ 20 ]; char ucData[ 20 ];
} xMessage; } xMessage;
unsigned long ulVar = 10UL; uint32_t ulVar = 10UL;
void vATask( void *pvParameters ) void vATask( void *pvParameters )
{ {
xQueueHandle xQueue1, xQueue2; QueueHandle_t xQueue1, xQueue2;
struct AMessage *pxMessage; struct AMessage *pxMessage;
// Create a queue capable of containing 10 unsigned long values. // Create a queue capable of containing 10 uint32_t values.
xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) ); xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
// Create a queue capable of containing 10 pointers to AMessage structures. // Create a queue capable of containing 10 pointers to AMessage structures.
// These should be passed by pointer as they contain a lot of data. // These should be passed by pointer as they contain a lot of data.
@ -391,9 +392,9 @@ typedef void * xQueueSetMemberHandle;
if( xQueue1 != 0 ) if( xQueue1 != 0 )
{ {
// Send an unsigned long. Wait for 10 ticks for space to become // Send an uint32_t. Wait for 10 ticks for space to become
// available if necessary. // available if necessary.
if( xQueueSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS ) if( xQueueSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
{ {
// Failed to post the message, even after 10 ticks. // Failed to post the message, even after 10 ticks.
} }
@ -404,7 +405,7 @@ typedef void * xQueueSetMemberHandle;
// Send a pointer to a struct AMessage object. Don't block if the // Send a pointer to a struct AMessage object. Don't block if the
// queue is already full. // queue is already full.
pxMessage = & xMessage; pxMessage = & xMessage;
xQueueSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 ); xQueueSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
} }
// ... Rest of task code. // ... Rest of task code.
@ -418,8 +419,8 @@ typedef void * xQueueSetMemberHandle;
/** /**
* queue. h * queue. h
* <pre> * <pre>
portBASE_TYPE xQueueOverwrite( BaseType_t xQueueOverwrite(
xQueueHandle xQueue, QueueHandle_t xQueue,
const void * pvItemToQueue const void * pvItemToQueue
); );
* </pre> * </pre>
@ -450,14 +451,14 @@ typedef void * xQueueSetMemberHandle;
void vFunction( void *pvParameters ) void vFunction( void *pvParameters )
{ {
xQueueHandle xQueue; QueueHandle_t xQueue;
unsigned long ulVarToSend, ulValReceived; uint32_t ulVarToSend, ulValReceived;
// Create a queue to hold one unsigned long value. It is strongly // Create a queue to hold one uint32_t value. It is strongly
// recommended *not* to use xQueueOverwrite() on queues that can // recommended *not* to use xQueueOverwrite() on queues that can
// contain more than one value, and doing so will trigger an assertion // contain more than one value, and doing so will trigger an assertion
// if configASSERT() is defined. // if configASSERT() is defined.
xQueue = xQueueCreate( 1, sizeof( unsigned long ) ); xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
// Write the value 10 to the queue using xQueueOverwrite(). // Write the value 10 to the queue using xQueueOverwrite().
ulVarToSend = 10; ulVarToSend = 10;
@ -502,11 +503,11 @@ typedef void * xQueueSetMemberHandle;
/** /**
* queue. h * queue. h
* <pre> * <pre>
portBASE_TYPE xQueueGenericSend( BaseType_t xQueueGenericSend(
xQueueHandle xQueue, QueueHandle_t xQueue,
const void * pvItemToQueue, const void * pvItemToQueue,
portTickType xTicksToWait TickType_t xTicksToWait
portBASE_TYPE xCopyPosition BaseType_t xCopyPosition
); );
* </pre> * </pre>
* *
@ -528,7 +529,7 @@ typedef void * xQueueSetMemberHandle;
* waiting for space to become available on the queue, should it already * waiting for space to become available on the queue, should it already
* be full. The call will return immediately if this is set to 0 and the * be full. The call will return immediately if this is set to 0 and the
* queue is full. The time is defined in tick periods so the constant * queue is full. The time is defined in tick periods so the constant
* portTICK_RATE_MS should be used to convert to real time if this is required. * portTICK_PERIOD_MS should be used to convert to real time if this is required.
* *
* @param xCopyPosition Can take the value queueSEND_TO_BACK to place the * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the
* item at the back of the queue, or queueSEND_TO_FRONT to place the item * item at the back of the queue, or queueSEND_TO_FRONT to place the item
@ -544,15 +545,15 @@ typedef void * xQueueSetMemberHandle;
char ucData[ 20 ]; char ucData[ 20 ];
} xMessage; } xMessage;
unsigned long ulVar = 10UL; uint32_t ulVar = 10UL;
void vATask( void *pvParameters ) void vATask( void *pvParameters )
{ {
xQueueHandle xQueue1, xQueue2; QueueHandle_t xQueue1, xQueue2;
struct AMessage *pxMessage; struct AMessage *pxMessage;
// Create a queue capable of containing 10 unsigned long values. // Create a queue capable of containing 10 uint32_t values.
xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) ); xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
// Create a queue capable of containing 10 pointers to AMessage structures. // Create a queue capable of containing 10 pointers to AMessage structures.
// These should be passed by pointer as they contain a lot of data. // These should be passed by pointer as they contain a lot of data.
@ -562,9 +563,9 @@ typedef void * xQueueSetMemberHandle;
if( xQueue1 != 0 ) if( xQueue1 != 0 )
{ {
// Send an unsigned long. Wait for 10 ticks for space to become // Send an uint32_t. Wait for 10 ticks for space to become
// available if necessary. // available if necessary.
if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10, queueSEND_TO_BACK ) != pdPASS ) if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10, queueSEND_TO_BACK ) != pdPASS )
{ {
// Failed to post the message, even after 10 ticks. // Failed to post the message, even after 10 ticks.
} }
@ -575,7 +576,7 @@ typedef void * xQueueSetMemberHandle;
// Send a pointer to a struct AMessage object. Don't block if the // Send a pointer to a struct AMessage object. Don't block if the
// queue is already full. // queue is already full.
pxMessage = & xMessage; pxMessage = & xMessage;
xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0, queueSEND_TO_BACK ); xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0, queueSEND_TO_BACK );
} }
// ... Rest of task code. // ... Rest of task code.
@ -584,15 +585,15 @@ typedef void * xQueueSetMemberHandle;
* \defgroup xQueueSend xQueueSend * \defgroup xQueueSend xQueueSend
* \ingroup QueueManagement * \ingroup QueueManagement
*/ */
signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION; BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION;
/** /**
* queue. h * queue. h
* <pre> * <pre>
portBASE_TYPE xQueuePeek( BaseType_t xQueuePeek(
xQueueHandle xQueue, QueueHandle_t xQueue,
void *pvBuffer, void *pvBuffer,
portTickType xTicksToWait TickType_t xTicksToWait
);</pre> );</pre>
* *
* This is a macro that calls the xQueueGenericReceive() function. * This is a macro that calls the xQueueGenericReceive() function.
@ -618,7 +619,7 @@ signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const
* @param xTicksToWait The maximum amount of time the task should block * @param xTicksToWait The maximum amount of time the task should block
* waiting for an item to receive should the queue be empty at the time * waiting for an item to receive should the queue be empty at the time
* of the call. The time is defined in tick periods so the constant * of the call. The time is defined in tick periods so the constant
* portTICK_RATE_MS should be used to convert to real time if this is required. * portTICK_PERIOD_MS should be used to convert to real time if this is required.
* xQueuePeek() will return immediately if xTicksToWait is 0 and the queue * xQueuePeek() will return immediately if xTicksToWait is 0 and the queue
* is empty. * is empty.
* *
@ -633,7 +634,7 @@ signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const
char ucData[ 20 ]; char ucData[ 20 ];
} xMessage; } xMessage;
xQueueHandle xQueue; QueueHandle_t xQueue;
// Task to create a queue and post a value. // Task to create a queue and post a value.
void vATask( void *pvParameters ) void vATask( void *pvParameters )
@ -653,7 +654,7 @@ signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const
// Send a pointer to a struct AMessage object. Don't block if the // Send a pointer to a struct AMessage object. Don't block if the
// queue is already full. // queue is already full.
pxMessage = & xMessage; pxMessage = & xMessage;
xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 ); xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
// ... Rest of task code. // ... Rest of task code.
} }
@ -667,7 +668,7 @@ signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const
{ {
// Peek a message on the created queue. Block for 10 ticks if a // Peek a message on the created queue. Block for 10 ticks if a
// message is not immediately available. // message is not immediately available.
if( xQueuePeek( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) ) if( xQueuePeek( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
{ {
// pcRxedMessage now points to the struct AMessage variable posted // pcRxedMessage now points to the struct AMessage variable posted
// by vATask, but the item still remains on the queue. // by vATask, but the item still remains on the queue.
@ -685,8 +686,8 @@ signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const
/** /**
* queue. h * queue. h
* <pre> * <pre>
portBASE_TYPE xQueuePeekFromISR( BaseType_t xQueuePeekFromISR(
xQueueHandle xQueue, QueueHandle_t xQueue,
void *pvBuffer, void *pvBuffer,
);</pre> );</pre>
* *
@ -713,15 +714,15 @@ signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const
* \defgroup xQueuePeekFromISR xQueuePeekFromISR * \defgroup xQueuePeekFromISR xQueuePeekFromISR
* \ingroup QueueManagement * \ingroup QueueManagement
*/ */
signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const pvBuffer ) PRIVILEGED_FUNCTION; BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION;
/** /**
* queue. h * queue. h
* <pre> * <pre>
portBASE_TYPE xQueueReceive( BaseType_t xQueueReceive(
xQueueHandle xQueue, QueueHandle_t xQueue,
void *pvBuffer, void *pvBuffer,
portTickType xTicksToWait TickType_t xTicksToWait
);</pre> );</pre>
* *
* This is a macro that calls the xQueueGenericReceive() function. * This is a macro that calls the xQueueGenericReceive() function.
@ -745,7 +746,7 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const
* waiting for an item to receive should the queue be empty at the time * waiting for an item to receive should the queue be empty at the time
* of the call. xQueueReceive() will return immediately if xTicksToWait * of the call. xQueueReceive() will return immediately if xTicksToWait
* is zero and the queue is empty. The time is defined in tick periods so the * is zero and the queue is empty. The time is defined in tick periods so the
* constant portTICK_RATE_MS should be used to convert to real time if this is * constant portTICK_PERIOD_MS should be used to convert to real time if this is
* required. * required.
* *
* @return pdTRUE if an item was successfully received from the queue, * @return pdTRUE if an item was successfully received from the queue,
@ -759,7 +760,7 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const
char ucData[ 20 ]; char ucData[ 20 ];
} xMessage; } xMessage;
xQueueHandle xQueue; QueueHandle_t xQueue;
// Task to create a queue and post a value. // Task to create a queue and post a value.
void vATask( void *pvParameters ) void vATask( void *pvParameters )
@ -779,7 +780,7 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const
// Send a pointer to a struct AMessage object. Don't block if the // Send a pointer to a struct AMessage object. Don't block if the
// queue is already full. // queue is already full.
pxMessage = & xMessage; pxMessage = & xMessage;
xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 ); xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
// ... Rest of task code. // ... Rest of task code.
} }
@ -793,7 +794,7 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const
{ {
// Receive a message on the created queue. Block for 10 ticks if a // Receive a message on the created queue. Block for 10 ticks if a
// message is not immediately available. // message is not immediately available.
if( xQueueReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) ) if( xQueueReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
{ {
// pcRxedMessage now points to the struct AMessage variable posted // pcRxedMessage now points to the struct AMessage variable posted
// by vATask. // by vATask.
@ -812,11 +813,11 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const
/** /**
* queue. h * queue. h
* <pre> * <pre>
portBASE_TYPE xQueueGenericReceive( BaseType_t xQueueGenericReceive(
xQueueHandle xQueue, QueueHandle_t xQueue,
void *pvBuffer, void *pvBuffer,
portTickType xTicksToWait TickType_t xTicksToWait
portBASE_TYPE xJustPeek BaseType_t xJustPeek
);</pre> );</pre>
* *
* It is preferred that the macro xQueueReceive() be used rather than calling * It is preferred that the macro xQueueReceive() be used rather than calling
@ -838,7 +839,7 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const
* @param xTicksToWait The maximum amount of time the task should block * @param xTicksToWait The maximum amount of time the task should block
* waiting for an item to receive should the queue be empty at the time * waiting for an item to receive should the queue be empty at the time
* of the call. The time is defined in tick periods so the constant * of the call. The time is defined in tick periods so the constant
* portTICK_RATE_MS should be used to convert to real time if this is required. * portTICK_PERIOD_MS should be used to convert to real time if this is required.
* xQueueGenericReceive() will return immediately if the queue is empty and * xQueueGenericReceive() will return immediately if the queue is empty and
* xTicksToWait is 0. * xTicksToWait is 0.
* *
@ -858,7 +859,7 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const
char ucData[ 20 ]; char ucData[ 20 ];
} xMessage; } xMessage;
xQueueHandle xQueue; QueueHandle_t xQueue;
// Task to create a queue and post a value. // Task to create a queue and post a value.
void vATask( void *pvParameters ) void vATask( void *pvParameters )
@ -878,7 +879,7 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const
// Send a pointer to a struct AMessage object. Don't block if the // Send a pointer to a struct AMessage object. Don't block if the
// queue is already full. // queue is already full.
pxMessage = & xMessage; pxMessage = & xMessage;
xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 ); xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
// ... Rest of task code. // ... Rest of task code.
} }
@ -892,7 +893,7 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const
{ {
// Receive a message on the created queue. Block for 10 ticks if a // Receive a message on the created queue. Block for 10 ticks if a
// message is not immediately available. // message is not immediately available.
if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) ) if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
{ {
// pcRxedMessage now points to the struct AMessage variable posted // pcRxedMessage now points to the struct AMessage variable posted
// by vATask. // by vATask.
@ -905,11 +906,11 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const
* \defgroup xQueueReceive xQueueReceive * \defgroup xQueueReceive xQueueReceive
* \ingroup QueueManagement * \ingroup QueueManagement
*/ */
signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeek ) PRIVILEGED_FUNCTION; BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek ) PRIVILEGED_FUNCTION;
/** /**
* queue. h * queue. h
* <pre>unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue );</pre> * <pre>UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue );</pre>
* *
* Return the number of messages stored in a queue. * Return the number of messages stored in a queue.
* *
@ -920,11 +921,28 @@ signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, const void * con
* \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting
* \ingroup QueueManagement * \ingroup QueueManagement
*/ */
unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue ) PRIVILEGED_FUNCTION; UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
/** /**
* queue. h * queue. h
* <pre>void vQueueDelete( xQueueHandle xQueue );</pre> * <pre>UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );</pre>
*
* Return the number of free spaces available in a queue. This is equal to the
* number of items that can be sent to the queue before the queue becomes full
* if no items are removed.
*
* @param xQueue A handle to the queue being queried.
*
* @return The number of spaces available in the queue.
*
* \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting
* \ingroup QueueManagement
*/
UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
/**
* queue. h
* <pre>void vQueueDelete( QueueHandle_t xQueue );</pre>
* *
* Delete a queue - freeing all the memory allocated for storing of items * Delete a queue - freeing all the memory allocated for storing of items
* placed on the queue. * placed on the queue.
@ -934,15 +952,15 @@ unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue ) PRIVI
* \defgroup vQueueDelete vQueueDelete * \defgroup vQueueDelete vQueueDelete
* \ingroup QueueManagement * \ingroup QueueManagement
*/ */
void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION; void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
/** /**
* queue. h * queue. h
* <pre> * <pre>
portBASE_TYPE xQueueSendToFrontFromISR( BaseType_t xQueueSendToFrontFromISR(
xQueueHandle xQueue, QueueHandle_t xQueue,
const void *pvItemToQueue, const void *pvItemToQueue,
portBASE_TYPE *pxHigherPriorityTaskWoken BaseType_t *pxHigherPriorityTaskWoken
); );
</pre> </pre>
* *
@ -977,7 +995,7 @@ void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
void vBufferISR( void ) void vBufferISR( void )
{ {
char cIn; char cIn;
portBASE_TYPE xHigherPrioritTaskWoken; BaseType_t xHigherPrioritTaskWoken;
// We have not woken a task at the start of the ISR. // We have not woken a task at the start of the ISR.
xHigherPriorityTaskWoken = pdFALSE; xHigherPriorityTaskWoken = pdFALSE;
@ -1010,10 +1028,10 @@ void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
/** /**
* queue. h * queue. h
* <pre> * <pre>
portBASE_TYPE xQueueSendToBackFromISR( BaseType_t xQueueSendToBackFromISR(
xQueueHandle xQueue, QueueHandle_t xQueue,
const void *pvItemToQueue, const void *pvItemToQueue,
portBASE_TYPE *pxHigherPriorityTaskWoken BaseType_t *pxHigherPriorityTaskWoken
); );
</pre> </pre>
* *
@ -1048,7 +1066,7 @@ void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
void vBufferISR( void ) void vBufferISR( void )
{ {
char cIn; char cIn;
portBASE_TYPE xHigherPriorityTaskWoken; BaseType_t xHigherPriorityTaskWoken;
// We have not woken a task at the start of the ISR. // We have not woken a task at the start of the ISR.
xHigherPriorityTaskWoken = pdFALSE; xHigherPriorityTaskWoken = pdFALSE;
@ -1080,10 +1098,10 @@ void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
/** /**
* queue. h * queue. h
* <pre> * <pre>
portBASE_TYPE xQueueOverwriteFromISR( BaseType_t xQueueOverwriteFromISR(
xQueueHandle xQueue, QueueHandle_t xQueue,
const void * pvItemToQueue, const void * pvItemToQueue,
portBASE_TYPE *pxHigherPriorityTaskWoken BaseType_t *pxHigherPriorityTaskWoken
); );
* </pre> * </pre>
* *
@ -1118,22 +1136,22 @@ void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
* Example usage: * Example usage:
<pre> <pre>
xQueueHandle xQueue; QueueHandle_t xQueue;
void vFunction( void *pvParameters ) void vFunction( void *pvParameters )
{ {
// Create a queue to hold one unsigned long value. It is strongly // Create a queue to hold one uint32_t value. It is strongly
// recommended *not* to use xQueueOverwriteFromISR() on queues that can // recommended *not* to use xQueueOverwriteFromISR() on queues that can
// contain more than one value, and doing so will trigger an assertion // contain more than one value, and doing so will trigger an assertion
// if configASSERT() is defined. // if configASSERT() is defined.
xQueue = xQueueCreate( 1, sizeof( unsigned long ) ); xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
} }
void vAnInterruptHandler( void ) void vAnInterruptHandler( void )
{ {
// xHigherPriorityTaskWoken must be set to pdFALSE before it is used. // xHigherPriorityTaskWoken must be set to pdFALSE before it is used.
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; BaseType_t xHigherPriorityTaskWoken = pdFALSE;
unsigned long ulVarToSend, ulValReceived; uint32_t ulVarToSend, ulValReceived;
// Write the value 10 to the queue using xQueueOverwriteFromISR(). // Write the value 10 to the queue using xQueueOverwriteFromISR().
ulVarToSend = 10; ulVarToSend = 10;
@ -1148,7 +1166,7 @@ unsigned long ulVarToSend, ulValReceived;
// Reading from the queue will now return 100. // Reading from the queue will now return 100.
// ... // ...
if( xHigherPrioritytaskWoken == pdTRUE ) if( xHigherPrioritytaskWoken == pdTRUE )
{ {
// Writing to the queue caused a task to unblock and the unblocked task // Writing to the queue caused a task to unblock and the unblocked task
@ -1167,10 +1185,10 @@ unsigned long ulVarToSend, ulValReceived;
/** /**
* queue. h * queue. h
* <pre> * <pre>
portBASE_TYPE xQueueSendFromISR( BaseType_t xQueueSendFromISR(
xQueueHandle xQueue, QueueHandle_t xQueue,
const void *pvItemToQueue, const void *pvItemToQueue,
portBASE_TYPE *pxHigherPriorityTaskWoken BaseType_t *pxHigherPriorityTaskWoken
); );
</pre> </pre>
* *
@ -1208,7 +1226,7 @@ unsigned long ulVarToSend, ulValReceived;
void vBufferISR( void ) void vBufferISR( void )
{ {
char cIn; char cIn;
portBASE_TYPE xHigherPriorityTaskWoken; BaseType_t xHigherPriorityTaskWoken;
// We have not woken a task at the start of the ISR. // We have not woken a task at the start of the ISR.
xHigherPriorityTaskWoken = pdFALSE; xHigherPriorityTaskWoken = pdFALSE;
@ -1228,7 +1246,7 @@ unsigned long ulVarToSend, ulValReceived;
if( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken )
{ {
// Actual macro used here is port specific. // Actual macro used here is port specific.
taskYIELD_FROM_ISR (); portYIELD_FROM_ISR ();
} }
} }
</pre> </pre>
@ -1241,11 +1259,11 @@ unsigned long ulVarToSend, ulValReceived;
/** /**
* queue. h * queue. h
* <pre> * <pre>
portBASE_TYPE xQueueGenericSendFromISR( BaseType_t xQueueGenericSendFromISR(
xQueueHandle xQueue, QueueHandle_t xQueue,
const void *pvItemToQueue, const void *pvItemToQueue,
portBASE_TYPE *pxHigherPriorityTaskWoken, BaseType_t *pxHigherPriorityTaskWoken,
portBASE_TYPE xCopyPosition BaseType_t xCopyPosition
); );
</pre> </pre>
* *
@ -1286,7 +1304,7 @@ unsigned long ulVarToSend, ulValReceived;
void vBufferISR( void ) void vBufferISR( void )
{ {
char cIn; char cIn;
portBASE_TYPE xHigherPriorityTaskWokenByPost; BaseType_t xHigherPriorityTaskWokenByPost;
// We have not woken a task at the start of the ISR. // We have not woken a task at the start of the ISR.
xHigherPriorityTaskWokenByPost = pdFALSE; xHigherPriorityTaskWokenByPost = pdFALSE;
@ -1314,15 +1332,15 @@ unsigned long ulVarToSend, ulValReceived;
* \defgroup xQueueSendFromISR xQueueSendFromISR * \defgroup xQueueSendFromISR xQueueSendFromISR
* \ingroup QueueManagement * \ingroup QueueManagement
*/ */
signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION; BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION;
/** /**
* queue. h * queue. h
* <pre> * <pre>
portBASE_TYPE xQueueReceiveFromISR( BaseType_t xQueueReceiveFromISR(
xQueueHandle xQueue, QueueHandle_t xQueue,
void *pvBuffer, void *pvBuffer,
portBASE_TYPE *pxTaskWoken BaseType_t *pxTaskWoken
); );
* </pre> * </pre>
* *
@ -1346,13 +1364,13 @@ signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void *
* Example usage: * Example usage:
<pre> <pre>
xQueueHandle xQueue; QueueHandle_t xQueue;
// Function to create a queue and post some values. // Function to create a queue and post some values.
void vAFunction( void *pvParameters ) void vAFunction( void *pvParameters )
{ {
char cValueToPost; char cValueToPost;
const portTickType xBlockTime = ( portTickType )0xff; const TickType_t xTicksToWait = ( TickType_t )0xff;
// Create a queue capable of containing 10 characters. // Create a queue capable of containing 10 characters.
xQueue = xQueueCreate( 10, sizeof( char ) ); xQueue = xQueueCreate( 10, sizeof( char ) );
@ -1364,23 +1382,23 @@ signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void *
// ... // ...
// Post some characters that will be used within an ISR. If the queue // Post some characters that will be used within an ISR. If the queue
// is full then this task will block for xBlockTime ticks. // is full then this task will block for xTicksToWait ticks.
cValueToPost = 'a'; cValueToPost = 'a';
xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime ); xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
cValueToPost = 'b'; cValueToPost = 'b';
xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime ); xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
// ... keep posting characters ... this task may block when the queue // ... keep posting characters ... this task may block when the queue
// becomes full. // becomes full.
cValueToPost = 'c'; cValueToPost = 'c';
xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime ); xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
} }
// ISR that outputs all the characters received on the queue. // ISR that outputs all the characters received on the queue.
void vISR_Routine( void ) void vISR_Routine( void )
{ {
portBASE_TYPE xTaskWokenByReceive = pdFALSE; BaseType_t xTaskWokenByReceive = pdFALSE;
char cRxedChar; char cRxedChar;
while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) ) while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) )
@ -1403,15 +1421,15 @@ signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void *
* \defgroup xQueueReceiveFromISR xQueueReceiveFromISR * \defgroup xQueueReceiveFromISR xQueueReceiveFromISR
* \ingroup QueueManagement * \ingroup QueueManagement
*/ */
signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle xQueue, const void * const pvBuffer, signed portBASE_TYPE *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
/* /*
* Utilities to query queues that are safe to use from an ISR. These utilities * Utilities to query queues that are safe to use from an ISR. These utilities
* should be used only from witin an ISR, or within a critical section. * should be used only from witin an ISR, or within a critical section.
*/ */
signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle xQueue ) PRIVILEGED_FUNCTION; BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle xQueue ) PRIVILEGED_FUNCTION; BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle xQueue ) PRIVILEGED_FUNCTION; UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
/* /*
@ -1428,8 +1446,8 @@ unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle xQueue
* responsiveness to gain execution speed, whereas the fully featured API * responsiveness to gain execution speed, whereas the fully featured API
* sacrifices execution speed to ensure better interrupt responsiveness. * sacrifices execution speed to ensure better interrupt responsiveness.
*/ */
signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ); BaseType_t xQueueAltGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition );
signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ); BaseType_t xQueueAltGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking );
#define xQueueAltSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT ) #define xQueueAltSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT )
#define xQueueAltSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) #define xQueueAltSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
#define xQueueAltReceive( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE ) #define xQueueAltReceive( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE )
@ -1444,26 +1462,26 @@ signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle xQueue, void * const
* should not be called directly from application code. Instead use the macro * should not be called directly from application code. Instead use the macro
* wrappers defined within croutine.h. * wrappers defined within croutine.h.
*/ */
signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ); BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken );
signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle xQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ); BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxTaskWoken );
signed portBASE_TYPE xQueueCRSend( xQueueHandle xQueue, const void *pvItemToQueue, portTickType xTicksToWait ); BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait );
signed portBASE_TYPE xQueueCRReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait ); BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait );
/* /*
* For internal use only. Use xSemaphoreCreateMutex(), * For internal use only. Use xSemaphoreCreateMutex(),
* xSemaphoreCreateCounting() or xSemaphoreGetMutexHolder() instead of calling * xSemaphoreCreateCounting() or xSemaphoreGetMutexHolder() instead of calling
* these functions directly. * these functions directly.
*/ */
xQueueHandle xQueueCreateMutex( unsigned char ucQueueType ) PRIVILEGED_FUNCTION; QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) PRIVILEGED_FUNCTION; QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION;
void* xQueueGetMutexHolder( xQueueHandle xSemaphore ) PRIVILEGED_FUNCTION; void* xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION;
/* /*
* For internal use only. Use xSemaphoreTakeMutexRecursive() or * For internal use only. Use xSemaphoreTakeMutexRecursive() or
* xSemaphoreGiveMutexRecursive() instead of calling these functions directly. * xSemaphoreGiveMutexRecursive() instead of calling these functions directly.
*/ */
portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) PRIVILEGED_FUNCTION; BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex ) PRIVILEGED_FUNCTION; BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) PRIVILEGED_FUNCTION;
/* /*
* Reset a queue back to its original empty state. pdPASS is returned if the * Reset a queue back to its original empty state. pdPASS is returned if the
@ -1491,10 +1509,12 @@ portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex ) PRIVILEGED_FUNCTI
* handles can also be passed in here. * handles can also be passed in here.
* *
* @param pcName The name to be associated with the handle. This is the * @param pcName The name to be associated with the handle. This is the
* name that the kernel aware debugger will display. * name that the kernel aware debugger will display. The queue registry only
* stores a pointer to the string - so the string must be persistent (global or
* preferably in ROM/Flash), not on the stack.
*/ */
#if configQUEUE_REGISTRY_SIZE > 0 #if configQUEUE_REGISTRY_SIZE > 0
void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcName ) PRIVILEGED_FUNCTION; void vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcName ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
#endif #endif
/* /*
@ -1508,14 +1528,14 @@ portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex ) PRIVILEGED_FUNCTI
* @param xQueue The handle of the queue being removed from the registry. * @param xQueue The handle of the queue being removed from the registry.
*/ */
#if configQUEUE_REGISTRY_SIZE > 0 #if configQUEUE_REGISTRY_SIZE > 0
void vQueueUnregisterQueue( xQueueHandle xQueue ) PRIVILEGED_FUNCTION; void vQueueUnregisterQueue( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
#endif #endif
/* /*
* Generic version of the queue creation function, which is in turn called by * Generic version of the queue creation function, which is in turn called by
* any queue, semaphore or mutex creation function or macro. * any queue, semaphore or mutex creation function or macro.
*/ */
xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType ) PRIVILEGED_FUNCTION; QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
/* /*
* Queue sets provide a mechanism to allow a task to block (pend) on a read * Queue sets provide a mechanism to allow a task to block (pend) on a read
@ -1565,7 +1585,7 @@ xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned
* @return If the queue set is created successfully then a handle to the created * @return If the queue set is created successfully then a handle to the created
* queue set is returned. Otherwise NULL is returned. * queue set is returned. Otherwise NULL is returned.
*/ */
xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength ) PRIVILEGED_FUNCTION; QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) PRIVILEGED_FUNCTION;
/* /*
* Adds a queue or semaphore to a queue set that was previously created by a * Adds a queue or semaphore to a queue set that was previously created by a
@ -1579,7 +1599,7 @@ xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength ) PRI
* a call to xQueueSelectFromSet() has first returned a handle to that set member. * a call to xQueueSelectFromSet() has first returned a handle to that set member.
* *
* @param xQueueOrSemaphore The handle of the queue or semaphore being added to * @param xQueueOrSemaphore The handle of the queue or semaphore being added to
* the queue set (cast to an xQueueSetMemberHandle type). * the queue set (cast to an QueueSetMemberHandle_t type).
* *
* @param xQueueSet The handle of the queue set to which the queue or semaphore * @param xQueueSet The handle of the queue set to which the queue or semaphore
* is being added. * is being added.
@ -1589,7 +1609,7 @@ xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength ) PRI
* queue set because it is already a member of a different queue set then pdFAIL * queue set because it is already a member of a different queue set then pdFAIL
* is returned. * is returned.
*/ */
portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet ) PRIVILEGED_FUNCTION; BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION;
/* /*
* Removes a queue or semaphore from a queue set. A queue or semaphore can only * Removes a queue or semaphore from a queue set. A queue or semaphore can only
@ -1599,7 +1619,7 @@ portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSet
* function. * function.
* *
* @param xQueueOrSemaphore The handle of the queue or semaphore being removed * @param xQueueOrSemaphore The handle of the queue or semaphore being removed
* from the queue set (cast to an xQueueSetMemberHandle type). * from the queue set (cast to an QueueSetMemberHandle_t type).
* *
* @param xQueueSet The handle of the queue set in which the queue or semaphore * @param xQueueSet The handle of the queue set in which the queue or semaphore
* is included. * is included.
@ -1608,7 +1628,7 @@ portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSet
* then pdPASS is returned. If the queue was not in the queue set, or the * then pdPASS is returned. If the queue was not in the queue set, or the
* queue (or semaphore) was not empty, then pdFAIL is returned. * queue (or semaphore) was not empty, then pdFAIL is returned.
*/ */
portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet ) PRIVILEGED_FUNCTION; BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION;
/* /*
* xQueueSelectFromSet() selects from the members of a queue set a queue or * xQueueSelectFromSet() selects from the members of a queue set a queue or
@ -1633,30 +1653,30 @@ portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQue
* *
* @param xQueueSet The queue set on which the task will (potentially) block. * @param xQueueSet The queue set on which the task will (potentially) block.
* *
* @param xBlockTimeTicks The maximum time, in ticks, that the calling task will * @param xTicksToWait The maximum time, in ticks, that the calling task will
* remain in the Blocked state (with other tasks executing) to wait for a member * remain in the Blocked state (with other tasks executing) to wait for a member
* of the queue set to be ready for a successful queue read or semaphore take * of the queue set to be ready for a successful queue read or semaphore take
* operation. * operation.
* *
* @return xQueueSelectFromSet() will return the handle of a queue (cast to * @return xQueueSelectFromSet() will return the handle of a queue (cast to
* a xQueueSetMemberHandle type) contained in the queue set that contains data, * a QueueSetMemberHandle_t type) contained in the queue set that contains data,
* or the handle of a semaphore (cast to a xQueueSetMemberHandle type) contained * or the handle of a semaphore (cast to a QueueSetMemberHandle_t type) contained
* in the queue set that is available, or NULL if no such queue or semaphore * in the queue set that is available, or NULL if no such queue or semaphore
* exists before before the specified block time expires. * exists before before the specified block time expires.
*/ */
xQueueSetMemberHandle xQueueSelectFromSet( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks ) PRIVILEGED_FUNCTION; QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/* /*
* A version of xQueueSelectFromSet() that can be used from an ISR. * A version of xQueueSelectFromSet() that can be used from an ISR.
*/ */
xQueueSetMemberHandle xQueueSelectFromSetFromISR( xQueueSetHandle xQueueSet ) PRIVILEGED_FUNCTION; QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION;
/* Not public API functions. */ /* Not public API functions. */
void vQueueWaitForMessageRestricted( xQueueHandle xQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION; void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
portBASE_TYPE xQueueGenericReset( xQueueHandle xQueue, portBASE_TYPE xNewQueue ) PRIVILEGED_FUNCTION; BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) PRIVILEGED_FUNCTION;
void vQueueSetQueueNumber( xQueueHandle xQueue, unsigned char ucQueueNumber ) PRIVILEGED_FUNCTION; void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) PRIVILEGED_FUNCTION;
unsigned char ucQueueGetQueueNumber( xQueueHandle xQueue ) PRIVILEGED_FUNCTION; UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
unsigned char ucQueueGetQueueType( xQueueHandle xQueue ) PRIVILEGED_FUNCTION; uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -71,16 +72,23 @@
#include "queue.h" #include "queue.h"
typedef xQueueHandle xSemaphoreHandle; typedef QueueHandle_t SemaphoreHandle_t;
#define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( unsigned char ) 1U ) #define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( uint8_t ) 1U )
#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned char ) 0U ) #define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( uint8_t ) 0U )
#define semGIVE_BLOCK_TIME ( ( portTickType ) 0U ) #define semGIVE_BLOCK_TIME ( ( TickType_t ) 0U )
/** /**
* semphr. h * semphr. h
* <pre>vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore )</pre> * <pre>vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )</pre>
*
* This old vSemaphoreCreateBinary() macro is now deprecated in favour of the
* xSemaphoreCreateBinary() function. Note that binary semaphores created using
* the vSemaphoreCreateBinary() macro are created in a state such that the
* first call to 'take' the semaphore would pass, whereas binary semaphores
* created using xSemaphoreCreateBinary() are created in a state such that the
* the semaphore must first be 'given' before it can be 'taken'.
* *
* <i>Macro</i> that implements a semaphore by using the existing queue mechanism. * <i>Macro</i> that implements a semaphore by using the existing queue mechanism.
* The queue length is 1 as this is a binary semaphore. The data size is 0 * The queue length is 1 as this is a binary semaphore. The data size is 0
@ -94,11 +102,11 @@ typedef xQueueHandle xSemaphoreHandle;
* semaphore does not use a priority inheritance mechanism. For an alternative * semaphore does not use a priority inheritance mechanism. For an alternative
* that does use priority inheritance see xSemaphoreCreateMutex(). * that does use priority inheritance see xSemaphoreCreateMutex().
* *
* @param xSemaphore Handle to the created semaphore. Should be of type xSemaphoreHandle. * @param xSemaphore Handle to the created semaphore. Should be of type SemaphoreHandle_t.
* *
* Example usage: * Example usage:
<pre> <pre>
xSemaphoreHandle xSemaphore; SemaphoreHandle_t xSemaphore = NULL;
void vATask( void * pvParameters ) void vATask( void * pvParameters )
{ {
@ -109,27 +117,74 @@ typedef xQueueHandle xSemaphoreHandle;
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
*/ */
#define vSemaphoreCreateBinary( xSemaphore ) \ #define vSemaphoreCreateBinary( xSemaphore ) \
{ \ { \
( xSemaphore ) = xQueueGenericCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \
if( ( xSemaphore ) != NULL ) \ if( ( xSemaphore ) != NULL ) \
{ \ { \
( void ) xSemaphoreGive( ( xSemaphore ) ); \ ( void ) xSemaphoreGive( ( xSemaphore ) ); \
} \ } \
} }
/** /**
* semphr. h * semphr. h
* <pre>xSemaphoreTake( * <pre>SemaphoreHandle_t xSemaphoreCreateBinary( void )</pre>
* xSemaphoreHandle xSemaphore, *
* portTickType xBlockTime * The old vSemaphoreCreateBinary() macro is now deprecated in favour of this
* xSemaphoreCreateBinary() function. Note that binary semaphores created using
* the vSemaphoreCreateBinary() macro are created in a state such that the
* first call to 'take' the semaphore would pass, whereas binary semaphores
* created using xSemaphoreCreateBinary() are created in a state such that the
* the semaphore must first be 'given' before it can be 'taken'.
*
* Function that creates a semaphore by using the existing queue mechanism.
* The queue length is 1 as this is a binary semaphore. The data size is 0
* as nothing is actually stored - all that is important is whether the queue is
* empty or full (the binary semaphore is available or not).
*
* This type of semaphore can be used for pure synchronisation between tasks or
* between an interrupt and a task. The semaphore need not be given back once
* obtained, so one task/interrupt can continuously 'give' the semaphore while
* another continuously 'takes' the semaphore. For this reason this type of
* semaphore does not use a priority inheritance mechanism. For an alternative
* that does use priority inheritance see xSemaphoreCreateMutex().
*
* @return Handle to the created semaphore.
*
* Example usage:
<pre>
SemaphoreHandle_t xSemaphore = NULL;
void vATask( void * pvParameters )
{
// Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
// This is a macro so pass the variable in directly.
xSemaphore = xSemaphoreCreateBinary();
if( xSemaphore != NULL )
{
// The semaphore was created successfully.
// The semaphore can now be used.
}
}
</pre>
* \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary
* \ingroup Semaphores
*/
#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
/**
* semphr. h
* <pre>xSemaphoreTake(
* SemaphoreHandle_t xSemaphore,
* TickType_t xBlockTime
* )</pre> * )</pre>
* *
* <i>Macro</i> to obtain a semaphore. The semaphore must have previously been * <i>Macro</i> to obtain a semaphore. The semaphore must have previously been
@ -140,7 +195,7 @@ typedef xQueueHandle xSemaphoreHandle;
* the semaphore was created. * the semaphore was created.
* *
* @param xBlockTime The time in ticks to wait for the semaphore to become * @param xBlockTime The time in ticks to wait for the semaphore to become
* available. The macro portTICK_RATE_MS can be used to convert this to a * available. The macro portTICK_PERIOD_MS can be used to convert this to a
* real time. A block time of zero can be used to poll the semaphore. A block * real time. A block time of zero can be used to poll the semaphore. A block
* time of portMAX_DELAY can be used to block indefinitely (provided * time of portMAX_DELAY can be used to block indefinitely (provided
* INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h). * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h).
@ -150,7 +205,7 @@ typedef xQueueHandle xSemaphoreHandle;
* *
* Example usage: * Example usage:
<pre> <pre>
xSemaphoreHandle 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 )
@ -167,15 +222,15 @@ typedef xQueueHandle xSemaphoreHandle;
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, ( portTickType ) 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 );
} }
@ -190,28 +245,28 @@ typedef xQueueHandle xSemaphoreHandle;
* \defgroup xSemaphoreTake xSemaphoreTake * \defgroup xSemaphoreTake xSemaphoreTake
* \ingroup Semaphores * \ingroup Semaphores
*/ */
#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( xQueueHandle ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) #define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE )
/** /**
* semphr. h * semphr. h
* xSemaphoreTakeRecursive( * xSemaphoreTakeRecursive(
* xSemaphoreHandle xMutex, * SemaphoreHandle_t xMutex,
* portTickType xBlockTime * TickType_t xBlockTime
* ) * )
* *
* <i>Macro</i> to recursively obtain, or 'take', a mutex type semaphore. * <i>Macro</i> to recursively obtain, or 'take', a mutex type semaphore.
* The mutex must have previously been created using a call to * The mutex must have previously been created using a call to
* xSemaphoreCreateRecursiveMutex(); * xSemaphoreCreateRecursiveMutex();
* *
* configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this
* macro to be available. * macro to be available.
* *
* This macro must not be used on mutexes created using xSemaphoreCreateMutex(). * This macro must not be used on mutexes created using xSemaphoreCreateMutex().
* *
* A mutex used recursively can be 'taken' repeatedly by the owner. The mutex * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
* doesn't become available again until the owner has called * doesn't become available again until the owner has called
* xSemaphoreGiveRecursive() for each successful 'take' request. For example, * xSemaphoreGiveRecursive() for each successful 'take' request. For example,
* if a task successfully 'takes' the same mutex 5 times then the mutex will * if a task successfully 'takes' the same mutex 5 times then the mutex will
* not be available to any other task until it has also 'given' the mutex back * not be available to any other task until it has also 'given' the mutex back
* exactly five times. * exactly five times.
* *
@ -219,17 +274,17 @@ typedef xQueueHandle xSemaphoreHandle;
* handle returned by xSemaphoreCreateRecursiveMutex(); * handle returned by xSemaphoreCreateRecursiveMutex();
* *
* @param xBlockTime The time in ticks to wait for the semaphore to become * @param xBlockTime The time in ticks to wait for the semaphore to become
* available. The macro portTICK_RATE_MS can be used to convert this to a * available. The macro portTICK_PERIOD_MS can be used to convert this to a
* real time. A block time of zero can be used to poll the semaphore. If * real time. A block time of zero can be used to poll the semaphore. If
* the task already owns the semaphore then xSemaphoreTakeRecursive() will * the task already owns the semaphore then xSemaphoreTakeRecursive() will
* return immediately no matter what the value of xBlockTime. * return immediately no matter what the value of xBlockTime.
* *
* @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime
* expired without the semaphore becoming available. * expired without the semaphore becoming available.
* *
* Example usage: * Example usage:
<pre> <pre>
xSemaphoreHandle 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 )
@ -246,22 +301,22 @@ typedef xQueueHandle xSemaphoreHandle;
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, ( portTickType ) 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, ( portTickType ) 10 ); xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
xSemaphoreTakeRecursive( xMutex, ( portTickType ) 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
@ -286,23 +341,23 @@ typedef xQueueHandle xSemaphoreHandle;
#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) #define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) )
/* /*
* xSemaphoreAltTake() is an alternative version of xSemaphoreTake(). * xSemaphoreAltTake() is an alternative version of xSemaphoreTake().
* *
* The source code that implements the alternative (Alt) API is much * The source code that implements the alternative (Alt) API is much
* simpler because it executes everything from within a critical section. * simpler because it executes everything from within a critical section.
* This is the approach taken by many other RTOSes, but FreeRTOS.org has the * This is the approach taken by many other RTOSes, but FreeRTOS.org has the
* preferred fully featured API too. The fully featured API has more * preferred fully featured API too. The fully featured API has more
* complex code that takes longer to execute, but makes much less use of * complex code that takes longer to execute, but makes much less use of
* critical sections. Therefore the alternative API sacrifices interrupt * critical sections. Therefore the alternative API sacrifices interrupt
* responsiveness to gain execution speed, whereas the fully featured API * responsiveness to gain execution speed, whereas the fully featured API
* sacrifices execution speed to ensure better interrupt responsiveness. * sacrifices execution speed to ensure better interrupt responsiveness.
*/ */
#define xSemaphoreAltTake( xSemaphore, xBlockTime ) xQueueAltGenericReceive( ( xQueueHandle ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) #define xSemaphoreAltTake( xSemaphore, xBlockTime ) xQueueAltGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE )
/** /**
* semphr. h * semphr. h
* <pre>xSemaphoreGive( xSemaphoreHandle xSemaphore )</pre> * <pre>xSemaphoreGive( SemaphoreHandle_t xSemaphore )</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 vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or
@ -311,7 +366,7 @@ typedef xQueueHandle xSemaphoreHandle;
* This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for * This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for
* an alternative which can be used from an ISR. * an alternative which can be used from an ISR.
* *
* This macro must also not be used on semaphores created using * This macro must also not be used on semaphores created using
* xSemaphoreCreateRecursiveMutex(). * xSemaphoreCreateRecursiveMutex().
* *
* @param xSemaphore A handle to the semaphore being released. This is the * @param xSemaphore A handle to the semaphore being released. This is the
@ -319,12 +374,12 @@ typedef xQueueHandle xSemaphoreHandle;
* *
* @return pdTRUE if the semaphore was released. pdFALSE if an error occurred. * @return pdTRUE if the semaphore was released. pdFALSE if an error occurred.
* Semaphores are implemented using queues. An error can occur if there is * Semaphores are implemented using queues. An error can occur if there is
* no space on the queue to post a message - indicating that the * no space on the queue to post a message - indicating that the
* semaphore was not first obtained correctly. * semaphore was not first obtained correctly.
* *
* Example usage: * Example usage:
<pre> <pre>
xSemaphoreHandle xSemaphore = NULL; SemaphoreHandle_t xSemaphore = NULL;
void vATask( void * pvParameters ) void vATask( void * pvParameters )
{ {
@ -341,7 +396,7 @@ typedef xQueueHandle xSemaphoreHandle;
// 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, ( portTickType ) 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.
@ -361,25 +416,25 @@ typedef xQueueHandle xSemaphoreHandle;
* \defgroup xSemaphoreGive xSemaphoreGive * \defgroup xSemaphoreGive xSemaphoreGive
* \ingroup Semaphores * \ingroup Semaphores
*/ */
#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( xQueueHandle ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) #define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
/** /**
* semphr. h * semphr. h
* <pre>xSemaphoreGiveRecursive( xSemaphoreHandle xMutex )</pre> * <pre>xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex )</pre>
* *
* <i>Macro</i> to recursively release, or 'give', a mutex type semaphore. * <i>Macro</i> to recursively release, or 'give', a mutex type semaphore.
* The mutex must have previously been created using a call to * The mutex must have previously been created using a call to
* xSemaphoreCreateRecursiveMutex(); * xSemaphoreCreateRecursiveMutex();
* *
* configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this
* macro to be available. * macro to be available.
* *
* This macro must not be used on mutexes created using xSemaphoreCreateMutex(). * This macro must not be used on mutexes created using xSemaphoreCreateMutex().
* *
* A mutex used recursively can be 'taken' repeatedly by the owner. The mutex * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
* doesn't become available again until the owner has called * doesn't become available again until the owner has called
* xSemaphoreGiveRecursive() for each successful 'take' request. For example, * xSemaphoreGiveRecursive() for each successful 'take' request. For example,
* if a task successfully 'takes' the same mutex 5 times then the mutex will * if a task successfully 'takes' the same mutex 5 times then the mutex will
* not be available to any other task until it has also 'given' the mutex back * not be available to any other task until it has also 'given' the mutex back
* exactly five times. * exactly five times.
* *
@ -390,7 +445,7 @@ typedef xQueueHandle xSemaphoreHandle;
* *
* Example usage: * Example usage:
<pre> <pre>
xSemaphoreHandle 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 )
@ -407,22 +462,22 @@ typedef xQueueHandle xSemaphoreHandle;
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, ( portTickType ) 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, ( portTickType ) 10 ); xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
xSemaphoreTakeRecursive( xMutex, ( portTickType ) 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
@ -447,26 +502,26 @@ typedef xQueueHandle xSemaphoreHandle;
*/ */
#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) #define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) )
/* /*
* xSemaphoreAltGive() is an alternative version of xSemaphoreGive(). * xSemaphoreAltGive() is an alternative version of xSemaphoreGive().
* *
* The source code that implements the alternative (Alt) API is much * The source code that implements the alternative (Alt) API is much
* simpler because it executes everything from within a critical section. * simpler because it executes everything from within a critical section.
* This is the approach taken by many other RTOSes, but FreeRTOS.org has the * This is the approach taken by many other RTOSes, but FreeRTOS.org has the
* preferred fully featured API too. The fully featured API has more * preferred fully featured API too. The fully featured API has more
* complex code that takes longer to execute, but makes much less use of * complex code that takes longer to execute, but makes much less use of
* critical sections. Therefore the alternative API sacrifices interrupt * critical sections. Therefore the alternative API sacrifices interrupt
* responsiveness to gain execution speed, whereas the fully featured API * responsiveness to gain execution speed, whereas the fully featured API
* sacrifices execution speed to ensure better interrupt responsiveness. * sacrifices execution speed to ensure better interrupt responsiveness.
*/ */
#define xSemaphoreAltGive( xSemaphore ) xQueueAltGenericSend( ( xQueueHandle ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) #define xSemaphoreAltGive( xSemaphore ) xQueueAltGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
/** /**
* semphr. h * semphr. h
* <pre> * <pre>
xSemaphoreGiveFromISR( xSemaphoreGiveFromISR(
xSemaphoreHandle xSemaphore, SemaphoreHandle_t xSemaphore,
signed portBASE_TYPE *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
@ -492,14 +547,14 @@ typedef xQueueHandle xSemaphoreHandle;
<pre> <pre>
\#define LONG_TIME 0xffff \#define LONG_TIME 0xffff
\#define TICKS_TO_WAIT 10 \#define TICKS_TO_WAIT 10
xSemaphoreHandle 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.
@ -510,7 +565,7 @@ typedef xQueueHandle xSemaphoreHandle;
// ... // ...
// 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.
} }
@ -520,8 +575,8 @@ typedef xQueueHandle xSemaphoreHandle;
// Timer ISR // Timer ISR
void vTimerISR( void * pvParameters ) void vTimerISR( void * pvParameters )
{ {
static unsigned char ucLocalTickCount = 0; static uint8_t ucLocalTickCount = 0;
static signed portBASE_TYPE xHigherPriorityTaskWoken; static BaseType_t xHigherPriorityTaskWoken;
// A timer tick has occurred. // A timer tick has occurred.
@ -550,18 +605,18 @@ typedef xQueueHandle xSemaphoreHandle;
* \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR
* \ingroup Semaphores * \ingroup Semaphores
*/ */
#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueueHandle ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) #define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK )
/** /**
* semphr. h * semphr. h
* <pre> * <pre>
xSemaphoreTakeFromISR( xSemaphoreTakeFromISR(
xSemaphoreHandle xSemaphore, SemaphoreHandle_t xSemaphore,
signed portBASE_TYPE *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 vSemaphoreCreateBinary() or * previously been created with a call to vSemaphoreCreateBinary() or
* xSemaphoreCreateCounting(). * xSemaphoreCreateCounting().
* *
* Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex())
@ -581,39 +636,39 @@ typedef xQueueHandle xSemaphoreHandle;
* running task. If xSemaphoreTakeFromISR() sets this value to pdTRUE then * running task. If xSemaphoreTakeFromISR() sets this value to pdTRUE then
* a context switch should be requested before the interrupt is exited. * a context switch should be requested before the interrupt is exited.
* *
* @return pdTRUE if the semaphore was successfully taken, otherwise * @return pdTRUE if the semaphore was successfully taken, otherwise
* pdFALSE * pdFALSE
*/ */
#define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( xQueueHandle ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) ) #define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) )
/** /**
* semphr. h * semphr. h
* <pre>xSemaphoreHandle xSemaphoreCreateMutex( void )</pre> * <pre>SemaphoreHandle_t xSemaphoreCreateMutex( void )</pre>
* *
* <i>Macro</i> that implements a mutex semaphore by using the existing queue * <i>Macro</i> that implements a mutex semaphore by using the existing queue
* mechanism. * mechanism.
* *
* Mutexes created using this macro can be accessed using the xSemaphoreTake() * Mutexes created using this macro can be accessed using the xSemaphoreTake()
* and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and
* xSemaphoreGiveRecursive() macros should not be used. * xSemaphoreGiveRecursive() macros should not be used.
*
* This type of semaphore uses a priority inheritance mechanism so a task
* 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
* semaphore it is no longer required.
* *
* Mutex type semaphores cannot be used from within interrupt service routines. * This type of semaphore uses a priority inheritance mechanism so a task
* 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
* semaphore it is no longer required.
* *
* See vSemaphoreCreateBinary() for an alternative implementation that can be * Mutex type semaphores cannot be used from within interrupt service routines.
* used for pure synchronisation (where one task or interrupt always 'gives' the *
* semaphore and another always 'takes' the semaphore) and from within interrupt * See vSemaphoreCreateBinary() for an alternative implementation that can be
* used for pure synchronisation (where one task or interrupt always 'gives' the
* semaphore and another always 'takes' the semaphore) and from within interrupt
* service routines. * service routines.
* *
* @return xSemaphore Handle to the created mutex semaphore. Should be of type * @return xSemaphore Handle to the created mutex semaphore. Should be of type
* xSemaphoreHandle. * SemaphoreHandle_t.
* *
* Example usage: * Example usage:
<pre> <pre>
xSemaphoreHandle xSemaphore; SemaphoreHandle_t xSemaphore;
void vATask( void * pvParameters ) void vATask( void * pvParameters )
{ {
@ -624,7 +679,7 @@ typedef xQueueHandle xSemaphoreHandle;
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>
@ -636,39 +691,39 @@ typedef xQueueHandle xSemaphoreHandle;
/** /**
* semphr. h * semphr. h
* <pre>xSemaphoreHandle xSemaphoreCreateRecursiveMutex( void )</pre> * <pre>SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )</pre>
* *
* <i>Macro</i> that implements a recursive mutex by using the existing queue * <i>Macro</i> that implements a recursive mutex by using the existing queue
* mechanism. * mechanism.
* *
* Mutexes created using this macro can be accessed using the * Mutexes created using this macro can be accessed using the
* xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The
* xSemaphoreTake() and xSemaphoreGive() macros should not be used. * xSemaphoreTake() and xSemaphoreGive() macros should not be used.
* *
* A mutex used recursively can be 'taken' repeatedly by the owner. The mutex * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
* doesn't become available again until the owner has called * doesn't become available again until the owner has called
* xSemaphoreGiveRecursive() for each successful 'take' request. For example, * xSemaphoreGiveRecursive() for each successful 'take' request. For example,
* if a task successfully 'takes' the same mutex 5 times then the mutex will * if a task successfully 'takes' the same mutex 5 times then the mutex will
* not be available to any other task until it has also 'given' the mutex back * not be available to any other task until it has also 'given' the mutex back
* exactly five times. * exactly five times.
*
* This type of semaphore uses a priority inheritance mechanism so a task
* 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
* semaphore it is no longer required.
* *
* Mutex type semaphores cannot be used from within interrupt service routines. * This type of semaphore uses a priority inheritance mechanism so a task
* 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
* semaphore it is no longer required.
* *
* See vSemaphoreCreateBinary() for an alternative implementation that can be * Mutex type semaphores cannot be used from within interrupt service routines.
* used for pure synchronisation (where one task or interrupt always 'gives' the *
* semaphore and another always 'takes' the semaphore) and from within interrupt * See vSemaphoreCreateBinary() for an alternative implementation that can be
* used for pure synchronisation (where one task or interrupt always 'gives' the
* semaphore and another always 'takes' the semaphore) and from within interrupt
* service routines. * service routines.
* *
* @return xSemaphore Handle to the created mutex semaphore. Should be of type * @return xSemaphore Handle to the created mutex semaphore. Should be of type
* xSemaphoreHandle. * SemaphoreHandle_t.
* *
* Example usage: * Example usage:
<pre> <pre>
xSemaphoreHandle xSemaphore; SemaphoreHandle_t xSemaphore;
void vATask( void * pvParameters ) void vATask( void * pvParameters )
{ {
@ -679,7 +734,7 @@ typedef xQueueHandle xSemaphoreHandle;
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>
@ -690,34 +745,34 @@ typedef xQueueHandle xSemaphoreHandle;
/** /**
* semphr. h * semphr. h
* <pre>xSemaphoreHandle xSemaphoreCreateCounting( unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount )</pre> * <pre>SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount )</pre>
* *
* <i>Macro</i> that creates a counting semaphore by using the existing * <i>Macro</i> that creates a counting semaphore by using the existing
* queue mechanism. * queue mechanism.
* *
* Counting semaphores are typically used for two things: * Counting semaphores are typically used for two things:
* *
* 1) Counting events. * 1) Counting events.
* *
* In this usage scenario an event handler will 'give' a semaphore each time * In this usage scenario an event handler will 'give' a semaphore each time
* an event occurs (incrementing the semaphore count value), and a handler * an event occurs (incrementing the semaphore count value), and a handler
* task will 'take' a semaphore each time it processes an event * task will 'take' a semaphore each time it processes an event
* (decrementing the semaphore count value). The count value is therefore * (decrementing the semaphore count value). The count value is therefore
* the difference between the number of events that have occurred and the * the difference between the number of events that have occurred and the
* number that have been processed. In this case it is desirable for the * number that have been processed. In this case it is desirable for the
* initial count value to be zero. * initial count value to be zero.
* *
* 2) Resource management. * 2) Resource management.
* *
* In this usage scenario the count value indicates the number of resources * In this usage scenario the count value indicates the number of resources
* available. To obtain control of a resource a task must first obtain a * available. To obtain control of a resource a task must first obtain a
* semaphore - decrementing the semaphore count value. When the count value * semaphore - decrementing the semaphore count value. When the count value
* reaches zero there are no free resources. When a task finishes with the * reaches zero there are no free resources. When a task finishes with the
* resource it 'gives' the semaphore back - incrementing the semaphore count * resource it 'gives' the semaphore back - incrementing the semaphore count
* value. In this case it is desirable for the initial count value to be * value. In this case it is desirable for the initial count value to be
* equal to the maximum count value, indicating that all resources are free. * equal to the maximum count value, indicating that all resources are free.
* *
* @param uxMaxCount The maximum count value that can be reached. When the * @param uxMaxCount The maximum count value that can be reached. When the
* semaphore reaches this value it can no longer be 'given'. * semaphore reaches this value it can no longer be 'given'.
* *
* @param uxInitialCount The count value assigned to the semaphore when it is * @param uxInitialCount The count value assigned to the semaphore when it is
@ -725,14 +780,14 @@ typedef xQueueHandle xSemaphoreHandle;
* *
* @return Handle to the created semaphore. Null if the semaphore could not be * @return Handle to the created semaphore. Null if the semaphore could not be
* created. * created.
* *
* Example usage: * Example usage:
<pre> <pre>
xSemaphoreHandle xSemaphore; SemaphoreHandle_t xSemaphore;
void vATask( void * pvParameters ) void vATask( void * pvParameters )
{ {
xSemaphoreHandle 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
@ -742,7 +797,7 @@ typedef xQueueHandle xSemaphoreHandle;
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>
@ -753,7 +808,7 @@ typedef xQueueHandle xSemaphoreHandle;
/** /**
* semphr. h * semphr. h
* <pre>void vSemaphoreDelete( xSemaphoreHandle xSemaphore );</pre> * <pre>void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );</pre>
* *
* Delete a semaphore. This function must be used with care. For example, * Delete a semaphore. This function must be used with care. For example,
* do not delete a mutex type semaphore if the mutex is held by a task. * do not delete a mutex type semaphore if the mutex is held by a task.
@ -763,17 +818,17 @@ typedef xQueueHandle xSemaphoreHandle;
* \defgroup vSemaphoreDelete vSemaphoreDelete * \defgroup vSemaphoreDelete vSemaphoreDelete
* \ingroup Semaphores * \ingroup Semaphores
*/ */
#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( xQueueHandle ) ( xSemaphore ) ) #define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )
/** /**
* semphr.h * semphr.h
* <pre>xTaskHandle xSemaphoreGetMutexHolder( xSemaphoreHandle xMutex );</pre> * <pre>TaskHandle_t xSemaphoreGetMutexHolder( SemaphoreHandle_t xMutex );</pre>
* *
* If xMutex is indeed a mutex type semaphore, return the current mutex holder. * If xMutex is indeed a mutex type semaphore, return the current mutex holder.
* If xMutex is not a mutex type semaphore, or the mutex is available (not held * If xMutex is not a mutex type semaphore, or the mutex is available (not held
* by a task), return NULL. * by a task), return NULL.
* *
* Note: This Is is a good way of determining if the calling task is the mutex * Note: This is a good way of determining if the calling task is the mutex
* holder, but not a good way of determining the identity of the mutex holder as * holder, but not a good way of determining the identity of the mutex holder as
* the holder may change between the function exiting and the returned value * the holder may change between the function exiting and the returned value
* being tested. * being tested.

View File

@ -0,0 +1,27 @@
#ifndef FREERTOS_STDINT
#define FREERTOS_STDINT
/*******************************************************************************
* THIS IS NOT A FULL stdint.h IMPLEMENTATION - It only contains the definitions
* necessary to build the FreeRTOS code. It is provided to allow FreeRTOS to be
* built using compilers that do not provide their own stdint.h definition.
*
* To use this file:
*
* 1) Copy this file into the directory that contains your FreeRTOSConfig.h
* header file, as that directory will already be in the compilers include
* path.
*
* 2) Rename the copied file stdint.h.
*
*/
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef long int32_t;
typedef unsigned long uint32_t;
#endif /* FREERTOS_STDINT */

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -80,19 +81,28 @@ extern "C" {
* MACROS AND DEFINITIONS * MACROS AND DEFINITIONS
*----------------------------------------------------------*/ *----------------------------------------------------------*/
#define tskKERNEL_VERSION_NUMBER "V7.5.2" #define tskKERNEL_VERSION_NUMBER "V8.0.0"
#define tskKERNEL_VERSION_MAJOR 8
#define tskKERNEL_VERSION_MINOR 0
#define tskKERNEL_VERSION_BUILD 0
/** /**
* task. h * task. h
* *
* Type by which tasks are referenced. For example, a call to xTaskCreate * Type by which tasks are referenced. For example, a call to xTaskCreate
* returns (via a pointer parameter) an xTaskHandle variable that can then * returns (via a pointer parameter) an TaskHandle_t variable that can then
* be used as a parameter to vTaskDelete to delete the task. * be used as a parameter to vTaskDelete to delete the task.
* *
* \defgroup xTaskHandle xTaskHandle * \defgroup TaskHandle_t TaskHandle_t
* \ingroup Tasks * \ingroup Tasks
*/ */
typedef void * xTaskHandle; typedef void * TaskHandle_t;
/*
* Defines the prototype to which the application task hook function must
* conform.
*/
typedef BaseType_t (*TaskHookFunction_t)( void * );
/* Task states returned by eTaskGetState. */ /* Task states returned by eTaskGetState. */
typedef enum typedef enum
@ -109,9 +119,9 @@ typedef enum
*/ */
typedef struct xTIME_OUT typedef struct xTIME_OUT
{ {
portBASE_TYPE xOverflowCount; BaseType_t xOverflowCount;
portTickType xTimeOnEntering; TickType_t xTimeOnEntering;
} xTimeOutType; } TimeOut_t;
/* /*
* Defines the memory ranges allocated to the task when an MPU is used. * Defines the memory ranges allocated to the task when an MPU is used.
@ -119,37 +129,37 @@ typedef struct xTIME_OUT
typedef struct xMEMORY_REGION typedef struct xMEMORY_REGION
{ {
void *pvBaseAddress; void *pvBaseAddress;
unsigned long ulLengthInBytes; uint32_t ulLengthInBytes;
unsigned long ulParameters; uint32_t ulParameters;
} xMemoryRegion; } MemoryRegion_t;
/* /*
* Parameters required to create an MPU protected task. * Parameters required to create an MPU protected task.
*/ */
typedef struct xTASK_PARAMTERS typedef struct xTASK_PARAMETERS
{ {
pdTASK_CODE pvTaskCode; TaskFunction_t pvTaskCode;
const signed char * const pcName; const char * const pcName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
unsigned short usStackDepth; uint16_t usStackDepth;
void *pvParameters; void *pvParameters;
unsigned portBASE_TYPE uxPriority; UBaseType_t uxPriority;
portSTACK_TYPE *puxStackBuffer; StackType_t *puxStackBuffer;
xMemoryRegion xRegions[ portNUM_CONFIGURABLE_REGIONS ]; MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ];
} xTaskParameters; } TaskParameters_t;
/* Used with the uxTaskGetSystemState() function to return the state of each task /* Used with the uxTaskGetSystemState() function to return the state of each task
in the system. */ in the system. */
typedef struct xTASK_STATUS typedef struct xTASK_STATUS
{ {
xTaskHandle xHandle; /* The handle of the task to which the rest of the information in the structure relates. */ TaskHandle_t xHandle; /* The handle of the task to which the rest of the information in the structure relates. */
const signed char *pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ const char *pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
unsigned portBASE_TYPE xTaskNumber; /* A number unique to the task. */ UBaseType_t xTaskNumber; /* A number unique to the task. */
eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */ eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */
unsigned portBASE_TYPE uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */ UBaseType_t uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */
unsigned portBASE_TYPE uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */ UBaseType_t uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */
unsigned long ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See http://www.freertos.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */ uint32_t ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See http://www.freertos.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */
unsigned short usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */ uint16_t usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */
} xTaskStatusType; } TaskStatus_t;
/* Possible return values for eTaskConfirmSleepModeStatus(). */ /* Possible return values for eTaskConfirmSleepModeStatus(). */
typedef enum typedef enum
@ -160,12 +170,12 @@ typedef enum
} eSleepModeStatus; } eSleepModeStatus;
/* /**
* Defines the priority used by the idle task. This must not be modified. * Defines the priority used by the idle task. This must not be modified.
* *
* \ingroup TaskUtils * \ingroup TaskUtils
*/ */
#define tskIDLE_PRIORITY ( ( unsigned portBASE_TYPE ) 0U ) #define tskIDLE_PRIORITY ( ( UBaseType_t ) 0U )
/** /**
* task. h * task. h
@ -225,10 +235,13 @@ typedef enum
*/ */
#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() #define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS()
/* Definitions returned by xTaskGetSchedulerState(). */ /* Definitions returned by xTaskGetSchedulerState(). taskSCHEDULER_SUSPENDED is
#define taskSCHEDULER_NOT_STARTED ( ( portBASE_TYPE ) 0 ) 0 to generate more optimal code when configASSERT() is defined as the constant
#define taskSCHEDULER_RUNNING ( ( portBASE_TYPE ) 1 ) is used in assert() statements. */
#define taskSCHEDULER_SUSPENDED ( ( portBASE_TYPE ) 2 ) #define taskSCHEDULER_SUSPENDED ( ( BaseType_t ) 0 )
#define taskSCHEDULER_NOT_STARTED ( ( BaseType_t ) 1 )
#define taskSCHEDULER_RUNNING ( ( BaseType_t ) 2 )
/*----------------------------------------------------------- /*-----------------------------------------------------------
* TASK CREATION API * TASK CREATION API
@ -237,13 +250,13 @@ typedef enum
/** /**
* task. h * task. h
*<pre> *<pre>
portBASE_TYPE xTaskCreate( BaseType_t xTaskCreate(
pdTASK_CODE pvTaskCode, TaskFunction_t pvTaskCode,
const char * const pcName, const char * const pcName,
unsigned short usStackDepth, uint16_t usStackDepth,
void *pvParameters, void *pvParameters,
unsigned portBASE_TYPE uxPriority, UBaseType_t uxPriority,
xTaskHandle *pvCreatedTask TaskHandle_t *pvCreatedTask
);</pre> );</pre>
* *
* Create a new task and add it to the list of tasks that are ready to run. * Create a new task and add it to the list of tasks that are ready to run.
@ -257,7 +270,7 @@ typedef enum
* must be implemented to never return (i.e. continuous loop). * must be implemented to never return (i.e. continuous loop).
* *
* @param pcName A descriptive name for the task. This is mainly used to * @param pcName A descriptive name for the task. This is mainly used to
* facilitate debugging. Max length defined by tskMAX_TASK_NAME_LEN - default * facilitate debugging. Max length defined by configMAX_TASK_NAME_LEN - default
* is 16. * is 16.
* *
* @param usStackDepth The size of the task stack specified as the number of * @param usStackDepth The size of the task stack specified as the number of
@ -278,7 +291,7 @@ typedef enum
* can be referenced. * can be referenced.
* *
* @return pdPASS if the task was successfully created and added to a ready * @return pdPASS if the task was successfully created and added to a ready
* list, otherwise an error code defined in the file errors. h * list, otherwise an error code defined in the file projdefs.h
* *
* Example usage: * Example usage:
<pre> <pre>
@ -294,17 +307,21 @@ typedef enum
// Function that creates a task. // Function that creates a task.
void vOtherFunction( void ) void vOtherFunction( void )
{ {
static unsigned char ucParameterToPass; static uint8_t ucParameterToPass;
xTaskHandle xHandle; TaskHandle_t xHandle = NULL;
// Create the task, storing the handle. Note that the passed parameter ucParameterToPass // Create the task, storing the handle. Note that the passed parameter ucParameterToPass
// must exist for the lifetime of the task, so in this case is declared static. If it was just an // must exist for the lifetime of the task, so in this case is declared static. If it was just an
// an automatic stack variable it might no longer exist, or at least have been corrupted, by the time // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
// the new task attempts to access it. // the new task attempts to access it.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle ); xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
configASSERT( xHandle );
// Use the handle to delete the task. // Use the handle to delete the task.
vTaskDelete( xHandle ); if( xHandle != NULL )
{
vTaskDelete( xHandle );
}
} }
</pre> </pre>
* \defgroup xTaskCreate xTaskCreate * \defgroup xTaskCreate xTaskCreate
@ -315,7 +332,7 @@ typedef enum
/** /**
* task. h * task. h
*<pre> *<pre>
portBASE_TYPE xTaskCreateRestricted( xTaskParameters *pxTaskDefinition, xTaskHandle *pxCreatedTask );</pre> BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );</pre>
* *
* xTaskCreateRestricted() should only be used in systems that include an MPU * xTaskCreateRestricted() should only be used in systems that include an MPU
* implementation. * implementation.
@ -333,12 +350,12 @@ typedef enum
* can be referenced. * can be referenced.
* *
* @return pdPASS if the task was successfully created and added to a ready * @return pdPASS if the task was successfully created and added to a ready
* list, otherwise an error code defined in the file errors. h * list, otherwise an error code defined in the file projdefs.h
* *
* Example usage: * Example usage:
<pre> <pre>
// Create an xTaskParameters structure that defines the task to be created. // Create an TaskParameters_t structure that defines the task to be created.
static const xTaskParameters xCheckTaskParameters = static const TaskParameters_t xCheckTaskParameters =
{ {
vATask, // pvTaskCode - the function that implements the task. vATask, // pvTaskCode - the function that implements the task.
"ATask", // pcName - just a text name for the task to assist debugging. "ATask", // pcName - just a text name for the task to assist debugging.
@ -361,7 +378,7 @@ static const xTaskParameters xCheckTaskParameters =
int main( void ) int main( void )
{ {
xTaskHandle xHandle; TaskHandle_t xHandle;
// Create a task from the const structure defined above. The task handle // Create a task from the const structure defined above. The task handle
// is requested (the second parameter is not NULL) but in this case just for // is requested (the second parameter is not NULL) but in this case just for
@ -372,7 +389,7 @@ xTaskHandle xHandle;
vTaskStartScheduler(); vTaskStartScheduler();
// Will only get here if there was insufficient memory to create the idle // Will only get here if there was insufficient memory to create the idle
// task. // and/or timer task.
for( ;; ); for( ;; );
} }
</pre> </pre>
@ -384,7 +401,7 @@ xTaskHandle xHandle;
/** /**
* task. h * task. h
*<pre> *<pre>
void vTaskAllocateMPURegions( xTaskHandle xTask, const xMemoryRegion * const pxRegions );</pre> void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions );</pre>
* *
* Memory regions are assigned to a restricted task when the task is created by * Memory regions are assigned to a restricted task when the task is created by
* a call to xTaskCreateRestricted(). These regions can be redefined using * a call to xTaskCreateRestricted(). These regions can be redefined using
@ -392,16 +409,16 @@ xTaskHandle xHandle;
* *
* @param xTask The handle of the task being updated. * @param xTask The handle of the task being updated.
* *
* @param xRegions A pointer to an xMemoryRegion structure that contains the * @param xRegions A pointer to an MemoryRegion_t structure that contains the
* new memory region definitions. * new memory region definitions.
* *
* Example usage: * Example usage:
<pre> <pre>
// Define an array of xMemoryRegion structures that configures an MPU region // Define an array of MemoryRegion_t structures that configures an MPU region
// allowing read/write access for 1024 bytes starting at the beginning of the // allowing read/write access for 1024 bytes starting at the beginning of the
// ucOneKByte array. The other two of the maximum 3 definable regions are // ucOneKByte array. The other two of the maximum 3 definable regions are
// unused so set to zero. // unused so set to zero.
static const xMemoryRegion xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] = static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
{ {
// Base address Length Parameters // Base address Length Parameters
{ ucOneKByte, 1024, portMPU_REGION_READ_WRITE }, { ucOneKByte, 1024, portMPU_REGION_READ_WRITE },
@ -427,16 +444,16 @@ void vATask( void *pvParameters )
* \defgroup xTaskCreateRestricted xTaskCreateRestricted * \defgroup xTaskCreateRestricted xTaskCreateRestricted
* \ingroup Tasks * \ingroup Tasks
*/ */
void vTaskAllocateMPURegions( xTaskHandle xTask, const xMemoryRegion * const pxRegions ) PRIVILEGED_FUNCTION; void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions ) PRIVILEGED_FUNCTION;
/** /**
* task. h * task. h
* <pre>void vTaskDelete( xTaskHandle xTask );</pre> * <pre>void vTaskDelete( TaskHandle_t xTask );</pre>
* *
* INCLUDE_vTaskDelete must be defined as 1 for this function to be available. * INCLUDE_vTaskDelete must be defined as 1 for this function to be available.
* See the configuration section for more information. * See the configuration section for more information.
* *
* Remove a task from the RTOS real time kernels management. The task being * Remove a task from the RTOS real time kernel's management. The task being
* deleted will be removed from all ready, blocked, suspended and event lists. * deleted will be removed from all ready, blocked, suspended and event lists.
* *
* NOTE: The idle task is responsible for freeing the kernel allocated * NOTE: The idle task is responsible for freeing the kernel allocated
@ -456,7 +473,7 @@ void vTaskAllocateMPURegions( xTaskHandle xTask, const xMemoryRegion * const pxR
<pre> <pre>
void vOtherFunction( void ) void vOtherFunction( void )
{ {
xTaskHandle xHandle; TaskHandle_t xHandle;
// Create the task, storing the handle. // Create the task, storing the handle.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
@ -468,7 +485,7 @@ void vTaskAllocateMPURegions( xTaskHandle xTask, const xMemoryRegion * const pxR
* \defgroup vTaskDelete vTaskDelete * \defgroup vTaskDelete vTaskDelete
* \ingroup Tasks * \ingroup Tasks
*/ */
void vTaskDelete( xTaskHandle xTaskToDelete ) PRIVILEGED_FUNCTION; void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION;
/*----------------------------------------------------------- /*-----------------------------------------------------------
* TASK CONTROL API * TASK CONTROL API
@ -476,11 +493,11 @@ void vTaskDelete( xTaskHandle xTaskToDelete ) PRIVILEGED_FUNCTION;
/** /**
* task. h * task. h
* <pre>void vTaskDelay( portTickType xTicksToDelay );</pre> * <pre>void vTaskDelay( const TickType_t xTicksToDelay );</pre>
* *
* Delay a task for a given number of ticks. The actual time that the * Delay a task for a given number of ticks. The actual time that the
* task remains blocked depends on the tick rate. The constant * task remains blocked depends on the tick rate. The constant
* portTICK_RATE_MS can be used to calculate real time from the tick * portTICK_PERIOD_MS can be used to calculate real time from the tick
* rate - with the resolution of one tick period. * rate - with the resolution of one tick period.
* *
* INCLUDE_vTaskDelay must be defined as 1 for this function to be available. * INCLUDE_vTaskDelay must be defined as 1 for this function to be available.
@ -491,7 +508,7 @@ void vTaskDelete( xTaskHandle xTaskToDelete ) PRIVILEGED_FUNCTION;
* the time at which vTaskDelay() is called. For example, specifying a block * the time at which vTaskDelay() is called. For example, specifying a block
* period of 100 ticks will cause the task to unblock 100 ticks after * period of 100 ticks will cause the task to unblock 100 ticks after
* vTaskDelay() is called. vTaskDelay() does not therefore provide a good method * vTaskDelay() is called. vTaskDelay() does not therefore provide a good method
* of controlling the frequency of a cyclical task as the path taken through the * of controlling the frequency of a periodic task as the path taken through the
* code, as well as other task and interrupt activity, will effect the frequency * code, as well as other task and interrupt activity, will effect the frequency
* at which vTaskDelay() gets called and therefore the time at which the task * at which vTaskDelay() gets called and therefore the time at which the task
* next executes. See vTaskDelayUntil() for an alternative API function designed * next executes. See vTaskDelayUntil() for an alternative API function designed
@ -504,12 +521,10 @@ void vTaskDelete( xTaskHandle xTaskToDelete ) PRIVILEGED_FUNCTION;
* *
* Example usage: * Example usage:
void vTaskFunction( void * pvParameters )
{
void vTaskFunction( void * pvParameters ) void vTaskFunction( void * pvParameters )
{ {
// Block for 500ms. // Block for 500ms.
const portTickType xDelay = 500 / portTICK_RATE_MS; const TickType_t xDelay = 500 / portTICK_PERIOD_MS;
for( ;; ) for( ;; )
{ {
@ -522,16 +537,16 @@ void vTaskDelete( xTaskHandle xTaskToDelete ) PRIVILEGED_FUNCTION;
* \defgroup vTaskDelay vTaskDelay * \defgroup vTaskDelay vTaskDelay
* \ingroup TaskCtrl * \ingroup TaskCtrl
*/ */
void vTaskDelay( portTickType xTicksToDelay ) PRIVILEGED_FUNCTION; void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION;
/** /**
* task. h * task. h
* <pre>void vTaskDelayUntil( portTickType *pxPreviousWakeTime, portTickType xTimeIncrement );</pre> * <pre>void vTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement );</pre>
* *
* INCLUDE_vTaskDelayUntil must be defined as 1 for this function to be available. * INCLUDE_vTaskDelayUntil must be defined as 1 for this function to be available.
* See the configuration section for more information. * See the configuration section for more information.
* *
* Delay a task until a specified time. This function can be used by cyclical * Delay a task until a specified time. This function can be used by periodic
* tasks to ensure a constant execution frequency. * tasks to ensure a constant execution frequency.
* *
* This function differs from vTaskDelay () in one important aspect: vTaskDelay () will * This function differs from vTaskDelay () in one important aspect: vTaskDelay () will
@ -546,7 +561,7 @@ void vTaskDelay( portTickType xTicksToDelay ) PRIVILEGED_FUNCTION;
* is called, vTaskDelayUntil () specifies the absolute (exact) time at which it wishes to * is called, vTaskDelayUntil () specifies the absolute (exact) time at which it wishes to
* unblock. * unblock.
* *
* The constant portTICK_RATE_MS can be used to calculate real time from the tick * The constant portTICK_PERIOD_MS can be used to calculate real time from the tick
* rate - with the resolution of one tick period. * rate - with the resolution of one tick period.
* *
* @param pxPreviousWakeTime Pointer to a variable that holds the time at which the * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the
@ -564,8 +579,8 @@ void vTaskDelay( portTickType xTicksToDelay ) PRIVILEGED_FUNCTION;
// Perform an action every 10 ticks. // Perform an action every 10 ticks.
void vTaskFunction( void * pvParameters ) void vTaskFunction( void * pvParameters )
{ {
portTickType xLastWakeTime; TickType_t xLastWakeTime;
const portTickType xFrequency = 10; const TickType_t xFrequency = 10;
// Initialise the xLastWakeTime variable with the current time. // Initialise the xLastWakeTime variable with the current time.
xLastWakeTime = xTaskGetTickCount (); xLastWakeTime = xTaskGetTickCount ();
@ -581,13 +596,13 @@ void vTaskDelay( portTickType xTicksToDelay ) PRIVILEGED_FUNCTION;
* \defgroup vTaskDelayUntil vTaskDelayUntil * \defgroup vTaskDelayUntil vTaskDelayUntil
* \ingroup TaskCtrl * \ingroup TaskCtrl
*/ */
void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement ) PRIVILEGED_FUNCTION; void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) PRIVILEGED_FUNCTION;
/** /**
* task. h * task. h
* <pre>unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle xTask );</pre> * <pre>UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );</pre>
* *
* INCLUDE_xTaskPriorityGet must be defined as 1 for this function to be available. * INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be available.
* See the configuration section for more information. * See the configuration section for more information.
* *
* Obtain the priority of any task. * Obtain the priority of any task.
@ -601,7 +616,7 @@ void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTim
<pre> <pre>
void vAFunction( void ) void vAFunction( void )
{ {
xTaskHandle xHandle; TaskHandle_t xHandle;
// Create a task, storing the handle. // Create a task, storing the handle.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
@ -628,11 +643,11 @@ void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTim
* \defgroup uxTaskPriorityGet uxTaskPriorityGet * \defgroup uxTaskPriorityGet uxTaskPriorityGet
* \ingroup TaskCtrl * \ingroup TaskCtrl
*/ */
unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle xTask ) PRIVILEGED_FUNCTION; UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
/** /**
* task. h * task. h
* <pre>eTaskState eTaskGetState( xTaskHandle xTask );</pre> * <pre>eTaskState eTaskGetState( TaskHandle_t xTask );</pre>
* *
* INCLUDE_eTaskGetState must be defined as 1 for this function to be available. * INCLUDE_eTaskGetState must be defined as 1 for this function to be available.
* See the configuration section for more information. * See the configuration section for more information.
@ -646,11 +661,11 @@ unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle xTask ) PRIVILEGED_FUNCTIO
* state of the task might change between the function being called, and the * state of the task might change between the function being called, and the
* functions return value being tested by the calling task. * functions return value being tested by the calling task.
*/ */
eTaskState eTaskGetState( xTaskHandle xTask ) PRIVILEGED_FUNCTION; eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
/** /**
* task. h * task. h
* <pre>void vTaskPrioritySet( xTaskHandle xTask, unsigned portBASE_TYPE uxNewPriority );</pre> * <pre>void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );</pre>
* *
* INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available. * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available.
* See the configuration section for more information. * See the configuration section for more information.
@ -669,7 +684,7 @@ eTaskState eTaskGetState( xTaskHandle xTask ) PRIVILEGED_FUNCTION;
<pre> <pre>
void vAFunction( void ) void vAFunction( void )
{ {
xTaskHandle xHandle; TaskHandle_t xHandle;
// Create a task, storing the handle. // Create a task, storing the handle.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
@ -688,11 +703,11 @@ eTaskState eTaskGetState( xTaskHandle xTask ) PRIVILEGED_FUNCTION;
* \defgroup vTaskPrioritySet vTaskPrioritySet * \defgroup vTaskPrioritySet vTaskPrioritySet
* \ingroup TaskCtrl * \ingroup TaskCtrl
*/ */
void vTaskPrioritySet( xTaskHandle xTask, unsigned portBASE_TYPE uxNewPriority ) PRIVILEGED_FUNCTION; void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION;
/** /**
* task. h * task. h
* <pre>void vTaskSuspend( xTaskHandle xTaskToSuspend );</pre> * <pre>void vTaskSuspend( TaskHandle_t xTaskToSuspend );</pre>
* *
* INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available.
* See the configuration section for more information. * See the configuration section for more information.
@ -711,7 +726,7 @@ void vTaskPrioritySet( xTaskHandle xTask, unsigned portBASE_TYPE uxNewPriority )
<pre> <pre>
void vAFunction( void ) void vAFunction( void )
{ {
xTaskHandle xHandle; TaskHandle_t xHandle;
// Create a task, storing the handle. // Create a task, storing the handle.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
@ -739,18 +754,18 @@ void vTaskPrioritySet( xTaskHandle xTask, unsigned portBASE_TYPE uxNewPriority )
* \defgroup vTaskSuspend vTaskSuspend * \defgroup vTaskSuspend vTaskSuspend
* \ingroup TaskCtrl * \ingroup TaskCtrl
*/ */
void vTaskSuspend( xTaskHandle xTaskToSuspend ) PRIVILEGED_FUNCTION; void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION;
/** /**
* task. h * task. h
* <pre>void vTaskResume( xTaskHandle xTaskToResume );</pre> * <pre>void vTaskResume( TaskHandle_t xTaskToResume );</pre>
* *
* INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available.
* See the configuration section for more information. * See the configuration section for more information.
* *
* Resumes a suspended task. * Resumes a suspended task.
* *
* A task that has been suspended by one of more calls to vTaskSuspend () * A task that has been suspended by one or more calls to vTaskSuspend ()
* will be made available for running again by a single call to * will be made available for running again by a single call to
* vTaskResume (). * vTaskResume ().
* *
@ -760,7 +775,7 @@ void vTaskSuspend( xTaskHandle xTaskToSuspend ) PRIVILEGED_FUNCTION;
<pre> <pre>
void vAFunction( void ) void vAFunction( void )
{ {
xTaskHandle xHandle; TaskHandle_t xHandle;
// Create a task, storing the handle. // Create a task, storing the handle.
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
@ -782,33 +797,42 @@ void vTaskSuspend( xTaskHandle xTaskToSuspend ) PRIVILEGED_FUNCTION;
vTaskResume( xHandle ); vTaskResume( xHandle );
// The created task will once again get microcontroller processing // The created task will once again get microcontroller processing
// time in accordance with it priority within the system. // time in accordance with its priority within the system.
} }
</pre> </pre>
* \defgroup vTaskResume vTaskResume * \defgroup vTaskResume vTaskResume
* \ingroup TaskCtrl * \ingroup TaskCtrl
*/ */
void vTaskResume( xTaskHandle xTaskToResume ) PRIVILEGED_FUNCTION; void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION;
/** /**
* task. h * task. h
* <pre>void xTaskResumeFromISR( xTaskHandle xTaskToResume );</pre> * <pre>void xTaskResumeFromISR( TaskHandle_t xTaskToResume );</pre>
* *
* INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be
* available. See the configuration section for more information. * available. See the configuration section for more information.
* *
* An implementation of vTaskResume() that can be called from within an ISR. * An implementation of vTaskResume() that can be called from within an ISR.
* *
* A task that has been suspended by one of more calls to vTaskSuspend () * A task that has been suspended by one or more calls to vTaskSuspend ()
* will be made available for running again by a single call to * will be made available for running again by a single call to
* xTaskResumeFromISR (). * xTaskResumeFromISR ().
* *
* xTaskResumeFromISR() should not be used to synchronise a task with an
* interrupt if there is a chance that the interrupt could arrive prior to the
* task being suspended - as this can lead to interrupts being missed. Use of a
* semaphore as a synchronisation mechanism would avoid this eventuality.
*
* @param xTaskToResume Handle to the task being readied. * @param xTaskToResume Handle to the task being readied.
* *
* @return pdTRUE if resuming the task should result in a context switch,
* otherwise pdFALSE. This is used by the ISR to determine if a context switch
* may be required following the ISR.
*
* \defgroup vTaskResumeFromISR vTaskResumeFromISR * \defgroup vTaskResumeFromISR vTaskResumeFromISR
* \ingroup TaskCtrl * \ingroup TaskCtrl
*/ */
portBASE_TYPE xTaskResumeFromISR( xTaskHandle xTaskToResume ) PRIVILEGED_FUNCTION; BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION;
/*----------------------------------------------------------- /*-----------------------------------------------------------
* SCHEDULER CONTROL * SCHEDULER CONTROL
@ -819,12 +843,7 @@ portBASE_TYPE xTaskResumeFromISR( xTaskHandle xTaskToResume ) PRIVILEGED_FUNCTIO
* <pre>void vTaskStartScheduler( void );</pre> * <pre>void vTaskStartScheduler( void );</pre>
* *
* Starts the real time kernel tick processing. After calling the kernel * Starts the real time kernel tick processing. After calling the kernel
* has control over which tasks are executed and when. This function * has control over which tasks are executed and when.
* does not return until an executing task calls vTaskEndScheduler ().
*
* At least one task should be created via a call to xTaskCreate ()
* before calling vTaskStartScheduler (). The idle task is created
* automatically when the first application task is created.
* *
* See the demo application file main.c for an example of creating * See the demo application file main.c for an example of creating
* tasks and starting the kernel. * tasks and starting the kernel.
@ -852,6 +871,9 @@ void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION;
* task. h * task. h
* <pre>void vTaskEndScheduler( void );</pre> * <pre>void vTaskEndScheduler( void );</pre>
* *
* NOTE: At the time of writing only the x86 real mode port, which runs on a PC
* in place of DOS, implements this function.
*
* Stops the real time kernel tick. All created tasks will be automatically * Stops the real time kernel tick. All created tasks will be automatically
* deleted and multitasking (either preemptive or cooperative) will * deleted and multitasking (either preemptive or cooperative) will
* stop. Execution then resumes from the point where vTaskStartScheduler () * stop. Execution then resumes from the point where vTaskStartScheduler ()
@ -905,8 +927,8 @@ void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION;
* task. h * task. h
* <pre>void vTaskSuspendAll( void );</pre> * <pre>void vTaskSuspendAll( void );</pre>
* *
* Suspends all real time kernel activity while keeping interrupts (including the * Suspends the scheduler without disabling interrupts. Context switches will
* kernel tick) enabled. * not occur while the scheduler is suspended.
* *
* After calling vTaskSuspendAll () the calling task will continue to execute * After calling vTaskSuspendAll () the calling task will continue to execute
* without risk of being swapped out until a call to xTaskResumeAll () has been * without risk of being swapped out until a call to xTaskResumeAll () has been
@ -954,11 +976,13 @@ void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION;
/** /**
* task. h * task. h
* <pre>char xTaskResumeAll( void );</pre> * <pre>BaseType_t xTaskResumeAll( void );</pre>
* *
* Resumes real time kernel activity following a call to vTaskSuspendAll (). * Resumes scheduler activity after it was suspended by a call to
* After a call to vTaskSuspendAll () the kernel will take control of which * vTaskSuspendAll().
* task is executing at any time. *
* xTaskResumeAll() only resumes the scheduler. It does not unsuspend tasks
* that were previously suspended by a call to vTaskSuspend().
* *
* @return If resuming the scheduler caused a context switch then pdTRUE is * @return If resuming the scheduler caused a context switch then pdTRUE is
* returned, otherwise pdFALSE is returned. * returned, otherwise pdFALSE is returned.
@ -1002,18 +1026,7 @@ void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION;
* \defgroup xTaskResumeAll xTaskResumeAll * \defgroup xTaskResumeAll xTaskResumeAll
* \ingroup SchedulerControl * \ingroup SchedulerControl
*/ */
signed portBASE_TYPE xTaskResumeAll( void ) PRIVILEGED_FUNCTION; BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION;
/**
* task. h
* <pre>signed portBASE_TYPE xTaskIsTaskSuspended( const xTaskHandle xTask );</pre>
*
* Utility task that simply returns pdTRUE if the task referenced by xTask is
* currently in the Suspended state, or pdFALSE if the task referenced by xTask
* is in any other state.
*
*/
signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask ) PRIVILEGED_FUNCTION;
/*----------------------------------------------------------- /*-----------------------------------------------------------
* TASK UTILITIES * TASK UTILITIES
@ -1021,34 +1034,34 @@ signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask ) PRIVILEGED_FUNCTI
/** /**
* task. h * task. h
* <PRE>portTickType xTaskGetTickCount( void );</PRE> * <PRE>TickType_t xTaskGetTickCount( void );</PRE>
* *
* @return The count of ticks since vTaskStartScheduler was called. * @return The count of ticks since vTaskStartScheduler was called.
* *
* \defgroup xTaskGetTickCount xTaskGetTickCount * \defgroup xTaskGetTickCount xTaskGetTickCount
* \ingroup TaskUtils * \ingroup TaskUtils
*/ */
portTickType xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; TickType_t xTaskGetTickCount( void ) PRIVILEGED_FUNCTION;
/** /**
* task. h * task. h
* <PRE>portTickType xTaskGetTickCountFromISR( void );</PRE> * <PRE>TickType_t xTaskGetTickCountFromISR( void );</PRE>
* *
* @return The count of ticks since vTaskStartScheduler was called. * @return The count of ticks since vTaskStartScheduler was called.
* *
* This is a version of xTaskGetTickCount() that is safe to be called from an * This is a version of xTaskGetTickCount() that is safe to be called from an
* ISR - provided that portTickType is the natural word size of the * ISR - provided that TickType_t is the natural word size of the
* microcontroller being used or interrupt nesting is either not supported or * microcontroller being used or interrupt nesting is either not supported or
* not being used. * not being used.
* *
* \defgroup xTaskGetTickCount xTaskGetTickCount * \defgroup xTaskGetTickCountFromISR xTaskGetTickCountFromISR
* \ingroup TaskUtils * \ingroup TaskUtils
*/ */
portTickType xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; TickType_t xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION;
/** /**
* task. h * task. h
* <PRE>unsigned short uxTaskGetNumberOfTasks( void );</PRE> * <PRE>uint16_t uxTaskGetNumberOfTasks( void );</PRE>
* *
* @return The number of tasks that the real time kernel is currently managing. * @return The number of tasks that the real time kernel is currently managing.
* This includes all ready, blocked and suspended tasks. A task that * This includes all ready, blocked and suspended tasks. A task that
@ -1058,38 +1071,25 @@ portTickType xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION;
* \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks * \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks
* \ingroup TaskUtils * \ingroup TaskUtils
*/ */
unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION;
/** /**
* task. h * task. h
* <PRE>signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery );</PRE> * <PRE>char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery );</PRE>
* *
* @return The text (human readable) name of the task referenced by the handle * @return The text (human readable) name of the task referenced by the handle
* xTaskToQueury. A task can query its own name by either passing in its own * xTaskToQuery. A task can query its own name by either passing in its own
* handle, or by setting xTaskToQuery to NULL. INCLUDE_pcTaskGetTaskName must be * handle, or by setting xTaskToQuery to NULL. INCLUDE_pcTaskGetTaskName must be
* set to 1 in FreeRTOSConfig.h for pcTaskGetTaskName() to be available. * set to 1 in FreeRTOSConfig.h for pcTaskGetTaskName() to be available.
* *
* \defgroup pcTaskGetTaskName pcTaskGetTaskName * \defgroup pcTaskGetTaskName pcTaskGetTaskName
* \ingroup TaskUtils * \ingroup TaskUtils
*/ */
signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery ); char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
/** /**
* task.h * task.h
* <PRE>unsigned portBASE_TYPE uxTaskGetRunTime( xTaskHandle xTask );</PRE> * <PRE>UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );</PRE>
*
* Returns the run time of selected task
*
* @param xTask Handle of the task associated with the stack to be checked.
* Set xTask to NULL to check the stack of the calling task.
*
* @return The run time of selected task
*/
unsigned portBASE_TYPE uxTaskGetRunTime( xTaskHandle xTask );
/**
* task.h
* <PRE>unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask );</PRE>
* *
* INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for
* this function to be available. * this function to be available.
@ -1102,13 +1102,14 @@ unsigned portBASE_TYPE uxTaskGetRunTime( xTaskHandle xTask );
* @param xTask Handle of the task associated with the stack to be checked. * @param xTask Handle of the task associated with the stack to be checked.
* Set xTask to NULL to check the stack of the calling task. * Set xTask to NULL to check the stack of the calling task.
* *
* @return The smallest amount of free stack space there has been (in bytes) * @return The smallest amount of free stack space there has been (in words, so
* since the task referenced by xTask was created. * actual spaces on the stack rather than bytes) since the task referenced by
* xTask was created.
*/ */
unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask ) PRIVILEGED_FUNCTION; UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
/* When using trace macros it is sometimes necessary to include tasks.h before /* When using trace macros it is sometimes necessary to include task.h before
FreeRTOS.h. When this is done pdTASK_HOOK_CODE will not yet have been defined, FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been defined,
so the following two prototypes will cause a compilation error. This can be so the following two prototypes will cause a compilation error. This can be
fixed by simply guarding against the inclusion of these two prototypes unless fixed by simply guarding against the inclusion of these two prototypes unless
they are explicitly required by the configUSE_APPLICATION_TASK_TAG configuration they are explicitly required by the configUSE_APPLICATION_TASK_TAG configuration
@ -1117,35 +1118,36 @@ constant. */
#if configUSE_APPLICATION_TASK_TAG == 1 #if configUSE_APPLICATION_TASK_TAG == 1
/** /**
* task.h * task.h
* <pre>void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction );</pre> * <pre>void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction );</pre>
* *
* Sets pxHookFunction to be the task hook function used by the task xTask. * Sets pxHookFunction to be the task hook function used by the task xTask.
* Passing xTask as NULL has the effect of setting the calling tasks hook * Passing xTask as NULL has the effect of setting the calling tasks hook
* function. * function.
*/ */
void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction ) PRIVILEGED_FUNCTION; void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ) PRIVILEGED_FUNCTION;
/** /**
* task.h * task.h
* <pre>void xTaskGetApplicationTaskTag( xTaskHandle xTask );</pre> * <pre>void xTaskGetApplicationTaskTag( TaskHandle_t xTask );</pre>
* *
* Returns the pxHookFunction value assigned to the task xTask. * Returns the pxHookFunction value assigned to the task xTask.
*/ */
pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask ) PRIVILEGED_FUNCTION; TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
#endif /* configUSE_APPLICATION_TASK_TAG ==1 */ #endif /* configUSE_APPLICATION_TASK_TAG ==1 */
#endif /* ifdef configUSE_APPLICATION_TASK_TAG */ #endif /* ifdef configUSE_APPLICATION_TASK_TAG */
/** /**
* task.h * task.h
* <pre>portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction );</pre> * <pre>BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter );</pre>
* *
* Calls the hook function associated with xTask. Passing xTask as NULL has * Calls the hook function associated with xTask. Passing xTask as NULL has
* the effect of calling the Running tasks (the calling task) hook function. * the effect of calling the Running tasks (the calling task) hook function.
* *
* pvParameter is passed to the hook function for the task to interpret as it * pvParameter is passed to the hook function for the task to interpret as it
* wants. * wants. The return value is the value returned by the task hook function
* registered by the user.
*/ */
portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter ) PRIVILEGED_FUNCTION; BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) PRIVILEGED_FUNCTION;
/** /**
* xTaskGetIdleTaskHandle() is only available if * xTaskGetIdleTaskHandle() is only available if
@ -1154,29 +1156,29 @@ portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter
* Simply returns the handle of the idle task. It is not valid to call * Simply returns the handle of the idle task. It is not valid to call
* xTaskGetIdleTaskHandle() before the scheduler has been started. * xTaskGetIdleTaskHandle() before the scheduler has been started.
*/ */
xTaskHandle xTaskGetIdleTaskHandle( void ); TaskHandle_t xTaskGetIdleTaskHandle( void );
/** /**
* configUSE_TRACE_FACILITY must bet defined as 1 in FreeRTOSConfig.h for * configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for
* uxTaskGetSystemState() to be available. * uxTaskGetSystemState() to be available.
* *
* uxTaskGetSystemState() populates an xTaskStatusType structure for each task in * uxTaskGetSystemState() populates an TaskStatus_t structure for each task in
* the system. xTaskStatusType structures contain, among other things, members * the system. TaskStatus_t structures contain, among other things, members
* for the task handle, task name, task priority, task state, and total amount * for the task handle, task name, task priority, task state, and total amount
* of run time consumed by the task. See the xTaskStatusType structure * of run time consumed by the task. See the TaskStatus_t structure
* definition in this file for the full member list. * definition in this file for the full member list.
* *
* NOTE: This function is intended for debugging use only as its use results in * NOTE: This function is intended for debugging use only as its use results in
* the scheduler remaining suspended for an extended period. * the scheduler remaining suspended for an extended period.
* *
* @param pxTaskStatusArray A pointer to an array of xTaskStatusType structures. * @param pxTaskStatusArray A pointer to an array of TaskStatus_t structures.
* The array must contain at least one xTaskStatusType structure for each task * The array must contain at least one TaskStatus_t structure for each task
* that is under the control of the RTOS. The number of tasks under the control * that is under the control of the RTOS. The number of tasks under the control
* of the RTOS can be determined using the uxTaskGetNumberOfTasks() API function. * of the RTOS can be determined using the uxTaskGetNumberOfTasks() API function.
* *
* @param uxArraySize The size of the array pointed to by the pxTaskStatusArray * @param uxArraySize The size of the array pointed to by the pxTaskStatusArray
* parameter. The size is specified as the number of indexes in the array, or * parameter. The size is specified as the number of indexes in the array, or
* the number of xTaskStatusType structures contained in the array, not by the * the number of TaskStatus_t structures contained in the array, not by the
* number of bytes in the array. * number of bytes in the array.
* *
* @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in * @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in
@ -1185,7 +1187,7 @@ xTaskHandle xTaskGetIdleTaskHandle( void );
* http://www.freertos.org/rtos-run-time-stats.html) since the target booted. * http://www.freertos.org/rtos-run-time-stats.html) since the target booted.
* pulTotalRunTime can be set to NULL to omit the total run time information. * pulTotalRunTime can be set to NULL to omit the total run time information.
* *
* @return The number of xTaskStatusType structures that were populated by * @return The number of TaskStatus_t structures that were populated by
* uxTaskGetSystemState(). This should equal the number returned by the * uxTaskGetSystemState(). This should equal the number returned by the
* uxTaskGetNumberOfTasks() API function, but will be zero if the value passed * uxTaskGetNumberOfTasks() API function, but will be zero if the value passed
* in the uxArraySize parameter was too small. * in the uxArraySize parameter was too small.
@ -1195,22 +1197,22 @@ xTaskHandle xTaskGetIdleTaskHandle( void );
// This example demonstrates how a human readable table of run time stats // This example demonstrates how a human readable table of run time stats
// information is generated from raw data provided by uxTaskGetSystemState(). // information is generated from raw data provided by uxTaskGetSystemState().
// The human readable table is written to pcWriteBuffer // The human readable table is written to pcWriteBuffer
void vTaskGetRunTimeStats( signed char *pcWriteBuffer ) void vTaskGetRunTimeStats( char *pcWriteBuffer )
{ {
xTaskStatusType *pxTaskStatusArray; TaskStatus_t *pxTaskStatusArray;
volatile unsigned portBASE_TYPE uxArraySize, x; volatile UBaseType_t uxArraySize, x;
unsigned long ulTotalRunTime, ulStatsAsPercentage; uint32_t ulTotalRunTime, ulStatsAsPercentage;
// Make sure the write buffer does not contain a string. // Make sure the write buffer does not contain a string.
*pcWriteBuffer = 0x00; *pcWriteBuffer = 0x00;
// Take a snapshot of the number of tasks in case it changes while this // Take a snapshot of the number of tasks in case it changes while this
// function is executing. // function is executing.
uxArraySize = uxCurrentNumberOfTasks(); uxArraySize = uxTaskGetNumberOfTasks();
// Allocate a xTaskStatusType structure for each task. An array could be // Allocate a TaskStatus_t structure for each task. An array could be
// allocated statically at compile time. // allocated statically at compile time.
pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( xTaskStatusType ) ); pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) );
if( pxTaskStatusArray != NULL ) if( pxTaskStatusArray != NULL )
{ {
@ -1234,13 +1236,13 @@ xTaskHandle xTaskGetIdleTaskHandle( void );
if( ulStatsAsPercentage > 0UL ) if( ulStatsAsPercentage > 0UL )
{ {
sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
} }
else else
{ {
// If the percentage is zero here then the task has // If the percentage is zero here then the task has
// consumed less than 1% of the total run time. // consumed less than 1% of the total run time.
sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter ); sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );
} }
pcWriteBuffer += strlen( ( char * ) pcWriteBuffer ); pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
@ -1253,7 +1255,7 @@ xTaskHandle xTaskGetIdleTaskHandle( void );
} }
</pre> </pre>
*/ */
unsigned portBASE_TYPE uxTaskGetSystemState( xTaskStatusType *pxTaskStatusArray, unsigned portBASE_TYPE uxArraySize, unsigned long *pulTotalRunTime ); UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime );
/** /**
* task. h * task. h
@ -1293,14 +1295,14 @@ unsigned portBASE_TYPE uxTaskGetSystemState( xTaskStatusType *pxTaskStatusArray,
* call to vTaskList(). * call to vTaskList().
* *
* @param pcWriteBuffer A buffer into which the above mentioned details * @param pcWriteBuffer A buffer into which the above mentioned details
* will be written, in ascii form. This buffer is assumed to be large * will be written, in ASCII form. This buffer is assumed to be large
* enough to contain the generated report. Approximately 40 bytes per * enough to contain the generated report. Approximately 40 bytes per
* task should be sufficient. * task should be sufficient.
* *
* \defgroup vTaskList vTaskList * \defgroup vTaskList vTaskList
* \ingroup TaskUtils * \ingroup TaskUtils
*/ */
void vTaskList( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION; void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
/** /**
* task. h * task. h
@ -1309,7 +1311,7 @@ void vTaskList( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION;
* configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS
* must both be defined as 1 for this function to be available. The application * must both be defined as 1 for this function to be available. The application
* must also then provide definitions for * must also then provide definitions for
* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE()
* to configure a peripheral timer/counter and return the timers current count * to configure a peripheral timer/counter and return the timers current count
* value respectively. The counter should be at least 10 times the frequency of * value respectively. The counter should be at least 10 times the frequency of
* the tick count. * the tick count.
@ -1347,14 +1349,14 @@ void vTaskList( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION;
* vTaskGetRunTimeStats(). * vTaskGetRunTimeStats().
* *
* @param pcWriteBuffer A buffer into which the execution times will be * @param pcWriteBuffer A buffer into which the execution times will be
* written, in ascii form. This buffer is assumed to be large enough to * written, in ASCII form. This buffer is assumed to be large enough to
* contain the generated report. Approximately 40 bytes per task should * contain the generated report. Approximately 40 bytes per task should
* be sufficient. * be sufficient.
* *
* \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats * \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats
* \ingroup TaskUtils * \ingroup TaskUtils
*/ */
void vTaskGetRunTimeStats( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION; void vTaskGetRunTimeStats( char *pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
/*----------------------------------------------------------- /*-----------------------------------------------------------
* SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES
@ -1375,7 +1377,7 @@ void vTaskGetRunTimeStats( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION;
* + Time slicing is in use and there is a task of equal priority to the * + Time slicing is in use and there is a task of equal priority to the
* currently running task. * currently running task.
*/ */
portBASE_TYPE xTaskIncrementTick( void ) PRIVILEGED_FUNCTION; BaseType_t xTaskIncrementTick( void ) PRIVILEGED_FUNCTION;
/* /*
* THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN
@ -1390,15 +1392,26 @@ portBASE_TYPE xTaskIncrementTick( void ) PRIVILEGED_FUNCTION;
* there be no higher priority tasks waiting on the same event) or * there be no higher priority tasks waiting on the same event) or
* the delay period expires. * the delay period expires.
* *
* The 'unordered' version replaces the event list item value with the
* xItemValue value, and inserts the list item at the end of the list.
*
* The 'ordered' version uses the existing event list item value (which is the
* owning tasks priority) to insert the list item into the event list is task
* priority order.
*
* @param pxEventList The list containing tasks that are blocked waiting * @param pxEventList The list containing tasks that are blocked waiting
* for the event to occur. * for the event to occur.
* *
* @param xItemValue The item value to use for the event list item when the
* event list is not ordered by task priority.
*
* @param xTicksToWait The maximum amount of time that the task should wait * @param xTicksToWait The maximum amount of time that the task should wait
* for the event to occur. This is specified in kernel ticks,the constant * for the event to occur. This is specified in kernel ticks,the constant
* portTICK_RATE_MS can be used to convert kernel ticks into a real time * portTICK_PERIOD_MS can be used to convert kernel ticks into a real time
* period. * period.
*/ */
void vTaskPlaceOnEventList( xList * const pxEventList, portTickType xTicksToWait ) PRIVILEGED_FUNCTION; void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/* /*
* THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN
@ -1410,10 +1423,8 @@ void vTaskPlaceOnEventList( xList * const pxEventList, portTickType xTicksToWait
* The difference being that this function does not permit tasks to block * The difference being that this function does not permit tasks to block
* indefinitely, whereas vTaskPlaceOnEventList() does. * indefinitely, whereas vTaskPlaceOnEventList() does.
* *
* @return pdTRUE if the task being removed has a higher priority than the task
* making the call, otherwise pdFALSE.
*/ */
void vTaskPlaceOnEventListRestricted( xList * const pxEventList, portTickType xTicksToWait ) PRIVILEGED_FUNCTION; void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/* /*
* THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN
@ -1424,13 +1435,23 @@ void vTaskPlaceOnEventListRestricted( xList * const pxEventList, portTickType xT
* Removes a task from both the specified event list and the list of blocked * Removes a task from both the specified event list and the list of blocked
* tasks, and places it on a ready queue. * tasks, and places it on a ready queue.
* *
* xTaskRemoveFromEventList () will be called if either an event occurs to * xTaskRemoveFromEventList()/xTaskRemoveFromUnorderedEventList() will be called
* unblock a task, or the block timeout period expires. * if either an event occurs to unblock a task, or the block timeout period
* expires.
*
* xTaskRemoveFromEventList() is used when the event list is in task priority
* order. It removes the list item from the head of the event list as that will
* have the highest priority owning task of all the tasks on the event list.
* xTaskRemoveFromUnorderedEventList() is used when the event list is not
* ordered and the event list items hold something other than the owning tasks
* priority. In this case the event list item value is updated to the value
* passed in the xItemValue parameter.
* *
* @return pdTRUE if the task being removed has a higher priority than the task * @return pdTRUE if the task being removed has a higher priority than the task
* making the call, otherwise pdFALSE. * making the call, otherwise pdFALSE.
*/ */
signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList ) PRIVILEGED_FUNCTION; BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) PRIVILEGED_FUNCTION;
BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue ) PRIVILEGED_FUNCTION;
/* /*
* THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY
@ -1442,21 +1463,27 @@ signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList )
*/ */
void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION; void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION;
/*
* THESE FUNCTIONS MUST NOT BE USED FROM APPLICATION CODE. THEY ARE USED BY
* THE EVENT BITS MODULE.
*/
TickType_t uxTaskResetEventItemValue( void ) PRIVILEGED_FUNCTION;
/* /*
* Return the handle of the calling task. * Return the handle of the calling task.
*/ */
xTaskHandle xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION;
/* /*
* Capture the current time status for future reference. * Capture the current time status for future reference.
*/ */
void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut ) PRIVILEGED_FUNCTION; void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION;
/* /*
* Compare the time status now with that previously captured to see if the * Compare the time status now with that previously captured to see if the
* timeout has expired. * timeout has expired.
*/ */
portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait ) PRIVILEGED_FUNCTION; BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) PRIVILEGED_FUNCTION;
/* /*
* Shortcut used by the queue implementation to prevent unnecessary call to * Shortcut used by the queue implementation to prevent unnecessary call to
@ -1468,47 +1495,49 @@ void vTaskMissedYield( void ) PRIVILEGED_FUNCTION;
* Returns the scheduler state as taskSCHEDULER_RUNNING, * Returns the scheduler state as taskSCHEDULER_RUNNING,
* taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED. * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED.
*/ */
portBASE_TYPE xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION; BaseType_t xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION;
/* /*
* Raises the priority of the mutex holder to that of the calling task should * Raises the priority of the mutex holder to that of the calling task should
* the mutex holder have a priority less than the calling task. * the mutex holder have a priority less than the calling task.
*/ */
void vTaskPriorityInherit( xTaskHandle const pxMutexHolder ) PRIVILEGED_FUNCTION; void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION;
/* /*
* Set the priority of a task back to its proper priority in the case that it * Set the priority of a task back to its proper priority in the case that it
* inherited a higher priority while it was holding a semaphore. * inherited a higher priority while it was holding a semaphore.
*/ */
void vTaskPriorityDisinherit( xTaskHandle const pxMutexHolder ) PRIVILEGED_FUNCTION; void vTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION;
/* /*
* Generic version of the task creation function which is in turn called by the * Generic version of the task creation function which is in turn called by the
* xTaskCreate() and xTaskCreateRestricted() macros. * xTaskCreate() and xTaskCreateRestricted() macros.
*/ */
signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) PRIVILEGED_FUNCTION; BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
/* /*
* Get the uxTCBNumber assigned to the task referenced by the xTask parameter. * Get the uxTCBNumber assigned to the task referenced by the xTask parameter.
*/ */
unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask ); UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
/* /*
* Set the uxTCBNumber of the task referenced by the xTask parameter to * Set the uxTaskNumber of the task referenced by the xTask parameter to
* ucHandle. * uxHandle.
*/ */
void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle ); void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle ) PRIVILEGED_FUNCTION;
/* /*
* Only available when configUSE_TICKLESS_IDLE is set to 1.
* If tickless mode is being used, or a low power mode is implemented, then * If tickless mode is being used, or a low power mode is implemented, then
* the tick interrupt will not execute during idle periods. When this is the * the tick interrupt will not execute during idle periods. When this is the
* case, the tick count value maintained by the scheduler needs to be kept up * case, the tick count value maintained by the scheduler needs to be kept up
* to date with the actual execution time by being skipped forward by the by * to date with the actual execution time by being skipped forward by a time
* a time equal to the idle period. * equal to the idle period.
*/ */
void vTaskStepTick( portTickType xTicksToJump ); void vTaskStepTick( const TickType_t xTicksToJump ) PRIVILEGED_FUNCTION;
/* /*
* Only avilable when configUSE_TICKLESS_IDLE is set to 1.
* Provided for use within portSUPPRESS_TICKS_AND_SLEEP() to allow the port * Provided for use within portSUPPRESS_TICKS_AND_SLEEP() to allow the port
* specific sleep function to determine if it is ok to proceed with the sleep, * specific sleep function to determine if it is ok to proceed with the sleep,
* and if it is ok to proceed, if it is ok to sleep indefinitely. * and if it is ok to proceed, if it is ok to sleep indefinitely.
@ -1521,8 +1550,9 @@ void vTaskStepTick( portTickType xTicksToJump );
* critical section between the timer being stopped and the sleep mode being * critical section between the timer being stopped and the sleep mode being
* entered to ensure it is ok to proceed into the sleep mode. * entered to ensure it is ok to proceed into the sleep mode.
*/ */
eSleepModeStatus eTaskConfirmSleepModeStatus( void ); eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION;
UBaseType_t uxTaskGetRunTime( TaskHandle_t xTask );
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -79,35 +80,56 @@ happens to also be including task.h. */
extern "C" { extern "C" {
#endif #endif
/* 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,
as defined below. */
#define tmrCOMMAND_START ( ( portBASE_TYPE ) 0 )
#define tmrCOMMAND_STOP ( ( portBASE_TYPE ) 1 )
#define tmrCOMMAND_CHANGE_PERIOD ( ( portBASE_TYPE ) 2 )
#define tmrCOMMAND_DELETE ( ( portBASE_TYPE ) 3 )
/*----------------------------------------------------------- /*-----------------------------------------------------------
* MACROS AND DEFINITIONS * MACROS AND DEFINITIONS
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/** /* 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,
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
or interrupt version of the queue send function should be used. */
#define tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR ( ( BaseType_t ) -2 )
#define tmrCOMMAND_EXECUTE_CALLBACK ( ( BaseType_t ) -1 )
#define tmrCOMMAND_START_DONT_TRACE ( ( BaseType_t ) 0 )
#define tmrCOMMAND_START ( ( BaseType_t ) 1 )
#define tmrCOMMAND_RESET ( ( BaseType_t ) 2 )
#define tmrCOMMAND_STOP ( ( BaseType_t ) 3 )
#define tmrCOMMAND_CHANGE_PERIOD ( ( BaseType_t ) 4 )
#define tmrCOMMAND_DELETE ( ( BaseType_t ) 5 )
#define tmrFIRST_FROM_ISR_COMMAND ( ( BaseType_t ) 6 )
#define tmrCOMMAND_START_FROM_ISR ( ( BaseType_t ) 6 )
#define tmrCOMMAND_RESET_FROM_ISR ( ( BaseType_t ) 7 )
#define tmrCOMMAND_STOP_FROM_ISR ( ( BaseType_t ) 8 )
#define tmrCOMMAND_CHANGE_PERIOD_FROM_ISR ( ( BaseType_t ) 9 )
/**
* Type by which software timers are referenced. For example, a call to * Type by which software timers are referenced. For example, a call to
* xTimerCreate() returns an xTimerHandle variable that can then be used to * xTimerCreate() returns an TimerHandle_t variable that can then be used to
* 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.).
*/ */
typedef void * xTimerHandle; typedef void * TimerHandle_t;
/* Define the prototype to which timer callback functions must conform. */ /*
typedef void (*tmrTIMER_CALLBACK)( xTimerHandle xTimer ); * Defines the prototype to which timer callback functions must conform.
*/
typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer );
/*
* Defines the prototype to which functions used with the
* xTimerPendFunctionCallFromISR() function must conform.
*/
typedef void (*PendedFunction_t)( void *, uint32_t );
/** /**
* xTimerHandle xTimerCreate( const signed char *pcTimerName, * TimerHandle_t xTimerCreate( const char * const pcTimerName,
* portTickType xTimerPeriodInTicks, * TickType_t xTimerPeriodInTicks,
* unsigned portBASE_TYPE uxAutoReload, * UBaseType_t uxAutoReload,
* void * pvTimerID, * void * pvTimerID,
* tmrTIMER_CALLBACK pxCallbackFunction ); * TimerCallbackFunction_t pxCallbackFunction );
* *
* Creates a new software timer instance. This allocates the storage required * Creates a new software timer instance. This allocates the storage required
* by the new timer, initialises the new timers internal state, and returns a * by the new timer, initialises the new timers internal state, and returns a
@ -115,23 +137,24 @@ typedef void (*tmrTIMER_CALLBACK)( xTimerHandle xTimer );
* *
* Timers are created in the dormant state. The xTimerStart(), xTimerReset(), * Timers are created in the dormant state. The xTimerStart(), xTimerReset(),
* xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and
* xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the * xTimerChangePeriodFromISR() API functions can all be used to transition a
* active state. * timer into the active state.
* *
* @param pcTimerName A text name that is assigned to the timer. This is done * @param pcTimerName A text name that is assigned to the timer. This is done
* purely to assist debugging. The kernel itself only ever references a timer by * purely to assist debugging. The kernel itself only ever references a timer
* its handle, and never by its name. * by its handle, and never by its name.
* *
* @param xTimerPeriodInTicks The timer period. The time is defined in tick periods so * @param xTimerPeriodInTicks The timer period. The time is defined in tick
* the constant portTICK_RATE_MS can be used to convert a time that has been * periods so the constant portTICK_PERIOD_MS can be used to convert a time that
* specified in milliseconds. For example, if the timer must expire after 100 * has been specified in milliseconds. For example, if the timer must expire
* ticks, then xTimerPeriodInTicks should be set to 100. Alternatively, if the timer * after 100 ticks, then xTimerPeriodInTicks should be set to 100.
* must expire after 500ms, then xPeriod can be set to ( 500 / portTICK_RATE_MS ) * Alternatively, if the timer must expire after 500ms, then xPeriod can be set
* provided configTICK_RATE_HZ is less than or equal to 1000. * to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than or
* equal to 1000.
* *
* @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will
* expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter. If * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter.
* uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and * If 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.
* *
* @param pvTimerID An identifier that is assigned to the timer being created. * @param pvTimerID An identifier that is assigned to the timer being created.
@ -140,38 +163,38 @@ typedef void (*tmrTIMER_CALLBACK)( xTimerHandle xTimer );
* timer. * timer.
* *
* @param pxCallbackFunction The function to call when the timer expires. * @param pxCallbackFunction The function to call when the timer expires.
* Callback functions must have the prototype defined by tmrTIMER_CALLBACK, * Callback functions must have the prototype defined by TimerCallbackFunction_t,
* which is "void vCallbackFunction( xTimerHandle xTimer );". * which is "void vCallbackFunction( TimerHandle_t xTimer );".
* *
* @return If the timer is successfully create then a handle to the newly * @return If the timer is successfully created then a handle to the newly
* created timer is returned. If the timer cannot be created (because either * created timer is returned. If the timer cannot be created (because either
* there is insufficient FreeRTOS heap remaining to allocate the timer * there is insufficient FreeRTOS heap remaining to allocate the timer
* structures, or the timer period was set to 0) then 0 is returned. * structures, or the timer period was set to 0) then NULL is returned.
* *
* Example usage: * Example usage:
* @verbatim * @verbatim
* #define NUM_TIMERS 5 * #define NUM_TIMERS 5
* *
* // An array to hold handles to the created timers. * // An array to hold handles to the created timers.
* xTimerHandle xTimers[ NUM_TIMERS ]; * TimerHandle_t xTimers[ NUM_TIMERS ];
* *
* // An array to hold a count of the number of times each timer expires. * // An array to hold a count of the number of times each timer expires.
* long lExpireCounters[ NUM_TIMERS ] = { 0 }; * int32_t lExpireCounters[ NUM_TIMERS ] = { 0 };
* *
* // Define a callback function that will be used by multiple timer instances. * // Define a callback function that will be used by multiple timer instances.
* // The callback function does nothing but count the number of times the * // The callback function does nothing but count the number of times the
* // associated timer expires, and stop the timer once the timer has expired * // associated timer expires, and stop the timer once the timer has expired
* // 10 times. * // 10 times.
* void vTimerCallback( xTimerHandle pxTimer ) * void vTimerCallback( TimerHandle_t pxTimer )
* { * {
* long lArrayIndex; * int32_t lArrayIndex;
* const long xMaxExpiryCountBeforeStopping = 10; * const int32_t xMaxExpiryCountBeforeStopping = 10;
* *
* // Optionally do something if the pxTimer parameter is NULL. * // Optionally do something if the pxTimer parameter is NULL.
* configASSERT( pxTimer ); * configASSERT( pxTimer );
* *
* // Which timer expired? * // Which timer expired?
* lArrayIndex = ( long ) pvTimerGetTimerID( pxTimer ); * lArrayIndex = ( int32_t ) pvTimerGetTimerID( pxTimer );
* *
* // Increment the number of times that pxTimer has expired. * // Increment the number of times that pxTimer has expired.
* lExpireCounters[ lArrayIndex ] += 1; * lExpireCounters[ lArrayIndex ] += 1;
@ -187,18 +210,18 @@ typedef void (*tmrTIMER_CALLBACK)( xTimerHandle xTimer );
* *
* void main( void ) * void main( void )
* { * {
* long x; * int32_t x;
* *
* // Create then start some timers. Starting the timers before the scheduler * // Create then start some timers. Starting the timers before the scheduler
* // has been started means the timers will start running immediately that * // has been started means the timers will start running immediately that
* // the scheduler starts. * // the scheduler starts.
* for( x = 0; x < NUM_TIMERS; x++ ) * for( x = 0; x < NUM_TIMERS; x++ )
* { * {
* xTimers[ x ] = xTimerCreate( "Timer", // Just a text name, not used by the kernel. * xTimers[ x ] = xTimerCreate( "Timer", // Just a text name, not used by the kernel.
* ( 100 * x ), // The timer period in ticks. * ( 100 * x ), // The timer period in ticks.
* pdTRUE, // The timers will auto-reload themselves when they expire. * pdTRUE, // The timers will auto-reload themselves when they expire.
* ( void * ) x, // Assign each timer a unique id equal to its array index. * ( void * ) x, // Assign each timer a unique id equal to its array index.
* vTimerCallback // Each timer calls the same callback when it expires. * vTimerCallback // Each timer calls the same callback when it expires.
* ); * );
* *
* if( xTimers[ x ] == NULL ) * if( xTimers[ x ] == NULL )
@ -230,10 +253,10 @@ typedef void (*tmrTIMER_CALLBACK)( xTimerHandle xTimer );
* } * }
* @endverbatim * @endverbatim
*/ */
xTimerHandle xTimerCreate( const signed char * const pcTimerName, portTickType xTimerPeriodInTicks, unsigned portBASE_TYPE uxAutoReload, void * pvTimerID, tmrTIMER_CALLBACK pxCallbackFunction ) PRIVILEGED_FUNCTION; TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
/** /**
* void *pvTimerGetTimerID( xTimerHandle xTimer ); * void *pvTimerGetTimerID( TimerHandle_t xTimer );
* *
* Returns the ID assigned to the timer. * Returns the ID assigned to the timer.
* *
@ -252,16 +275,16 @@ xTimerHandle xTimerCreate( const signed char * const pcTimerName, portTickType x
* *
* See the xTimerCreate() API function example usage scenario. * See the xTimerCreate() API function example usage scenario.
*/ */
void *pvTimerGetTimerID( xTimerHandle xTimer ) PRIVILEGED_FUNCTION; void *pvTimerGetTimerID( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
/** /**
* portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer ); * BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer );
* *
* Queries a timer to see if it is active or dormant. * Queries a timer to see if it is active or dormant.
* *
* A timer will be dormant if: * A timer will be dormant if:
* 1) It has been created but not started, or * 1) It has been created but not started, or
* 2) It is an expired on-shot timer that has not been restarted. * 2) It is an expired one-shot timer that has not been restarted.
* *
* Timers are created in the dormant state. The xTimerStart(), xTimerReset(), * Timers are created in the dormant state. The xTimerStart(), xTimerReset(),
* xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and
@ -276,7 +299,7 @@ void *pvTimerGetTimerID( xTimerHandle xTimer ) PRIVILEGED_FUNCTION;
* Example usage: * Example usage:
* @verbatim * @verbatim
* // This function assumes xTimer has already been created. * // This function assumes xTimer has already been created.
* void vAFunction( xTimerHandle xTimer ) * void vAFunction( TimerHandle_t xTimer )
* { * {
* if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )"
* { * {
@ -289,23 +312,25 @@ void *pvTimerGetTimerID( xTimerHandle xTimer ) PRIVILEGED_FUNCTION;
* } * }
* @endverbatim * @endverbatim
*/ */
portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer ) PRIVILEGED_FUNCTION; BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
/** /**
* xTimerGetTimerDaemonTaskHandle() is only available if * TaskHandle_t xTimerGetTimerDaemonTaskHandle( void );
*
* xTimerGetTimerDaemonTaskHandle() is only available if
* INCLUDE_xTimerGetTimerDaemonTaskHandle is set to 1 in FreeRTOSConfig.h. * INCLUDE_xTimerGetTimerDaemonTaskHandle is set to 1 in FreeRTOSConfig.h.
* *
* 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.
*/ */
xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); TaskHandle_t xTimerGetTimerDaemonTaskHandle( void );
/** /**
* portBASE_TYPE xTimerStart( xTimerHandle xTimer, portTickType xBlockTime ); * BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait );
* *
* Timer functionality is provided by a timer service/daemon task. Many of the * Timer functionality is provided by a timer service/daemon task. Many of the
* public FreeRTOS timer API functions send commands to the timer service task * public FreeRTOS timer API functions send commands to the timer service task
* though a queue called the timer command queue. The timer command queue is * through a queue called the timer command queue. The timer command queue is
* private to the kernel itself and is not directly accessible to application * private to the kernel itself and is not directly accessible to application
* code. The length of the timer command queue is set by the * code. The length of the timer command queue is set by the
* configTIMER_QUEUE_LENGTH configuration constant. * configTIMER_QUEUE_LENGTH configuration constant.
@ -330,14 +355,14 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* *
* @param xTimer The handle of the timer being started/restarted. * @param xTimer The handle of the timer being started/restarted.
* *
* @param xBlockTime Specifies the time, in ticks, that the calling task should * @param xTicksToWait Specifies the time, in ticks, that the calling task should
* be held in the Blocked state to wait for the start command to be successfully * be held in the Blocked state to wait for the start command to be successfully
* sent to the timer command queue, should the queue already be full when * sent to the timer command queue, should the queue already be full when
* xTimerStart() was called. xBlockTime is ignored if xTimerStart() is called * xTimerStart() was called. xTicksToWait is ignored if xTimerStart() is called
* before the scheduler is started. * before the scheduler is started.
* *
* @return pdFAIL will be returned if the start command could not be sent to * @return pdFAIL will be returned if the start command could not be sent to
* the timer command queue even after xBlockTime ticks had passed. pdPASS will * the timer command queue even after xTicksToWait ticks had passed. pdPASS will
* be returned if the command was successfully sent to the timer command queue. * be returned if the command was successfully sent to the timer command queue.
* When the command is actually processed will depend on the priority of the * When the command is actually processed will depend on the priority of the
* timer service/daemon task relative to other tasks in the system, although the * timer service/daemon task relative to other tasks in the system, although the
@ -350,14 +375,14 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* See the xTimerCreate() API function example usage scenario. * See the xTimerCreate() API function example usage scenario.
* *
*/ */
#define xTimerStart( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xBlockTime ) ) #define xTimerStart( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) )
/** /**
* portBASE_TYPE xTimerStop( xTimerHandle xTimer, portTickType xBlockTime ); * BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait );
* *
* Timer functionality is provided by a timer service/daemon task. Many of the * Timer functionality is provided by a timer service/daemon task. Many of the
* public FreeRTOS timer API functions send commands to the timer service task * public FreeRTOS timer API functions send commands to the timer service task
* though a queue called the timer command queue. The timer command queue is * through a queue called the timer command queue. The timer command queue is
* private to the kernel itself and is not directly accessible to application * private to the kernel itself and is not directly accessible to application
* code. The length of the timer command queue is set by the * code. The length of the timer command queue is set by the
* configTIMER_QUEUE_LENGTH configuration constant. * configTIMER_QUEUE_LENGTH configuration constant.
@ -373,14 +398,14 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* *
* @param xTimer The handle of the timer being stopped. * @param xTimer The handle of the timer being stopped.
* *
* @param xBlockTime Specifies the time, in ticks, that the calling task should * @param xTicksToWait Specifies the time, in ticks, that the calling task should
* be held in the Blocked state to wait for the stop command to be successfully * be held in the Blocked state to wait for the stop command to be successfully
* sent to the timer command queue, should the queue already be full when * sent to the timer command queue, should the queue already be full when
* xTimerStop() was called. xBlockTime is ignored if xTimerStop() is called * xTimerStop() was called. xTicksToWait is ignored if xTimerStop() is called
* before the scheduler is started. * before the scheduler is started.
* *
* @return pdFAIL will be returned if the stop command could not be sent to * @return pdFAIL will be returned if the stop command could not be sent to
* the timer command queue even after xBlockTime ticks had passed. pdPASS will * the timer command queue even after xTicksToWait ticks had passed. pdPASS will
* be returned if the command was successfully sent to the timer command queue. * be returned if the command was successfully sent to the timer command queue.
* When the command is actually processed will depend on the priority of the * When the command is actually processed will depend on the priority of the
* timer service/daemon task relative to other tasks in the system. The timer * timer service/daemon task relative to other tasks in the system. The timer
@ -392,16 +417,16 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* See the xTimerCreate() API function example usage scenario. * See the xTimerCreate() API function example usage scenario.
* *
*/ */
#define xTimerStop( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xBlockTime ) ) #define xTimerStop( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) )
/** /**
* portBASE_TYPE xTimerChangePeriod( xTimerHandle xTimer, * BaseType_t xTimerChangePeriod( TimerHandle_t xTimer,
* portTickType xNewPeriod, * TickType_t xNewPeriod,
* portTickType xBlockTime ); * TickType_t xTicksToWait );
* *
* Timer functionality is provided by a timer service/daemon task. Many of the * Timer functionality is provided by a timer service/daemon task. Many of the
* public FreeRTOS timer API functions send commands to the timer service task * public FreeRTOS timer API functions send commands to the timer service task
* though a queue called the timer command queue. The timer command queue is * through a queue called the timer command queue. The timer command queue is
* private to the kernel itself and is not directly accessible to application * private to the kernel itself and is not directly accessible to application
* code. The length of the timer command queue is set by the * code. The length of the timer command queue is set by the
* configTIMER_QUEUE_LENGTH configuration constant. * configTIMER_QUEUE_LENGTH configuration constant.
@ -418,21 +443,21 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* @param xTimer The handle of the timer that is having its period changed. * @param xTimer The handle of the timer that is having its period changed.
* *
* @param xNewPeriod The new period for xTimer. Timer periods are specified in * @param xNewPeriod The new period for xTimer. Timer periods are specified in
* tick periods, so the constant portTICK_RATE_MS can be used to convert a time * tick periods, so the constant portTICK_PERIOD_MS can be used to convert a time
* that has been specified in milliseconds. For example, if the timer must * that has been specified in milliseconds. For example, if the timer must
* expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively, * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively,
* if the timer must expire after 500ms, then xNewPeriod can be set to * if the timer must expire after 500ms, then xNewPeriod can be set to
* ( 500 / portTICK_RATE_MS ) provided configTICK_RATE_HZ is less than * ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than
* or equal to 1000. * or equal to 1000.
* *
* @param xBlockTime Specifies the time, in ticks, that the calling task should * @param xTicksToWait Specifies the time, in ticks, that the calling task should
* be held in the Blocked state to wait for the change period command to be * be held in the Blocked state to wait for the change period command to be
* successfully sent to the timer command queue, should the queue already be * successfully sent to the timer command queue, should the queue already be
* full when xTimerChangePeriod() was called. xBlockTime is ignored if * full when xTimerChangePeriod() was called. xTicksToWait is ignored if
* xTimerChangePeriod() is called before the scheduler is started. * xTimerChangePeriod() is called before the scheduler is started.
* *
* @return pdFAIL will be returned if the change period command could not be * @return pdFAIL will be returned if the change period command could not be
* sent to the timer command queue even after xBlockTime ticks had passed. * sent to the timer command queue even after xTicksToWait ticks had passed.
* pdPASS will be returned if the command was successfully sent to the timer * pdPASS will be returned if the command was successfully sent to the timer
* command queue. When the command is actually processed will depend on the * command queue. When the command is actually processed will depend on the
* priority of the timer service/daemon task relative to other tasks in the * priority of the timer service/daemon task relative to other tasks in the
@ -446,7 +471,7 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* // is deleted. If the timer referenced by xTimer is not active when it is * // is deleted. If the timer referenced by xTimer is not active when it is
* // called, then the period of the timer is set to 500ms and the timer is * // called, then the period of the timer is set to 500ms and the timer is
* // started. * // started.
* void vAFunction( xTimerHandle xTimer ) * void vAFunction( TimerHandle_t xTimer )
* { * {
* if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )"
* { * {
@ -459,7 +484,7 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* // cause the timer to start. Block for a maximum of 100 ticks if the * // cause the timer to start. Block for a maximum of 100 ticks if the
* // change period command cannot immediately be sent to the timer * // change period command cannot immediately be sent to the timer
* // command queue. * // command queue.
* if( xTimerChangePeriod( xTimer, 500 / portTICK_RATE_MS, 100 ) == pdPASS ) * if( xTimerChangePeriod( xTimer, 500 / portTICK_PERIOD_MS, 100 ) == pdPASS )
* { * {
* // The command was successfully sent. * // The command was successfully sent.
* } * }
@ -472,14 +497,14 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* } * }
* @endverbatim * @endverbatim
*/ */
#define xTimerChangePeriod( xTimer, xNewPeriod, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xBlockTime ) ) #define xTimerChangePeriod( xTimer, xNewPeriod, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xTicksToWait ) )
/** /**
* portBASE_TYPE xTimerDelete( xTimerHandle xTimer, portTickType xBlockTime ); * BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait );
* *
* Timer functionality is provided by a timer service/daemon task. Many of the * Timer functionality is provided by a timer service/daemon task. Many of the
* public FreeRTOS timer API functions send commands to the timer service task * public FreeRTOS timer API functions send commands to the timer service task
* though a queue called the timer command queue. The timer command queue is * through a queue called the timer command queue. The timer command queue is
* private to the kernel itself and is not directly accessible to application * private to the kernel itself and is not directly accessible to application
* code. The length of the timer command queue is set by the * code. The length of the timer command queue is set by the
* configTIMER_QUEUE_LENGTH configuration constant. * configTIMER_QUEUE_LENGTH configuration constant.
@ -492,14 +517,14 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* *
* @param xTimer The handle of the timer being deleted. * @param xTimer The handle of the timer being deleted.
* *
* @param xBlockTime Specifies the time, in ticks, that the calling task should * @param xTicksToWait Specifies the time, in ticks, that the calling task should
* be held in the Blocked state to wait for the delete command to be * be held in the Blocked state to wait for the delete command to be
* successfully sent to the timer command queue, should the queue already be * successfully sent to the timer command queue, should the queue already be
* full when xTimerDelete() was called. xBlockTime is ignored if xTimerDelete() * full when xTimerDelete() was called. xTicksToWait is ignored if xTimerDelete()
* is called before the scheduler is started. * is called before the scheduler is started.
* *
* @return pdFAIL will be returned if the delete command could not be sent to * @return pdFAIL will be returned if the delete command could not be sent to
* the timer command queue even after xBlockTime ticks had passed. pdPASS will * the timer command queue even after xTicksToWait ticks had passed. pdPASS will
* be returned if the command was successfully sent to the timer command queue. * be returned if the command was successfully sent to the timer command queue.
* When the command is actually processed will depend on the priority of the * When the command is actually processed will depend on the priority of the
* timer service/daemon task relative to other tasks in the system. The timer * timer service/daemon task relative to other tasks in the system. The timer
@ -510,14 +535,14 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* *
* See the xTimerChangePeriod() API function example usage scenario. * See the xTimerChangePeriod() API function example usage scenario.
*/ */
#define xTimerDelete( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xBlockTime ) ) #define xTimerDelete( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xTicksToWait ) )
/** /**
* portBASE_TYPE xTimerReset( xTimerHandle xTimer, portTickType xBlockTime ); * BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait );
* *
* Timer functionality is provided by a timer service/daemon task. Many of the * Timer functionality is provided by a timer service/daemon task. Many of the
* public FreeRTOS timer API functions send commands to the timer service task * public FreeRTOS timer API functions send commands to the timer service task
* though a queue called the timer command queue. The timer command queue is * through a queue called the timer command queue. The timer command queue is
* private to the kernel itself and is not directly accessible to application * private to the kernel itself and is not directly accessible to application
* code. The length of the timer command queue is set by the * code. The length of the timer command queue is set by the
* configTIMER_QUEUE_LENGTH configuration constant. * configTIMER_QUEUE_LENGTH configuration constant.
@ -544,14 +569,14 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* *
* @param xTimer The handle of the timer being reset/started/restarted. * @param xTimer The handle of the timer being reset/started/restarted.
* *
* @param xBlockTime Specifies the time, in ticks, that the calling task should * @param xTicksToWait Specifies the time, in ticks, that the calling task should
* be held in the Blocked state to wait for the reset command to be successfully * be held in the Blocked state to wait for the reset command to be successfully
* sent to the timer command queue, should the queue already be full when * sent to the timer command queue, should the queue already be full when
* xTimerReset() was called. xBlockTime is ignored if xTimerReset() is called * xTimerReset() was called. xTicksToWait is ignored if xTimerReset() is called
* before the scheduler is started. * before the scheduler is started.
* *
* @return pdFAIL will be returned if the reset command could not be sent to * @return pdFAIL will be returned if the reset command could not be sent to
* the timer command queue even after xBlockTime ticks had passed. pdPASS will * the timer command queue even after xTicksToWait ticks had passed. pdPASS will
* be returned if the command was successfully sent to the timer command queue. * be returned if the command was successfully sent to the timer command queue.
* When the command is actually processed will depend on the priority of the * When the command is actually processed will depend on the priority of the
* timer service/daemon task relative to other tasks in the system, although the * timer service/daemon task relative to other tasks in the system, although the
@ -565,11 +590,11 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* // without a key being pressed, then the LCD back-light is switched off. In * // without a key being pressed, then the LCD back-light is switched off. In
* // this case, the timer is a one-shot timer. * // this case, the timer is a one-shot timer.
* *
* xTimerHandle xBacklightTimer = NULL; * TimerHandle_t xBacklightTimer = NULL;
* *
* // The callback function assigned to the one-shot timer. In this case the * // The callback function assigned to the one-shot timer. In this case the
* // parameter is not used. * // parameter is not used.
* void vBacklightTimerCallback( xTimerHandle pxTimer ) * void vBacklightTimerCallback( TimerHandle_t pxTimer )
* { * {
* // The timer expired, therefore 5 seconds must have passed since a key * // The timer expired, therefore 5 seconds must have passed since a key
* // was pressed. Switch off the LCD back-light. * // was pressed. Switch off the LCD back-light.
@ -595,12 +620,12 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* *
* void main( void ) * void main( void )
* { * {
* long x; * int32_t x;
* *
* // Create then start the one-shot timer that is responsible for turning * // Create then start the one-shot timer that is responsible for turning
* // the back-light off if no keys are pressed within a 5 second period. * // the back-light off if no keys are pressed within a 5 second period.
* xBacklightTimer = xTimerCreate( "BacklightTimer", // Just a text name, not used by the kernel. * xBacklightTimer = xTimerCreate( "BacklightTimer", // Just a text name, not used by the kernel.
* ( 5000 / portTICK_RATE_MS), // The timer period in ticks. * ( 5000 / portTICK_PERIOD_MS), // The timer period in ticks.
* pdFALSE, // The timer is a one-shot timer. * pdFALSE, // The timer is a one-shot timer.
* 0, // The id is not used by the callback so can take any value. * 0, // The id is not used by the callback so can take any value.
* vBacklightTimerCallback // The callback function that switches the LCD back-light off. * vBacklightTimerCallback // The callback function that switches the LCD back-light off.
@ -634,11 +659,11 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* } * }
* @endverbatim * @endverbatim
*/ */
#define xTimerReset( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xBlockTime ) ) #define xTimerReset( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) )
/** /**
* portBASE_TYPE xTimerStartFromISR( xTimerHandle xTimer, * BaseType_t xTimerStartFromISR( TimerHandle_t xTimer,
* portBASE_TYPE *pxHigherPriorityTaskWoken ); * BaseType_t *pxHigherPriorityTaskWoken );
* *
* A version of xTimerStart() that can be called from an interrupt service * A version of xTimerStart() that can be called from an interrupt service
* routine. * routine.
@ -662,8 +687,9 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* successfully sent to the timer command queue. When the command is actually * successfully sent to the timer command queue. When the command is actually
* processed will depend on the priority of the timer service/daemon task * processed will depend on the priority of the timer service/daemon task
* relative to other tasks in the system, although the timers expiry time is * relative to other tasks in the system, although the timers expiry time is
* relative to when xTimerStartFromISR() is actually called. The timer service/daemon * relative to when xTimerStartFromISR() is actually called. The timer
* task priority is set by the configTIMER_TASK_PRIORITY configuration constant. * service/daemon task priority is set by the configTIMER_TASK_PRIORITY
* configuration constant.
* *
* Example usage: * Example usage:
* @verbatim * @verbatim
@ -676,7 +702,7 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* *
* // The callback function assigned to the one-shot timer. In this case the * // The callback function assigned to the one-shot timer. In this case the
* // parameter is not used. * // parameter is not used.
* void vBacklightTimerCallback( xTimerHandle pxTimer ) * void vBacklightTimerCallback( TimerHandle_t pxTimer )
* { * {
* // The timer expired, therefore 5 seconds must have passed since a key * // The timer expired, therefore 5 seconds must have passed since a key
* // was pressed. Switch off the LCD back-light. * // was pressed. Switch off the LCD back-light.
@ -686,7 +712,7 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* // The key press interrupt service routine. * // The key press interrupt service routine.
* void vKeyPressEventInterruptHandler( void ) * void vKeyPressEventInterruptHandler( void )
* { * {
* portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; * BaseType_t xHigherPriorityTaskWoken = pdFALSE;
* *
* // Ensure the LCD back-light is on, then restart the timer that is * // Ensure the LCD back-light is on, then restart the timer that is
* // responsible for turning the back-light off after 5 seconds of * // responsible for turning the back-light off after 5 seconds of
@ -714,16 +740,16 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* if( xHigherPriorityTaskWoken != pdFALSE ) * if( xHigherPriorityTaskWoken != pdFALSE )
* { * {
* // Call the interrupt safe yield function here (actual function * // Call the interrupt safe yield function here (actual function
* // depends on the FreeRTOS port being used. * // depends on the FreeRTOS port being used).
* } * }
* } * }
* @endverbatim * @endverbatim
*/ */
#define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) #define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U )
/** /**
* portBASE_TYPE xTimerStopFromISR( xTimerHandle xTimer, * BaseType_t xTimerStopFromISR( TimerHandle_t xTimer,
* portBASE_TYPE *pxHigherPriorityTaskWoken ); * BaseType_t *pxHigherPriorityTaskWoken );
* *
* A version of xTimerStop() that can be called from an interrupt service * A version of xTimerStop() that can be called from an interrupt service
* routine. * routine.
@ -757,7 +783,7 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* // The interrupt service routine that stops the timer. * // The interrupt service routine that stops the timer.
* void vAnExampleInterruptServiceRoutine( void ) * void vAnExampleInterruptServiceRoutine( void )
* { * {
* portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; * BaseType_t xHigherPriorityTaskWoken = pdFALSE;
* *
* // The interrupt has occurred - simply stop the timer. * // The interrupt has occurred - simply stop the timer.
* // xHigherPriorityTaskWoken was set to pdFALSE where it was defined * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined
@ -777,17 +803,17 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* if( xHigherPriorityTaskWoken != pdFALSE ) * if( xHigherPriorityTaskWoken != pdFALSE )
* { * {
* // Call the interrupt safe yield function here (actual function * // Call the interrupt safe yield function here (actual function
* // depends on the FreeRTOS port being used. * // depends on the FreeRTOS port being used).
* } * }
* } * }
* @endverbatim * @endverbatim
*/ */
#define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0, ( pxHigherPriorityTaskWoken ), 0U ) #define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP_FROM_ISR, 0, ( pxHigherPriorityTaskWoken ), 0U )
/** /**
* portBASE_TYPE xTimerChangePeriodFromISR( xTimerHandle xTimer, * BaseType_t xTimerChangePeriodFromISR( TimerHandle_t xTimer,
* portTickType xNewPeriod, * TickType_t xNewPeriod,
* portBASE_TYPE *pxHigherPriorityTaskWoken ); * BaseType_t *pxHigherPriorityTaskWoken );
* *
* A version of xTimerChangePeriod() that can be called from an interrupt * A version of xTimerChangePeriod() that can be called from an interrupt
* service routine. * service routine.
@ -795,11 +821,11 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* @param xTimer The handle of the timer that is having its period changed. * @param xTimer The handle of the timer that is having its period changed.
* *
* @param xNewPeriod The new period for xTimer. Timer periods are specified in * @param xNewPeriod The new period for xTimer. Timer periods are specified in
* tick periods, so the constant portTICK_RATE_MS can be used to convert a time * tick periods, so the constant portTICK_PERIOD_MS can be used to convert a time
* that has been specified in milliseconds. For example, if the timer must * that has been specified in milliseconds. For example, if the timer must
* expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively, * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively,
* if the timer must expire after 500ms, then xNewPeriod can be set to * if the timer must expire after 500ms, then xNewPeriod can be set to
* ( 500 / portTICK_RATE_MS ) provided configTICK_RATE_HZ is less than * ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than
* or equal to 1000. * or equal to 1000.
* *
* @param pxHigherPriorityTaskWoken The timer service/daemon task spends most * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most
@ -830,7 +856,7 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* // The interrupt service routine that changes the period of xTimer. * // The interrupt service routine that changes the period of xTimer.
* void vAnExampleInterruptServiceRoutine( void ) * void vAnExampleInterruptServiceRoutine( void )
* { * {
* portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; * BaseType_t xHigherPriorityTaskWoken = pdFALSE;
* *
* // The interrupt has occurred - change the period of xTimer to 500ms. * // The interrupt has occurred - change the period of xTimer to 500ms.
* // xHigherPriorityTaskWoken was set to pdFALSE where it was defined * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined
@ -850,16 +876,16 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* if( xHigherPriorityTaskWoken != pdFALSE ) * if( xHigherPriorityTaskWoken != pdFALSE )
* { * {
* // Call the interrupt safe yield function here (actual function * // Call the interrupt safe yield function here (actual function
* // depends on the FreeRTOS port being used. * // depends on the FreeRTOS port being used).
* } * }
* } * }
* @endverbatim * @endverbatim
*/ */
#define xTimerChangePeriodFromISR( xTimer, xNewPeriod, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), ( pxHigherPriorityTaskWoken ), 0U ) #define xTimerChangePeriodFromISR( xTimer, xNewPeriod, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD_FROM_ISR, ( xNewPeriod ), ( pxHigherPriorityTaskWoken ), 0U )
/** /**
* portBASE_TYPE xTimerResetFromISR( xTimerHandle xTimer, * BaseType_t xTimerResetFromISR( TimerHandle_t xTimer,
* portBASE_TYPE *pxHigherPriorityTaskWoken ); * BaseType_t *pxHigherPriorityTaskWoken );
* *
* A version of xTimerReset() that can be called from an interrupt service * A version of xTimerReset() that can be called from an interrupt service
* routine. * routine.
@ -898,7 +924,7 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* *
* // The callback function assigned to the one-shot timer. In this case the * // The callback function assigned to the one-shot timer. In this case the
* // parameter is not used. * // parameter is not used.
* void vBacklightTimerCallback( xTimerHandle pxTimer ) * void vBacklightTimerCallback( TimerHandle_t pxTimer )
* { * {
* // The timer expired, therefore 5 seconds must have passed since a key * // The timer expired, therefore 5 seconds must have passed since a key
* // was pressed. Switch off the LCD back-light. * // was pressed. Switch off the LCD back-light.
@ -908,7 +934,7 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* // The key press interrupt service routine. * // The key press interrupt service routine.
* void vKeyPressEventInterruptHandler( void ) * void vKeyPressEventInterruptHandler( void )
* { * {
* portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; * BaseType_t xHigherPriorityTaskWoken = pdFALSE;
* *
* // Ensure the LCD back-light is on, then reset the timer that is * // Ensure the LCD back-light is on, then reset the timer that is
* // responsible for turning the back-light off after 5 seconds of * // responsible for turning the back-light off after 5 seconds of
@ -936,19 +962,144 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
* if( xHigherPriorityTaskWoken != pdFALSE ) * if( xHigherPriorityTaskWoken != pdFALSE )
* { * {
* // Call the interrupt safe yield function here (actual function * // Call the interrupt safe yield function here (actual function
* // depends on the FreeRTOS port being used. * // depends on the FreeRTOS port being used).
* } * }
* } * }
* @endverbatim * @endverbatim
*/ */
#define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) #define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U )
/**
* BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend,
* void *pvParameter1,
* uint32_t ulParameter2,
* BaseType_t *pxHigherPriorityTaskWoken );
*
*
* Used from application interrupt service routines to defer the execution of a
* function to the RTOS daemon task (the timer service task, hence this function
* is implemented in timers.c and is prefixed with 'Timer').
*
* Ideally an interrupt service routine (ISR) is kept as short as possible, but
* sometimes an ISR either has a lot of processing to do, or needs to perform
* processing that is not deterministic. In these cases
* xTimerPendFunctionCallFromISR() can be used to defer processing of a function
* to the RTOS daemon task.
*
* A mechanism is provided that allows the interrupt to return directly to the
* task that will subsequently execute the pended callback function. This
* allows the callback function to execute contiguously in time with the
* interrupt - just as if the callback had executed in the interrupt itself.
*
* @param xFunctionToPend The function to execute from the timer service/
* daemon task. The function must conform to the PendedFunction_t
* prototype.
*
* @param pvParameter1 The value of the callback function's first parameter.
* The parameter has a void * type to allow it to be used to pass any type.
* For example, unsigned longs can be cast to a void *, or the void * can be
* used to point to a structure.
*
* @param ulParameter2 The value of the callback function's second parameter.
*
* @param pxHigherPriorityTaskWoken As mentioned above, calling this function
* will result in a message being sent to the timer daemon task. If the
* priority of the timer daemon task (which is set using
* configTIMER_TASK_PRIORITY in FreeRTOSConfig.h) is higher than the priority of
* the currently running task (the task the interrupt interrupted) then
* *pxHigherPriorityTaskWoken will be set to pdTRUE within
* xTimerPendFunctionCallFromISR(), indicating that a context switch should be
* requested before the interrupt exits. For that reason
* *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the
* example code below.
*
* @return pdPASS is returned if the message was successfully sent to the
* timer daemon task, otherwise pdFALSE is returned.
*
* Example usage:
* @verbatim
*
* // The callback function that will execute in the context of the daemon task.
* // Note callback functions must all use this same prototype.
* void vProcessInterface( void *pvParameter1, uint32_t ulParameter2 )
* {
* BaseType_t xInterfaceToService;
*
* // The interface that requires servicing is passed in the second
* // parameter. The first parameter is not used in this case.
* xInterfaceToService = ( BaseType_t ) ulParameter2;
*
* // ...Perform the processing here...
* }
*
* // An ISR that receives data packets from multiple interfaces
* void vAnISR( void )
* {
* BaseType_t xInterfaceToService, xHigherPriorityTaskWoken;
*
* // Query the hardware to determine which interface needs processing.
* xInterfaceToService = prvCheckInterfaces();
*
* // The actual processing is to be deferred to a task. Request the
* // vProcessInterface() callback function is executed, passing in the
* // number of the interface that needs processing. The interface to
* // service is passed in the second parameter. The first parameter is
* // not used in this case.
* xHigherPriorityTaskWoken = pdFALSE;
* xTimerPendFunctionCallFromISR( vProcessInterface, NULL, ( uint32_t ) xInterfaceToService, &xHigherPriorityTaskWoken );
*
* // If xHigherPriorityTaskWoken is now set to pdTRUE then a context
* // switch should be requested. The macro used is port specific and will
* // be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to
* // the documentation page for the port being used.
* portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
*
* }
* @endverbatim
*/
BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken );
/**
* BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend,
* void *pvParameter1,
* uint32_t ulParameter2,
* TickType_t xTicksToWait );
*
*
* Used to defer the execution of a function to the RTOS daemon task (the timer
* service task, hence this function is implemented in timers.c and is prefixed
* with 'Timer').
*
* @param xFunctionToPend The function to execute from the timer service/
* daemon task. The function must conform to the PendedFunction_t
* prototype.
*
* @param pvParameter1 The value of the callback function's first parameter.
* The parameter has a void * type to allow it to be used to pass any type.
* For example, unsigned longs can be cast to a void *, or the void * can be
* used to point to a structure.
*
* @param ulParameter2 The value of the callback function's second parameter.
*
* @param xTicksToWait Calling this function will result in a message being
* sent to the timer daemon task on a queue. xTicksToWait is the amount of
* time the calling task should remain in the Blocked state (so not using any
* processing time) for space to become available on the timer queue if the
* queue is found to be full.
*
* @return pdPASS is returned if the message was successfully sent to the
* timer daemon task, otherwise pdFALSE is returned.
*
*/
BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait );
/* /*
* 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.
*/ */
portBASE_TYPE xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION; BaseType_t xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION;
portBASE_TYPE xTimerGenericCommand( xTimerHandle xTimer, portBASE_TYPE xCommandID, portTickType xOptionalValue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portTickType xBlockTime ) 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;
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -71,12 +72,12 @@
* PUBLIC LIST API documented in list.h * PUBLIC LIST API documented in list.h
*----------------------------------------------------------*/ *----------------------------------------------------------*/
void vListInitialise( xList * 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 = ( xListItem * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 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. */
@ -84,29 +85,27 @@ void vListInitialise( xList * const pxList )
/* 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 = ( xListItem * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
pxList->xListEnd.pxPrevious = ( xListItem * ) &( pxList->xListEnd );/*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
pxList->uxNumberOfItems = ( unsigned portBASE_TYPE ) 0U; pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vListInitialiseItem( xListItem * const pxItem ) void vListInitialiseItem( ListItem_t * const pxItem )
{ {
/* Make sure the list item is not recorded as being on a list. */ /* Make sure the list item is not recorded as being on a list. */
pxItem->pvContainer = NULL; pxItem->pvContainer = NULL;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vListInsertEnd( xList * const pxList, xListItem * const pxNewListItem ) void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{ {
xListItem * pxIndex; ListItem_t * const pxIndex = pxList->pxIndex;
/* 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
pvListGetOwnerOfNextEntry. */ listGET_OWNER_OF_NEXT_ENTRY(). */
pxIndex = pxList->pxIndex;
pxNewListItem->pxNext = pxIndex; pxNewListItem->pxNext = pxIndex;
pxNewListItem->pxPrevious = pxIndex->pxPrevious; pxNewListItem->pxPrevious = pxIndex->pxPrevious;
pxIndex->pxPrevious->pxNext = pxNewListItem; pxIndex->pxPrevious->pxNext = pxNewListItem;
@ -119,17 +118,16 @@ xListItem * pxIndex;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vListInsert( xList * const pxList, xListItem * const pxNewListItem ) void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{ {
xListItem *pxIterator; ListItem_t *pxIterator;
portTickType xValueOfInsertion; const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
/* Insert the new list item into the list, sorted in ulListItem order. */ /* Insert the new list item into the list, sorted in xItemValue order.
xValueOfInsertion = pxNewListItem->xItemValue;
/* If the list already contains a list item with the same item value then If the list already contains a list item with the same item value then
the new list item should be placed after it. This ensures that TCB's which the new list item should be placed after it. This ensures that TCB's which
are stored in ready lists (all of which have the same ulListItem value) are stored in ready lists (all of which have the same xItemValue value)
get an equal share of the CPU. However, if the xItemValue is the same as get an equal share of the CPU. However, if the xItemValue is the same as
the back marker the iteration loop below will not end. This means we need the back marker the iteration loop below will not end. This means we need
to guard against this by checking the value first and modifying the to guard against this by checking the value first and modifying the
@ -154,10 +152,11 @@ portTickType xValueOfInsertion;
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?).
See http://www.freertos.org/FAQHelp.html for more tips. See http://www.freertos.org/FAQHelp.html for more tips, and ensure
configASSERT() is defined! http://www.freertos.org/a00110.html#configASSERT
**********************************************************************/ **********************************************************************/
for( pxIterator = ( xListItem * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
{ {
/* There is nothing to do here, we are just iterating to the /* There is nothing to do here, we are just iterating to the
wanted insertion position. */ wanted insertion position. */
@ -177,22 +176,24 @@ portTickType xValueOfInsertion;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
unsigned portBASE_TYPE uxListRemove( xListItem * const pxItemToRemove ) UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{ {
xList * pxList; /* The list item knows which list it is in. Obtain the list from the list
item. */
List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
/* The list item knows which list it is in. Obtain the list from the list
item. */
pxList = ( xList * ) pxItemToRemove->pvContainer;
/* Make sure the index is left pointing to a valid item. */ /* Make sure the index is left pointing to a valid item. */
if( pxList->pxIndex == pxItemToRemove ) if( pxList->pxIndex == pxItemToRemove )
{ {
pxList->pxIndex = pxItemToRemove->pxPrevious; pxList->pxIndex = pxItemToRemove->pxPrevious;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
pxItemToRemove->pvContainer = NULL; pxItemToRemove->pvContainer = NULL;
( pxList->uxNumberOfItems )--; ( pxList->uxNumberOfItems )--;

View File

@ -0,0 +1,364 @@
/*
FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that has become a de facto standard. *
* *
* Help yourself get started quickly and support the FreeRTOS *
* project by purchasing a FreeRTOS tutorial book, reference *
* manual, or both from: http://www.FreeRTOS.org/Documentation *
* *
* Thank you! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
>>! NOTE: The modification to the GPL is included to allow you to distribute
>>! a combined work that includes FreeRTOS without being obliged to provide
>>! the source code for proprietary components outside of the FreeRTOS
>>! kernel.
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available from the following
link: http://www.freertos.org/a00114.html
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong?" *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
license and Real Time Engineers Ltd. contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM CM0 port.
*----------------------------------------------------------*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
/* Constants required to manipulate the NVIC. */
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t *) 0xe000e010 )
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t *) 0xe000e014 )
#define portNVIC_INT_CTRL ( ( volatile uint32_t *) 0xe000ed04 )
#define portNVIC_SYSPRI2 ( ( volatile uint32_t *) 0xe000ed20 )
#define portNVIC_SYSTICK_CLK 0x00000004
#define portNVIC_SYSTICK_INT 0x00000002
#define portNVIC_SYSTICK_ENABLE 0x00000001
#define portNVIC_PENDSVSET 0x10000000
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )
/* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 )
/* Let the user override the pre-loading of the initial LR with the address of
prvTaskExitError() in case is messes up unwinding of the stack in the
debugger. */
#ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#else
#define portTASK_RETURN_ADDRESS prvTaskExitError
#endif
/* Each task maintains its own interrupt status in the critical nesting
variable. */
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
/*
* Setup the timer to generate the tick interrupts.
*/
static void prvSetupTimerInterrupt( void );
/*
* Exception handlers.
*/
void xPortPendSVHandler( void ) __attribute__ (( naked ));
void xPortSysTickHandler( void );
void vPortSVCHandler( void );
/*
* Start first task is a separate function so it can be tested in isolation.
*/
static void vPortStartFirstTask( void ) __attribute__ (( naked ));
/*
* Used to catch tasks that attempt to return from their implementing function.
*/
static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
{
/* Simulate the stack frame as it would be created by a context switch
interrupt. */
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack -= 8; /* R11..R4. */
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
static void prvTaskExitError( void )
{
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT( uxCriticalNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ;; );
}
/*-----------------------------------------------------------*/
void vPortSVCHandler( void )
{
/* This function is no longer used, but retained for backward
compatibility. */
}
/*-----------------------------------------------------------*/
void vPortStartFirstTask( void )
{
/* 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.
Not all M0 parts have the application vector table at address 0. */
__asm volatile(
" ldr r2, pxCurrentTCBConst2 \n" /* Obtain location of pxCurrentTCB. */
" ldr r3, [r2] \n"
" ldr r0, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" add 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. */
" movs r0, #2 \n" /* Switch to the psp stack. */
" msr CONTROL, r0 \n"
" pop {r0-r5} \n" /* Pop the registers that are saved automatically. */
" mov lr, r5 \n" /* lr is now in r5. */
" cpsie i \n" /* The first task has its context and interrupts can be enabled. */
" pop {pc} \n" /* Finally, pop the PC to jump to the user defined task code. */
" \n"
" .align 2 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB "
);
}
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
BaseType_t xPortStartScheduler( void )
{
/* Make PendSV, CallSV and SysTick the same priroity as the kernel. */
*(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI;
*(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI;
/* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */
prvSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */
uxCriticalNesting = 0;
/* Start the first task. */
vPortStartFirstTask();
/* Should never get here as the tasks will now be executing! Call the task
exit error function to prevent compiler warnings about a static function
not being called in the case that the application writer overrides this
functionality by defining configTASK_RETURN_ADDRESS. */
prvTaskExitError();
/* Should not get here! */
return 0;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL );
}
/*-----------------------------------------------------------*/
void vPortYield( void )
{
/* Set a PendSV to request a context switch. */
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
/* Barriers are normally not required but do ensure the code is completely
within the specified behaviour for the architecture. */
__asm volatile( "dsb" );
__asm volatile( "isb" );
}
/*-----------------------------------------------------------*/
void vPortEnterCritical( void )
{
portDISABLE_INTERRUPTS();
uxCriticalNesting++;
__asm volatile( "dsb" );
__asm volatile( "isb" );
}
/*-----------------------------------------------------------*/
void vPortExitCritical( void )
{
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if( uxCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
}
}
/*-----------------------------------------------------------*/
uint32_t ulSetInterruptMaskFromISR( void )
{
__asm volatile(
" mrs r0, PRIMASK \n"
" cpsid i \n"
" bx lr "
);
/* To avoid compiler warnings. This line will never be reached. */
return 0;
}
/*-----------------------------------------------------------*/
void vClearInterruptMaskFromISR( uint32_t ulMask )
{
__asm volatile(
" msr PRIMASK, r0 \n"
" bx lr "
);
/* Just to avoid compiler warning. */
( void ) ulMask;
}
/*-----------------------------------------------------------*/
void xPortPendSVHandler( void )
{
/* This is a naked function. */
__asm volatile
(
" mrs r0, psp \n"
" \n"
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n"
" \n"
" sub r0, r0, #32 \n" /* Make space for the remaining low registers. */
" str r0, [r2] \n" /* Save the new top of stack. */
" stmia r0!, {r4-r7} \n" /* Store the low registers that are not saved automatically. */
" mov r4, r8 \n" /* Store the high registers. */
" mov r5, r9 \n"
" mov r6, r10 \n"
" mov r7, r11 \n"
" stmia r0!, {r4-r7} \n"
" \n"
" push {r3, r14} \n"
" cpsid i \n"
" bl vTaskSwitchContext \n"
" cpsie i \n"
" pop {r2, r3} \n" /* lr goes in r3. r2 now holds tcb pointer. */
" \n"
" ldr r1, [r2] \n"
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" add r0, r0, #16 \n" /* Move to the high registers. */
" ldmia r0!, {r4-r7} \n" /* Pop the high registers. */
" mov r8, r4 \n"
" mov r9, r5 \n"
" mov r10, r6 \n"
" mov r11, r7 \n"
" \n"
" msr psp, r0 \n" /* Remember the new top of stack for the task. */
" \n"
" sub r0, r0, #32 \n" /* Go back for the low registers that are not automatically restored. */
" ldmia r0!, {r4-r7} \n" /* Pop low registers. */
" \n"
" bx r3 \n"
" \n"
" .align 2 \n"
"pxCurrentTCBConst: .word pxCurrentTCB "
);
}
/*-----------------------------------------------------------*/
void xPortSysTickHandler( void )
{
uint32_t ulPreviousMask;
ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
{
/* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE )
{
/* Pend a context switch. */
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
}
/*-----------------------------------------------------------*/
/*
* Setup the systick timer to generate the tick interrupts at the required
* frequency.
*/
void prvSetupTimerInterrupt( void )
{
/* Configure SysTick to interrupt at the requested rate. */
*(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
*(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,149 @@
/*
FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that has become a de facto standard. *
* *
* Help yourself get started quickly and support the FreeRTOS *
* project by purchasing a FreeRTOS tutorial book, reference *
* manual, or both from: http://www.FreeRTOS.org/Documentation *
* *
* Thank you! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
>>! NOTE: The modification to the GPL is included to allow you to distribute
>>! a combined work that includes FreeRTOS without being obliged to provide
>>! the source code for proprietary components outside of the FreeRTOS
>>! kernel.
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available from the following
link: http://www.freertos.org/a00114.html
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong?" *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
license and Real Time Engineers Ltd. contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------
* Port specific definitions.
*
* The settings in this file configure FreeRTOS correctly for the
* given hardware and compiler.
*
* These settings should not be altered.
*-----------------------------------------------------------
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif
/*-----------------------------------------------------------*/
/* Architecture specifics. */
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/
/* Scheduler utilities. */
extern void vPortYield( void );
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portYIELD() vPortYield()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/
/* Critical section management. */
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
extern uint32_t ulSetInterruptMaskFromISR( void ) __attribute__((naked));
extern void vClearInterruptMaskFromISR( uint32_t ulMask ) __attribute__((naked));
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMaskFromISR( x )
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " )
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " )
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portNOP()
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -79,31 +80,36 @@ FreeRTOS.org versions prior to V4.4.0 did not include this definition. */
#ifndef configSYSTICK_CLOCK_HZ #ifndef configSYSTICK_CLOCK_HZ
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
/* Ensure the SysTick is clocked at the same frequency as the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#else
/* 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 )
#endif #endif
/* Constants required to manipulate the core. Registers first... */ /* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile unsigned long * ) 0xe000e018 ) ) #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile unsigned long * ) 0xe000ed20 ) ) #define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
/* ...then bits in the registers. */ /* ...then bits in the registers. */
#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 )
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) #define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) #define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) #define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
/* 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 unsigned long * ) 0xE000ED0C ) ) #define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
#define portMAX_8_BIT_VALUE ( ( unsigned char ) 0xff ) #define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
#define portTOP_BIT_OF_BYTE ( ( unsigned char ) 0x80 ) #define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
#define portMAX_PRIGROUP_BITS ( ( unsigned char ) 7 ) #define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) #define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
#define portPRIGROUP_SHIFT ( 8UL ) #define portPRIGROUP_SHIFT ( 8UL )
@ -118,9 +124,18 @@ occurred while the SysTick counter is stopped during tickless idle
calculations. */ calculations. */
#define portMISSED_COUNTS_FACTOR ( 45UL ) #define portMISSED_COUNTS_FACTOR ( 45UL )
/* Let the user override the pre-loading of the initial LR with the address of
prvTaskExitError() in case is messes up unwinding of the stack in the
debugger. */
#ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#else
#define portTASK_RETURN_ADDRESS prvTaskExitError
#endif
/* 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 unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
/* /*
* Setup the timer to generate the tick interrupts. The implementation in this * Setup the timer to generate the tick interrupts. The implementation in this
@ -141,13 +156,18 @@ void vPortSVCHandler( void ) __attribute__ (( naked ));
*/ */
static void prvPortStartFirstTask( void ) __attribute__ (( naked )); static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
/*
* Used to catch tasks that attempt to return from their implementing function.
*/
static void prvTaskExitError( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* 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 unsigned long ulTimerCountsForOneTick = 0; static uint32_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/* /*
@ -155,7 +175,7 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
* 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 unsigned long xMaximumPossibleSuppressedTicks = 0; static uint32_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/* /*
@ -163,7 +183,7 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
* power functionality only. * power functionality only.
*/ */
#if configUSE_TICKLESS_IDLE == 1 #if configUSE_TICKLESS_IDLE == 1
static unsigned long ulStoppedTimerCompensation = 0; static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/* /*
@ -172,9 +192,9 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
*/ */
#if ( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
static unsigned char ucMaxSysCallPriority = 0; static uint8_t ucMaxSysCallPriority = 0;
static unsigned long ulMaxPRIGROUPValue = 0; static uint32_t ulMaxPRIGROUPValue = 0;
static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -182,24 +202,38 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
/* /*
* See header file for description. * See header file for description.
*/ */
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE 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--;
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ *pxTopOfStack = ( StackType_t ) pxCode; /* PC */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0; /* LR */ *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvTaskExitError( void )
{
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT( uxCriticalNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ;; );
}
/*-----------------------------------------------------------*/
void vPortSVCHandler( void ) void vPortSVCHandler( void )
{ {
__asm volatile ( __asm volatile (
@ -208,6 +242,7 @@ void vPortSVCHandler( void )
" 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. */
" ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ " ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
" msr psp, r0 \n" /* Restore the task stack pointer. */ " msr psp, r0 \n" /* Restore the task stack pointer. */
" isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" orr r14, #0xd \n" " orr r14, #0xd \n"
@ -227,6 +262,8 @@ static void prvPortStartFirstTask( void )
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" 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"
" isb \n"
" svc 0 \n" /* System call to start first task. */ " svc 0 \n" /* System call to start first task. */
" nop \n" " nop \n"
); );
@ -236,7 +273,7 @@ static void prvPortStartFirstTask( void )
/* /*
* See header file for description. * See header file for description.
*/ */
portBASE_TYPE xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
@ -244,9 +281,9 @@ portBASE_TYPE xPortStartScheduler( void )
#if( configASSERT_DEFINED == 1 ) #if( configASSERT_DEFINED == 1 )
{ {
volatile unsigned long ulOriginalPriority; volatile uint32_t ulOriginalPriority;
volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
volatile unsigned char 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
@ -254,14 +291,14 @@ portBASE_TYPE xPortStartScheduler( void )
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 = *pcFirstUserPriorityRegister; 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. */
*pcFirstUserPriorityRegister = 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. */
ucMaxPriorityValue = *pcFirstUserPriorityRegister; ucMaxPriorityValue = *pucFirstUserPriorityRegister;
/* Use the same mask on the maximum system call priority. */ /* Use the same mask on the maximum system call priority. */
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
@ -272,7 +309,7 @@ portBASE_TYPE xPortStartScheduler( void )
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulMaxPRIGROUPValue--; ulMaxPRIGROUPValue--;
ucMaxPriorityValue <<= ( unsigned char ) 0x01; ucMaxPriorityValue <<= ( uint8_t ) 0x01;
} }
/* Shift the priority group value back to its position within the AIRCR /* Shift the priority group value back to its position within the AIRCR
@ -282,7 +319,7 @@ portBASE_TYPE xPortStartScheduler( void )
/* Restore the clobbered interrupt priority register to its original /* Restore the clobbered interrupt priority register to its original
value. */ value. */
*pcFirstUserPriorityRegister = ulOriginalPriority; *pucFirstUserPriorityRegister = ulOriginalPriority;
} }
#endif /* conifgASSERT_DEFINED */ #endif /* conifgASSERT_DEFINED */
@ -300,6 +337,12 @@ portBASE_TYPE xPortStartScheduler( void )
/* Start the first task. */ /* Start the first task. */
prvPortStartFirstTask(); prvPortStartFirstTask();
/* Should never get here as the tasks will now be executing! Call the task
exit error function to prevent compiler warnings about a static function
not being called in the case that the application writer overrides this
functionality by defining configTASK_RETURN_ADDRESS. */
prvTaskExitError();
/* Should not get here! */ /* Should not get here! */
return 0; return 0;
} }
@ -307,8 +350,9 @@ portBASE_TYPE xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the CM3 port will require this function as there /* Not implemented in ports where there is nothing to return to.
is nothing to return to. */ Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -335,6 +379,7 @@ void vPortEnterCritical( void )
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
configASSERT( uxCriticalNesting );
uxCriticalNesting--; uxCriticalNesting--;
if( uxCriticalNesting == 0 ) if( uxCriticalNesting == 0 )
{ {
@ -343,7 +388,7 @@ void vPortExitCritical( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__attribute__(( naked )) unsigned long ulPortSetInterruptMask( void ) __attribute__(( naked )) uint32_t ulPortSetInterruptMask( void )
{ {
__asm volatile \ __asm volatile \
( \ ( \
@ -360,7 +405,7 @@ __attribute__(( naked )) unsigned long ulPortSetInterruptMask( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__attribute__(( naked )) void vPortClearInterruptMask( unsigned long ulNewMaskValue ) __attribute__(( naked )) void vPortClearInterruptMask( uint32_t ulNewMaskValue )
{ {
__asm volatile \ __asm volatile \
( \ ( \
@ -381,6 +426,7 @@ void xPortPendSVHandler( void )
__asm volatile __asm volatile
( (
" mrs r0, psp \n" " mrs r0, psp \n"
" isb \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"
@ -400,6 +446,7 @@ void xPortPendSVHandler( void )
" 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. */
" ldmia r0!, {r4-r11} \n" /* Pop the registers. */ " ldmia r0!, {r4-r11} \n" /* Pop the registers. */
" msr psp, r0 \n" " msr psp, r0 \n"
" isb \n"
" bx r14 \n" " bx r14 \n"
" \n" " \n"
" .align 2 \n" " .align 2 \n"
@ -431,10 +478,10 @@ void xPortSysTickHandler( void )
#if configUSE_TICKLESS_IDLE == 1 #if configUSE_TICKLESS_IDLE == 1
__attribute__((weak)) void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime ) __attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{ {
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
portTickType xModifiableIdleTime; TickType_t xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */ /* Make sure the SysTick reload value does not overflow the counter. */
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
@ -446,7 +493,7 @@ void xPortSysTickHandler( void )
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_CLK_BIT | portNVIC_SYSTICK_INT_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
@ -465,8 +512,16 @@ void xPortSysTickHandler( void )
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
this tick period. */
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* Restart SysTick. */ /* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Reset the reload register to the value required for normal tick
periods. */
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. */
@ -482,7 +537,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */ /* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | 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
@ -503,19 +558,32 @@ void xPortSysTickHandler( void )
accounted for as best it can be, but using the tickless mode will 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_CLK_BIT | portNVIC_SYSTICK_INT_BIT; ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
/* Re-enable interrupts - see comments above the cpsid instruction() /* Re-enable interrupts - see comments above the cpsid instruction()
above. */ above. */
__asm volatile( "cpsie i" ); __asm volatile( "cpsie i" );
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{ {
uint32_t ulCalculatedLoadValue;
/* The tick interrupt has already executed, and the SysTick /* The tick interrupt has already executed, and the SysTick
count reloaded with ulReloadValue. Reset the count 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. */
portNVIC_SYSTICK_LOAD_REG = ( 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
underflowed because the post sleep hook did something
that took too long. */
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
{
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
}
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
/* The tick interrupt handler will already have pended the tick /* The tick interrupt handler will already have pended the tick
processing in the kernel. As the pending tick will be processing in the kernel. As the pending tick will be
@ -549,7 +617,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portENTER_CRITICAL(); portENTER_CRITICAL();
{ {
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | 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;
} }
@ -576,8 +644,8 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/* Configure SysTick to interrupt at the requested rate. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;; portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -585,8 +653,8 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
void vPortValidateInterruptPriority( void ) void vPortValidateInterruptPriority( void )
{ {
unsigned long ulCurrentInterrupt; uint32_t ulCurrentInterrupt;
unsigned char ucCurrentPriority; uint8_t ucCurrentPriority;
/* Obtain the number of the currently executing interrupt. */ /* Obtain the number of the currently executing interrupt. */
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) ); __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -86,29 +87,32 @@ extern "C" {
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE unsigned portLONG #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef unsigned portSHORT portTickType; typedef uint16_t TickType_t;
#define portMAX_DELAY ( portTickType ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef unsigned portLONG portTickType; typedef uint32_t TickType_t;
#define portMAX_DELAY ( portTickType ) 0xffffffff #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specifics. */ /* Architecture specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portBYTE_HEAP_ALIGNMENT 4 // this value is used to allocate heap
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Scheduler utilities. */ /* Scheduler utilities. */
extern void vPortYield( void ); extern void vPortYield( void );
#define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 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
@ -118,15 +122,14 @@ extern void vPortYield( void );
/* Critical section management. */ /* Critical section management. */
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
extern unsigned long ulPortSetInterruptMask( void ); extern uint32_t ulPortSetInterruptMask( void );
extern void vPortClearInterruptMask( unsigned long ulNewMaskValue ); extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
#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)
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() #define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
#define portENABLE_INTERRUPTS() vPortClearInterruptMask(0) #define portENABLE_INTERRUPTS() vPortClearInterruptMask(0)
#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. These are /* Task function macros as described on the FreeRTOS.org WEB site. These are
@ -138,7 +141,7 @@ not necessary for to use this port. They are defined so the common demo files
/* Tickless idle/low power functionality. */ /* Tickless idle/low power functionality. */
#ifndef portSUPPRESS_TICKS_AND_SLEEP #ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( portTickType 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
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -147,9 +150,9 @@ not necessary for to use this port. They are defined so the common demo files
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Generic helper function. */ /* Generic helper function. */
__attribute__( ( always_inline ) ) static inline unsigned char ucPortCountLeadingZeros( unsigned long ulBitmap ) __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
{ {
unsigned char ucReturn; uint8_t ucReturn;
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) ); __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) );
return ucReturn; return ucReturn;

View File

@ -0,0 +1,1234 @@
/*
FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that has become a de facto standard. *
* *
* Help yourself get started quickly and support the FreeRTOS *
* project by purchasing a FreeRTOS tutorial book, reference *
* manual, or both from: http://www.FreeRTOS.org/Documentation *
* *
* Thank you! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
>>! NOTE: The modification to the GPL is included to allow you to distribute
>>! a combined work that includes FreeRTOS without being obliged to provide
>>! the source code for proprietary components outside of the FreeRTOS
>>! kernel.
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available from the following
link: http://www.freertos.org/a00114.html
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong?" *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
license and Real Time Engineers Ltd. contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM CM3 port.
*----------------------------------------------------------*/
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
all the API functions to use the MPU wrappers. That should only be done when
task.h is included from an application file. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* Constants required to access and manipulate the NVIC. */
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 )
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 )
#define portNVIC_SYSPRI2 ( ( volatile uint32_t * ) 0xe000ed20 )
#define portNVIC_SYSPRI1 ( ( volatile uint32_t * ) 0xe000ed1c )
#define portNVIC_SYS_CTRL_STATE ( ( volatile uint32_t * ) 0xe000ed24 )
#define portNVIC_MEM_FAULT_ENABLE ( 1UL << 16UL )
/* Constants required to access and manipulate the MPU. */
#define portMPU_TYPE ( ( volatile uint32_t * ) 0xe000ed90 )
#define portMPU_REGION_BASE_ADDRESS ( ( volatile uint32_t * ) 0xe000ed9C )
#define portMPU_REGION_ATTRIBUTE ( ( volatile uint32_t * ) 0xe000edA0 )
#define portMPU_CTRL ( ( volatile uint32_t * ) 0xe000ed94 )
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
#define portMPU_ENABLE ( 0x01UL )
#define portMPU_BACKGROUND_ENABLE ( 1UL << 2UL )
#define portPRIVILEGED_EXECUTION_START_ADDRESS ( 0UL )
#define portMPU_REGION_VALID ( 0x10UL )
#define portMPU_REGION_ENABLE ( 0x01UL )
#define portPERIPHERALS_START_ADDRESS 0x40000000UL
#define portPERIPHERALS_END_ADDRESS 0x5FFFFFFFUL
/* Constants required to access and manipulate the SysTick. */
#define portNVIC_SYSTICK_CLK ( 0x00000004UL )
#define portNVIC_SYSTICK_INT ( 0x00000002UL )
#define portNVIC_SYSTICK_ENABLE ( 0x00000001UL )
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
#define portNVIC_SVC_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
/* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 )
#define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 )
#define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 )
/* Offsets in the stack to the parameters when inside the SVC handler. */
#define portOFFSET_TO_PC ( 6 )
/* Set the privilege level to user mode if xRunningPrivileged is false. */
#define portRESET_PRIVILEGE( xRunningPrivileged ) if( xRunningPrivileged != pdTRUE ) __asm volatile ( " mrs r0, control \n orr r0, #1 \n msr control, r0" :::"r0" )
/* Each task maintains its own interrupt status in the critical nesting
variable. Note this is not saved as part of the task context as context
switches can only occur when uxCriticalNesting is zero. */
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
/*
* Setup the timer to generate the tick interrupts.
*/
static void prvSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION;
/*
* Configure a number of standard MPU regions that are used by all tasks.
*/
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
/*
* Return the smallest MPU region size that a given number of bytes will fit
* into. The region size is returned as the value that should be programmed
* into the region attribute register for that region.
*/
static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) PRIVILEGED_FUNCTION;
/*
* Checks to see if being called from the context of an unprivileged task, and
* if so raises the privilege level and returns false - otherwise does nothing
* other than return true.
*/
static BaseType_t prvRaisePrivilege( void ) __attribute__(( naked ));
/*
* Standard FreeRTOS exception handlers.
*/
void xPortPendSVHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
void xPortSysTickHandler( void ) __attribute__ ((optimize("3"))) PRIVILEGED_FUNCTION;
void vPortSVCHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
/*
* Starts the scheduler by restoring the context of the first task to run.
*/
static void prvRestoreContextOfFirstTask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
/*
* C portion of the SVC handler. The SVC handler is split between an asm entry
* and a C wrapper for simplicity of coding and maintenance.
*/
static void prvSVCHandler( uint32_t *pulRegisters ) __attribute__(( noinline )) PRIVILEGED_FUNCTION;
/*
* Prototypes for all the MPU wrappers.
*/
BaseType_t MPU_xTaskGenericCreate( TaskFunction_t pvTaskCode, const char * const pcName, uint16_t usStackDepth, void *pvParameters, UBaseType_t uxPriority, TaskHandle_t *pxCreatedTask, StackType_t *puxStackBuffer, const MemoryRegion_t * const xRegions );
void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const xRegions );
void MPU_vTaskDelete( TaskHandle_t pxTaskToDelete );
void MPU_vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, TickType_t xTimeIncrement );
void MPU_vTaskDelay( TickType_t xTicksToDelay );
UBaseType_t MPU_uxTaskPriorityGet( TaskHandle_t pxTask );
void MPU_vTaskPrioritySet( TaskHandle_t pxTask, UBaseType_t uxNewPriority );
eTaskState MPU_eTaskGetState( TaskHandle_t pxTask );
void MPU_vTaskSuspend( TaskHandle_t pxTaskToSuspend );
void MPU_vTaskResume( TaskHandle_t pxTaskToResume );
void MPU_vTaskSuspendAll( void );
BaseType_t MPU_xTaskResumeAll( void );
TickType_t MPU_xTaskGetTickCount( void );
UBaseType_t MPU_uxTaskGetNumberOfTasks( void );
void MPU_vTaskList( char *pcWriteBuffer );
void MPU_vTaskGetRunTimeStats( char *pcWriteBuffer );
void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxTagValue );
TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask );
BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter );
UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void );
BaseType_t MPU_xTaskGetSchedulerState( void );
TaskHandle_t MPU_xTaskGetIdleTaskHandle( void );
UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t *pxTaskStatusArray, UBaseType_t uxArraySize, uint32_t *pulTotalRunTime );
QueueHandle_t MPU_xQueueGenericCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize, uint8_t ucQueueType );
BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition );
BaseType_t MPU_xQueueGenericReset( QueueHandle_t pxQueue, BaseType_t xNewQueue );
UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t pxQueue );
BaseType_t MPU_xQueueGenericReceive( QueueHandle_t pxQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking );
QueueHandle_t MPU_xQueueCreateMutex( void );
QueueHandle_t MPU_xQueueCreateCountingSemaphore( UBaseType_t uxCountValue, UBaseType_t uxInitialCount );
BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xBlockTime );
BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t xMutex );
BaseType_t MPU_xQueueAltGenericSend( QueueHandle_t pxQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition );
BaseType_t MPU_xQueueAltGenericReceive( QueueHandle_t pxQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking );
void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, char *pcName );
void MPU_vQueueDelete( QueueHandle_t xQueue );
void *MPU_pvPortMalloc( size_t xSize );
void MPU_vPortFree( void *pv );
void MPU_vPortInitialiseBlocks( void );
size_t MPU_xPortGetFreeHeapSize( void );
QueueSetHandle_t MPU_xQueueCreateSet( UBaseType_t uxEventQueueLength );
QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t xBlockTimeTicks );
BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet );
BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet );
BaseType_t MPU_xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer );
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged )
{
/* Simulate the stack frame as it would be created by a context switch
interrupt. */
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
pxTopOfStack--;
*pxTopOfStack = 0; /* LR */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
if( xRunPrivileged == pdTRUE )
{
*pxTopOfStack = portINITIAL_CONTROL_IF_PRIVILEGED;
}
else
{
*pxTopOfStack = portINITIAL_CONTROL_IF_UNPRIVILEGED;
}
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
void vPortSVCHandler( void )
{
/* Assumes psp was in use. */
__asm volatile
(
#ifndef USE_PROCESS_STACK /* Code should not be required if a main() is using the process stack. */
" tst lr, #4 \n"
" ite eq \n"
" mrseq r0, msp \n"
" mrsne r0, psp \n"
#else
" mrs r0, psp \n"
#endif
" b %0 \n"
::"i"(prvSVCHandler):"r0"
);
}
/*-----------------------------------------------------------*/
static void prvSVCHandler( uint32_t *pulParam )
{
uint8_t ucSVCNumber;
/* The stack contains: r0, r1, r2, r3, r12, r14, the return address and
xPSR. The first argument (r0) is pulParam[ 0 ]. */
ucSVCNumber = ( ( uint8_t * ) pulParam[ portOFFSET_TO_PC ] )[ -2 ];
switch( ucSVCNumber )
{
case portSVC_START_SCHEDULER : *(portNVIC_SYSPRI1) |= portNVIC_SVC_PRI;
prvRestoreContextOfFirstTask();
break;
case portSVC_YIELD : *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;
/* Barriers are normally not required
but do ensure the code is completely
within the specified behaviour for the
architecture. */
__asm volatile( "dsb" );
__asm volatile( "isb" );
break;
case portSVC_RAISE_PRIVILEGE : __asm volatile
(
" mrs r1, control \n" /* Obtain current control value. */
" bic r1, #1 \n" /* Set privilege bit. */
" msr control, r1 \n" /* Write back new control value. */
:::"r1"
);
break;
default : /* Unknown SVC call. */
break;
}
}
/*-----------------------------------------------------------*/
static void prvRestoreContextOfFirstTask( void )
{
__asm volatile
(
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"
" ldr r0, [r0] \n"
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
" ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */
" ldr r1, [r3] \n"
" ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */
" add r1, r1, #4 \n" /* Move onto the second item in the TCB... */
" ldr r2, =0xe000ed9c \n" /* Region Base Address register. */
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */
" stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */
" ldmia r0!, {r3, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry. */
" msr control, r3 \n"
" msr psp, r0 \n" /* Restore the task stack pointer. */
" mov r0, #0 \n"
" msr basepri, r0 \n"
" ldr r14, =0xfffffffd \n" /* Load exec return code. */
" bx r14 \n"
" \n"
" .align 2 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
);
}
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
BaseType_t xPortStartScheduler( void )
{
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See
http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) );
/* Make PendSV and SysTick the same priority as the kernel. */
*(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI;
*(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI;
/* Configure the regions in the MPU that are common to all tasks. */
prvSetupMPU();
/* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */
prvSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */
uxCriticalNesting = 0;
/* Start the first task. */
__asm volatile( " svc %0 \n"
:: "i" (portSVC_START_SCHEDULER) );
/* Should not get here! */
return 0;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL );
}
/*-----------------------------------------------------------*/
void vPortEnterCritical( void )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
portDISABLE_INTERRUPTS();
uxCriticalNesting++;
portRESET_PRIVILEGE( xRunningPrivileged );
}
/*-----------------------------------------------------------*/
void vPortExitCritical( void )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if( uxCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
}
portRESET_PRIVILEGE( xRunningPrivileged );
}
/*-----------------------------------------------------------*/
void xPortPendSVHandler( void )
{
/* This is a naked function. */
__asm volatile
(
" mrs r0, psp \n"
" \n"
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n"
" \n"
" mrs r1, control \n"
" stmdb r0!, {r1, r4-r11} \n" /* Save the remaining registers. */
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
" \n"
" stmdb sp!, {r3, r14} \n"
" mov r0, %0 \n"
" msr basepri, r0 \n"
" bl vTaskSwitchContext \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
" ldmia sp!, {r3, r14} \n"
" \n" /* Restore the context. */
" ldr r1, [r3] \n"
" ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */
" add r1, r1, #4 \n" /* Move onto the second item in the TCB... */
" ldr r2, =0xe000ed9c \n" /* Region Base Address register. */
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */
" stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */
" ldmia r0!, {r3, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry. */
" msr control, r3 \n"
" \n"
" msr psp, r0 \n"
" bx r14 \n"
" \n"
" .align 2 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n"
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)
);
}
/*-----------------------------------------------------------*/
void xPortSysTickHandler( void )
{
uint32_t ulDummy;
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();
{
/* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE )
{
/* Pend a context switch. */
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );
}
/*-----------------------------------------------------------*/
/*
* Setup the systick timer to generate the tick interrupts at the required
* frequency.
*/
static void prvSetupTimerInterrupt( void )
{
/* Configure SysTick to interrupt at the requested rate. */
*(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
*(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
}
/*-----------------------------------------------------------*/
static void prvSetupMPU( void )
{
extern uint32_t __privileged_functions_end__[];
extern uint32_t __FLASH_segment_start__[];
extern uint32_t __FLASH_segment_end__[];
extern uint32_t __privileged_data_start__[];
extern uint32_t __privileged_data_end__[];
/* Check the expected MPU is present. */
if( *portMPU_TYPE == portEXPECTED_MPU_TYPE_VALUE )
{
/* First setup the entire flash for unprivileged read only access. */
*portMPU_REGION_BASE_ADDRESS = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
( portMPU_REGION_VALID ) |
( portUNPRIVILEGED_FLASH_REGION );
*portMPU_REGION_ATTRIBUTE = ( portMPU_REGION_READ_ONLY ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
( portMPU_REGION_ENABLE );
/* Setup the first 16K for privileged only access (even though less
than 10K is actually being used). This is where the kernel code is
placed. */
*portMPU_REGION_BASE_ADDRESS = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
( portMPU_REGION_VALID ) |
( portPRIVILEGED_FLASH_REGION );
*portMPU_REGION_ATTRIBUTE = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
( portMPU_REGION_ENABLE );
/* Setup the privileged data RAM region. This is where the kernel data
is placed. */
*portMPU_REGION_BASE_ADDRESS = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
( portMPU_REGION_VALID ) |
( portPRIVILEGED_RAM_REGION );
*portMPU_REGION_ATTRIBUTE = ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) |
( portMPU_REGION_ENABLE );
/* By default allow everything to access the general peripherals. The
system peripherals and registers are protected. */
*portMPU_REGION_BASE_ADDRESS = ( portPERIPHERALS_START_ADDRESS ) |
( portMPU_REGION_VALID ) |
( portGENERAL_PERIPHERALS_REGION );
*portMPU_REGION_ATTRIBUTE = ( portMPU_REGION_READ_WRITE | portMPU_REGION_EXECUTE_NEVER ) |
( prvGetMPURegionSizeSetting( portPERIPHERALS_END_ADDRESS - portPERIPHERALS_START_ADDRESS ) ) |
( portMPU_REGION_ENABLE );
/* Enable the memory fault exception. */
*portNVIC_SYS_CTRL_STATE |= portNVIC_MEM_FAULT_ENABLE;
/* Enable the MPU with the background region configured. */
*portMPU_CTRL |= ( portMPU_ENABLE | portMPU_BACKGROUND_ENABLE );
}
}
/*-----------------------------------------------------------*/
static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes )
{
uint32_t ulRegionSize, ulReturnValue = 4;
/* 32 is the smallest region size, 31 is the largest valid value for
ulReturnValue. */
for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) )
{
if( ulActualSizeInBytes <= ulRegionSize )
{
break;
}
else
{
ulReturnValue++;
}
}
/* Shift the code by one before returning so it can be written directly
into the the correct bit position of the attribute register. */
return ( ulReturnValue << 1UL );
}
/*-----------------------------------------------------------*/
static BaseType_t prvRaisePrivilege( void )
{
__asm volatile
(
" mrs r0, control \n"
" tst r0, #1 \n" /* Is the task running privileged? */
" itte ne \n"
" movne r0, #0 \n" /* CONTROL[0]!=0, return false. */
" svcne %0 \n" /* Switch to privileged. */
" moveq r0, #1 \n" /* CONTROL[0]==0, return true. */
" bx lr \n"
:: "i" (portSVC_RAISE_PRIVILEGE) : "r0"
);
return 0;
}
/*-----------------------------------------------------------*/
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint16_t usStackDepth )
{
extern uint32_t __SRAM_segment_start__[];
extern uint32_t __SRAM_segment_end__[];
extern uint32_t __privileged_data_start__[];
extern uint32_t __privileged_data_end__[];
int32_t lIndex;
uint32_t ul;
if( xRegions == NULL )
{
/* No MPU regions are specified so allow access to all RAM. */
xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress =
( ( uint32_t ) __SRAM_segment_start__ ) | /* Base address. */
( portMPU_REGION_VALID ) |
( portSTACK_REGION );
xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
( portMPU_REGION_READ_WRITE ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) |
( portMPU_REGION_ENABLE );
/* Re-instate the privileged only RAM region as xRegion[ 0 ] will have
just removed the privileged only parameters. */
xMPUSettings->xRegion[ 1 ].ulRegionBaseAddress =
( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
( portMPU_REGION_VALID ) |
( portSTACK_REGION + 1 );
xMPUSettings->xRegion[ 1 ].ulRegionAttribute =
( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) |
( portMPU_REGION_ENABLE );
/* Invalidate all other regions. */
for( ul = 2; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ )
{
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( portSTACK_REGION + ul ) | portMPU_REGION_VALID;
xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL;
}
}
else
{
/* This function is called automatically when the task is created - in
which case the stack region parameters will be valid. At all other
times the stack parameters will not be valid and it is assumed that the
stack region has already been configured. */
if( usStackDepth > 0 )
{
/* Define the region that allows access to the stack. */
xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress =
( ( uint32_t ) pxBottomOfStack ) |
( portMPU_REGION_VALID ) |
( portSTACK_REGION ); /* Region number. */
xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
( portMPU_REGION_READ_WRITE ) | /* Read and write. */
( prvGetMPURegionSizeSetting( ( uint32_t ) usStackDepth * ( uint32_t ) sizeof( StackType_t ) ) ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
( portMPU_REGION_ENABLE );
}
lIndex = 0;
for( ul = 1; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ )
{
if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL )
{
/* Translate the generic region definition contained in
xRegions into the CM3 specific MPU settings that are then
stored in xMPUSettings. */
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress =
( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) |
( portMPU_REGION_VALID ) |
( portSTACK_REGION + ul ); /* Region number. */
xMPUSettings->xRegion[ ul ].ulRegionAttribute =
( prvGetMPURegionSizeSetting( xRegions[ lIndex ].ulLengthInBytes ) ) |
( xRegions[ lIndex ].ulParameters ) |
( portMPU_REGION_ENABLE );
}
else
{
/* Invalidate the region. */
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( portSTACK_REGION + ul ) | portMPU_REGION_VALID;
xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL;
}
lIndex++;
}
}
}
/*-----------------------------------------------------------*/
BaseType_t MPU_xTaskGenericCreate( TaskFunction_t pvTaskCode, const char * const pcName, uint16_t usStackDepth, void *pvParameters, UBaseType_t uxPriority, TaskHandle_t *pxCreatedTask, StackType_t *puxStackBuffer, const MemoryRegion_t * const xRegions )
{
BaseType_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xTaskGenericCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, puxStackBuffer, xRegions );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
/*-----------------------------------------------------------*/
void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const xRegions )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
vTaskAllocateMPURegions( xTask, xRegions );
portRESET_PRIVILEGE( xRunningPrivileged );
}
/*-----------------------------------------------------------*/
#if ( INCLUDE_vTaskDelete == 1 )
void MPU_vTaskDelete( TaskHandle_t pxTaskToDelete )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
vTaskDelete( pxTaskToDelete );
portRESET_PRIVILEGE( xRunningPrivileged );
}
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_vTaskDelayUntil == 1 )
void MPU_vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, TickType_t xTimeIncrement )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
vTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement );
portRESET_PRIVILEGE( xRunningPrivileged );
}
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_vTaskDelay == 1 )
void MPU_vTaskDelay( TickType_t xTicksToDelay )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
vTaskDelay( xTicksToDelay );
portRESET_PRIVILEGE( xRunningPrivileged );
}
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_uxTaskPriorityGet == 1 )
UBaseType_t MPU_uxTaskPriorityGet( TaskHandle_t pxTask )
{
UBaseType_t uxReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
uxReturn = uxTaskPriorityGet( pxTask );
portRESET_PRIVILEGE( xRunningPrivileged );
return uxReturn;
}
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_vTaskPrioritySet == 1 )
void MPU_vTaskPrioritySet( TaskHandle_t pxTask, UBaseType_t uxNewPriority )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
vTaskPrioritySet( pxTask, uxNewPriority );
portRESET_PRIVILEGE( xRunningPrivileged );
}
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_eTaskGetState == 1 )
eTaskState MPU_eTaskGetState( TaskHandle_t pxTask )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
eTaskState eReturn;
eReturn = eTaskGetState( pxTask );
portRESET_PRIVILEGE( xRunningPrivileged );
return eReturn;
}
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
TaskHandle_t MPU_xTaskGetIdleTaskHandle( void )
{
TaskHandle_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xTaskGetIdleTaskHandle();
portRESET_PRIVILEGE( xRunningPrivileged );
return eReturn;
}
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_vTaskSuspend == 1 )
void MPU_vTaskSuspend( TaskHandle_t pxTaskToSuspend )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
vTaskSuspend( pxTaskToSuspend );
portRESET_PRIVILEGE( xRunningPrivileged );
}
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_vTaskSuspend == 1 )
void MPU_vTaskResume( TaskHandle_t pxTaskToResume )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
vTaskResume( pxTaskToResume );
portRESET_PRIVILEGE( xRunningPrivileged );
}
#endif
/*-----------------------------------------------------------*/
void MPU_vTaskSuspendAll( void )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
vTaskSuspendAll();
portRESET_PRIVILEGE( xRunningPrivileged );
}
/*-----------------------------------------------------------*/
BaseType_t MPU_xTaskResumeAll( void )
{
BaseType_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xTaskResumeAll();
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
/*-----------------------------------------------------------*/
TickType_t MPU_xTaskGetTickCount( void )
{
TickType_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xTaskGetTickCount();
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
/*-----------------------------------------------------------*/
UBaseType_t MPU_uxTaskGetNumberOfTasks( void )
{
UBaseType_t uxReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
uxReturn = uxTaskGetNumberOfTasks();
portRESET_PRIVILEGE( xRunningPrivileged );
return uxReturn;
}
/*-----------------------------------------------------------*/
#if ( configUSE_TRACE_FACILITY == 1 )
void MPU_vTaskList( char *pcWriteBuffer )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
vTaskList( pcWriteBuffer );
portRESET_PRIVILEGE( xRunningPrivileged );
}
#endif
/*-----------------------------------------------------------*/
#if ( configGENERATE_RUN_TIME_STATS == 1 )
void MPU_vTaskGetRunTimeStats( char *pcWriteBuffer )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
vTaskGetRunTimeStats( pcWriteBuffer );
portRESET_PRIVILEGE( xRunningPrivileged );
}
#endif
/*-----------------------------------------------------------*/
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxTagValue )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
vTaskSetApplicationTaskTag( xTask, pxTagValue );
portRESET_PRIVILEGE( xRunningPrivileged );
}
#endif
/*-----------------------------------------------------------*/
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask )
{
TaskHookFunction_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xTaskGetApplicationTaskTag( xTask );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter )
{
BaseType_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xTaskCallApplicationTaskHook( xTask, pvParameter );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t *pxTaskStatusArray, UBaseType_t uxArraySize, uint32_t *pulTotalRunTime )
{
UBaseType_t uxReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
uxReturn = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, pulTotalRunTime );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
{
UBaseType_t uxReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
uxReturn = uxTaskGetStackHighWaterMark( xTask );
portRESET_PRIVILEGE( xRunningPrivileged );
return uxReturn;
}
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_xTaskGetCurrentTaskHandle == 1 )
TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void )
{
TaskHandle_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xTaskGetCurrentTaskHandle();
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_xTaskGetSchedulerState == 1 )
BaseType_t MPU_xTaskGetSchedulerState( void )
{
BaseType_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xTaskGetSchedulerState();
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
QueueHandle_t MPU_xQueueGenericCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize, uint8_t ucQueueType )
{
QueueHandle_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xQueueGenericCreate( uxQueueLength, uxItemSize, ucQueueType );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
/*-----------------------------------------------------------*/
BaseType_t MPU_xQueueGenericReset( QueueHandle_t pxQueue, BaseType_t xNewQueue )
{
BaseType_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xQueueGenericReset( pxQueue, xNewQueue );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
/*-----------------------------------------------------------*/
BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition )
{
BaseType_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, xCopyPosition );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
/*-----------------------------------------------------------*/
UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t pxQueue )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
UBaseType_t uxReturn;
uxReturn = uxQueueMessagesWaiting( pxQueue );
portRESET_PRIVILEGE( xRunningPrivileged );
return uxReturn;
}
/*-----------------------------------------------------------*/
BaseType_t MPU_xQueueGenericReceive( QueueHandle_t pxQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
BaseType_t xReturn;
xReturn = xQueueGenericReceive( pxQueue, pvBuffer, xTicksToWait, xJustPeeking );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
/*-----------------------------------------------------------*/
BaseType_t MPU_xQueuePeekFromISR( QueueHandle_t pxQueue, void * const pvBuffer )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
BaseType_t xReturn;
xReturn = xQueuePeekFromISR( pxQueue, pvBuffer );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
/*-----------------------------------------------------------*/
#if ( configUSE_MUTEXES == 1 )
QueueHandle_t MPU_xQueueCreateMutex( void )
{
QueueHandle_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xQueueCreateMutex( queueQUEUE_TYPE_MUTEX );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if configUSE_COUNTING_SEMAPHORES == 1
QueueHandle_t MPU_xQueueCreateCountingSemaphore( UBaseType_t uxCountValue, UBaseType_t uxInitialCount )
{
QueueHandle_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xQueueCreateCountingSemaphore( uxCountValue, uxInitialCount );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if ( configUSE_MUTEXES == 1 )
BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xBlockTime )
{
BaseType_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xQueueTakeMutexRecursive( xMutex, xBlockTime );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if ( configUSE_MUTEXES == 1 )
BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t xMutex )
{
BaseType_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xQueueGiveMutexRecursive( xMutex );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if ( configUSE_QUEUE_SETS == 1 )
QueueSetHandle_t MPU_xQueueCreateSet( UBaseType_t uxEventQueueLength )
{
QueueSetHandle_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xQueueCreateSet( uxEventQueueLength );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if ( configUSE_QUEUE_SETS == 1 )
QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t xBlockTimeTicks )
{
QueueSetMemberHandle_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xQueueSelectFromSet( xQueueSet, xBlockTimeTicks );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if ( configUSE_QUEUE_SETS == 1 )
BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet )
{
BaseType_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xQueueAddToSet( xQueueOrSemaphore, xQueueSet );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if ( configUSE_QUEUE_SETS == 1 )
BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet )
{
BaseType_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xQueueRemoveFromSet( xQueueOrSemaphore, xQueueSet );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if configUSE_ALTERNATIVE_API == 1
BaseType_t MPU_xQueueAltGenericSend( QueueHandle_t pxQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition )
{
BaseType_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = BaseType_t xQueueAltGenericSend( pxQueue, pvItemToQueue, xTicksToWait, xCopyPosition );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if configUSE_ALTERNATIVE_API == 1
BaseType_t MPU_xQueueAltGenericReceive( QueueHandle_t pxQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking )
{
BaseType_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xQueueAltGenericReceive( pxQueue, pvBuffer, xTicksToWait, xJustPeeking );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if configQUEUE_REGISTRY_SIZE > 0
void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, char *pcName )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
vQueueAddToRegistry( xQueue, pcName );
portRESET_PRIVILEGE( xRunningPrivileged );
}
#endif
/*-----------------------------------------------------------*/
void MPU_vQueueDelete( QueueHandle_t xQueue )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
vQueueDelete( xQueue );
portRESET_PRIVILEGE( xRunningPrivileged );
}
/*-----------------------------------------------------------*/
void *MPU_pvPortMalloc( size_t xSize )
{
void *pvReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
pvReturn = pvPortMalloc( xSize );
portRESET_PRIVILEGE( xRunningPrivileged );
return pvReturn;
}
/*-----------------------------------------------------------*/
void MPU_vPortFree( void *pv )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
vPortFree( pv );
portRESET_PRIVILEGE( xRunningPrivileged );
}
/*-----------------------------------------------------------*/
void MPU_vPortInitialiseBlocks( void )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
vPortInitialiseBlocks();
portRESET_PRIVILEGE( xRunningPrivileged );
}
/*-----------------------------------------------------------*/
size_t MPU_xPortGetFreeHeapSize( void )
{
size_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xPortGetFreeHeapSize();
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
/* Functions that the application writer wants to execute in privileged mode
can be defined in application_defined_privileged_functions.h. The functions
must take the same format as those above whereby the privilege state on exit
equals the privilege state on entry. For example:
void MPU_FunctionName( [parameters ] )
{
BaseType_t xRunningPrivileged = prvRaisePrivilege();
FunctionName( [parameters ] );
portRESET_PRIVILEGE( xRunningPrivileged );
}
*/
#if configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS == 1
#include "application_defined_privileged_functions.h"
#endif

View File

@ -0,0 +1,218 @@
/*
FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that has become a de facto standard. *
* *
* Help yourself get started quickly and support the FreeRTOS *
* project by purchasing a FreeRTOS tutorial book, reference *
* manual, or both from: http://www.FreeRTOS.org/Documentation *
* *
* Thank you! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
>>! NOTE: The modification to the GPL is included to allow you to distribute
>>! a combined work that includes FreeRTOS without being obliged to provide
>>! the source code for proprietary components outside of the FreeRTOS
>>! kernel.
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available from the following
link: http://www.freertos.org/a00114.html
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong?" *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
license and Real Time Engineers Ltd. contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------
* Port specific definitions.
*
* The settings in this file configure FreeRTOS correctly for the
* given hardware and compiler.
*
* These settings should not be altered.
*-----------------------------------------------------------
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif
/*-----------------------------------------------------------*/
/* MPU specific constants. */
#define portUSING_MPU_WRAPPERS 1
#define portPRIVILEGE_BIT ( 0x80000000UL )
#define portMPU_REGION_READ_WRITE ( 0x03UL << 24UL )
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
#define portUNPRIVILEGED_FLASH_REGION ( 0UL )
#define portPRIVILEGED_FLASH_REGION ( 1UL )
#define portPRIVILEGED_RAM_REGION ( 2UL )
#define portGENERAL_PERIPHERALS_REGION ( 3UL )
#define portSTACK_REGION ( 4UL )
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
#define portLAST_CONFIGURABLE_REGION ( 7UL )
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
#define portSWITCH_TO_USER_MODE() __asm volatile ( " mrs r0, control \n orr r0, #1 \n msr control, r0 " :::"r0" )
typedef struct MPU_REGION_REGISTERS
{
uint32_t ulRegionBaseAddress;
uint32_t ulRegionAttribute;
} xMPU_REGION_REGISTERS;
/* Plus 1 to create space for the stack region. */
typedef struct MPU_SETTINGS
{
xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS ];
} xMPU_SETTINGS;
/* Architecture specifics. */
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/
/* SVC numbers for various services. */
#define portSVC_START_SCHEDULER 0
#define portSVC_YIELD 1
#define portSVC_RAISE_PRIVILEGE 2
/* Scheduler utilities. */
#define portYIELD() __asm volatile ( " SVC %0 \n" :: "i" (portSVC_YIELD) )
#define portYIELD_WITHIN_API() *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET
#define portNVIC_INT_CTRL ( ( volatile uint32_t *) 0xe000ed04 )
#define portNVIC_PENDSVSET 0x10000000
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/
/* Critical section management. */
/*
* Set basepri to portMAX_SYSCALL_INTERRUPT_PRIORITY without effecting other
* registers. r0 is clobbered.
*/
#define portSET_INTERRUPT_MASK() \
__asm volatile \
( \
" mov r0, %0 \n" \
" msr basepri, r0 \n" \
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY):"r0" \
)
/*
* Set basepri back to 0 without effective other registers.
* r0 is clobbered. FAQ: Setting BASEPRI to 0 is not a bug. Please see
* http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing.
*/
#define portCLEAR_INTERRUPT_MASK() \
__asm volatile \
( \
" mov r0, #0 \n" \
" msr basepri, r0 \n" \
:::"r0" \
)
/* FAQ: Setting BASEPRI to 0 is not a bug. Please see
http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */
#define portSET_INTERRUPT_MASK_FROM_ISR() 0;portSET_INTERRUPT_MASK()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) portCLEAR_INTERRUPT_MASK();(void)x
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK()
#define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK()
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portNOP()
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -76,36 +77,41 @@
#ifndef configSYSTICK_CLOCK_HZ #ifndef configSYSTICK_CLOCK_HZ
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
/* Ensure the SysTick is clocked at the same frequency as the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#else
/* 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 )
#endif #endif
/* Constants required to manipulate the core. Registers first... */ /* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile unsigned long * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile unsigned long * ) 0xe000e018 ) ) #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile unsigned long * ) 0xe000ed20 ) ) #define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
/* ...then bits in the registers. */ /* ...then bits in the registers. */
#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 )
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) #define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) #define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) #define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
/* 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 unsigned long * ) 0xE000ED0C ) ) #define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
#define portMAX_8_BIT_VALUE ( ( unsigned char ) 0xff ) #define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
#define portTOP_BIT_OF_BYTE ( ( unsigned char ) 0x80 ) #define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
#define portMAX_PRIGROUP_BITS ( ( unsigned char ) 7 ) #define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) #define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
#define portPRIGROUP_SHIFT ( 8UL ) #define portPRIGROUP_SHIFT ( 8UL )
/* Constants required to manipulate the VFP. */ /* Constants required to manipulate the VFP. */
#define portFPCCR ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */ #define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL ) #define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
/* Constants required to set up the initial stack. */ /* Constants required to set up the initial stack. */
@ -120,9 +126,18 @@ occurred while the SysTick counter is stopped during tickless idle
calculations. */ calculations. */
#define portMISSED_COUNTS_FACTOR ( 45UL ) #define portMISSED_COUNTS_FACTOR ( 45UL )
/* Let the user override the pre-loading of the initial LR with the address of
prvTaskExitError() in case is messes up unwinding of the stack in the
debugger. */
#ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#else
#define portTASK_RETURN_ADDRESS prvTaskExitError
#endif
/* 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 unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
/* /*
* Setup the timer to generate the tick interrupts. The implementation in this * Setup the timer to generate the tick interrupts. The implementation in this
@ -148,13 +163,18 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
*/ */
static void vPortEnableVFP( void ) __attribute__ (( naked )); static void vPortEnableVFP( void ) __attribute__ (( naked ));
/*
* Used to catch tasks that attempt to return from their implementing function.
*/
static void prvTaskExitError( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* 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 unsigned long ulTimerCountsForOneTick = 0; static uint32_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/* /*
@ -162,7 +182,7 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
* 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 unsigned long xMaximumPossibleSuppressedTicks = 0; static uint32_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/* /*
@ -170,18 +190,18 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
* power functionality only. * power functionality only.
*/ */
#if configUSE_TICKLESS_IDLE == 1 #if configUSE_TICKLESS_IDLE == 1
static unsigned long ulStoppedTimerCompensation = 0; static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/* /*
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
* FreeRTOS API functions are not called from interrupts that have been assigned * FreeRTOS API functions are not called from interrupts that have been assigned
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
*/ */
#if ( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
static unsigned char ucMaxSysCallPriority = 0; static uint8_t ucMaxSysCallPriority = 0;
static unsigned long ulMaxPRIGROUPValue = 0; static uint32_t ulMaxPRIGROUPValue = 0;
static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -189,7 +209,7 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
/* /*
* See header file for description. * See header file for description.
*/ */
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE 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. */
@ -200,13 +220,13 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */ *pxTopOfStack = portINITIAL_XPSR; /* xPSR */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ *pxTopOfStack = ( StackType_t ) pxCode; /* PC */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0; /* LR */ *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
/* Save code space by skipping register initialisation. */ /* Save code space by skipping register initialisation. */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( portSTACK_TYPE ) 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. */
@ -219,6 +239,20 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvTaskExitError( void )
{
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT( uxCriticalNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ;; );
}
/*-----------------------------------------------------------*/
void vPortSVCHandler( void ) void vPortSVCHandler( void )
{ {
__asm volatile ( __asm volatile (
@ -227,6 +261,7 @@ void vPortSVCHandler( void )
" 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. */
" ldmia r0!, {r4-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ " ldmia r0!, {r4-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
" msr psp, r0 \n" /* Restore the task stack pointer. */ " msr psp, r0 \n" /* Restore the task stack pointer. */
" isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" bx r14 \n" " bx r14 \n"
@ -245,6 +280,8 @@ static void prvPortStartFirstTask( void )
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" 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"
" isb \n"
" svc 0 \n" /* System call to start first task. */ " svc 0 \n" /* System call to start first task. */
" nop \n" " nop \n"
); );
@ -254,7 +291,7 @@ static void prvPortStartFirstTask( void )
/* /*
* See header file for description. * See header file for description.
*/ */
portBASE_TYPE xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
@ -262,9 +299,9 @@ portBASE_TYPE xPortStartScheduler( void )
#if( configASSERT_DEFINED == 1 ) #if( configASSERT_DEFINED == 1 )
{ {
volatile unsigned long ulOriginalPriority; volatile uint32_t ulOriginalPriority;
volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
volatile unsigned char 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
@ -272,14 +309,14 @@ portBASE_TYPE xPortStartScheduler( void )
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 = *pcFirstUserPriorityRegister; 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. */
*pcFirstUserPriorityRegister = 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. */
ucMaxPriorityValue = *pcFirstUserPriorityRegister; ucMaxPriorityValue = *pucFirstUserPriorityRegister;
/* Use the same mask on the maximum system call priority. */ /* Use the same mask on the maximum system call priority. */
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
@ -290,7 +327,7 @@ portBASE_TYPE xPortStartScheduler( void )
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulMaxPRIGROUPValue--; ulMaxPRIGROUPValue--;
ucMaxPriorityValue <<= ( unsigned char ) 0x01; ucMaxPriorityValue <<= ( uint8_t ) 0x01;
} }
/* Shift the priority group value back to its position within the AIRCR /* Shift the priority group value back to its position within the AIRCR
@ -300,7 +337,7 @@ portBASE_TYPE xPortStartScheduler( void )
/* Restore the clobbered interrupt priority register to its original /* Restore the clobbered interrupt priority register to its original
value. */ value. */
*pcFirstUserPriorityRegister = ulOriginalPriority; *pucFirstUserPriorityRegister = ulOriginalPriority;
} }
#endif /* conifgASSERT_DEFINED */ #endif /* conifgASSERT_DEFINED */
@ -324,6 +361,12 @@ portBASE_TYPE xPortStartScheduler( void )
/* Start the first task. */ /* Start the first task. */
prvPortStartFirstTask(); prvPortStartFirstTask();
/* Should never get here as the tasks will now be executing! Call the task
exit error function to prevent compiler warnings about a static function
not being called in the case that the application writer overrides this
functionality by defining configTASK_RETURN_ADDRESS. */
prvTaskExitError();
/* Should not get here! */ /* Should not get here! */
return 0; return 0;
} }
@ -331,8 +374,9 @@ portBASE_TYPE xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the CM4F port will require this function as there /* Not implemented in ports where there is nothing to return to.
is nothing to return to. */ Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -359,6 +403,7 @@ void vPortEnterCritical( void )
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
configASSERT( uxCriticalNesting );
uxCriticalNesting--; uxCriticalNesting--;
if( uxCriticalNesting == 0 ) if( uxCriticalNesting == 0 )
{ {
@ -367,7 +412,7 @@ void vPortExitCritical( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__attribute__(( naked )) unsigned long ulPortSetInterruptMask( void ) __attribute__(( naked )) uint32_t ulPortSetInterruptMask( void )
{ {
__asm volatile \ __asm volatile \
( \ ( \
@ -384,7 +429,7 @@ __attribute__(( naked )) unsigned long ulPortSetInterruptMask( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__attribute__(( naked )) void vPortClearInterruptMask( unsigned long ulNewMaskValue ) __attribute__(( naked )) void vPortClearInterruptMask( uint32_t ulNewMaskValue )
{ {
__asm volatile \ __asm volatile \
( \ ( \
@ -405,8 +450,9 @@ void xPortPendSVHandler( void )
__asm volatile __asm volatile
( (
" mrs r0, psp \n" " mrs r0, psp \n"
" isb \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"
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */ " tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */
@ -417,13 +463,13 @@ void xPortPendSVHandler( void )
" \n" " \n"
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
" \n" " \n"
" stmdb sp!, {r3, r14} \n" " stmdb sp!, {r3} \n"
" mov r0, %0 \n" " mov r0, %0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" ldmia sp!, {r3, r14} \n" " ldmia sp!, {r3} \n"
" \n" " \n"
" ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldr r0, [r1] \n" " ldr r0, [r1] \n"
@ -435,6 +481,15 @@ void xPortPendSVHandler( void )
" vldmiaeq r0!, {s16-s31} \n" " vldmiaeq r0!, {s16-s31} \n"
" \n" " \n"
" msr psp, r0 \n" " msr psp, r0 \n"
" isb \n"
" \n"
#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */
#if WORKAROUND_PMU_CM001 == 1
" push { r14 } \n"
" pop { pc } \n"
#endif
#endif
" \n"
" bx r14 \n" " bx r14 \n"
" \n" " \n"
" .align 2 \n" " .align 2 \n"
@ -466,10 +521,10 @@ void xPortSysTickHandler( void )
#if configUSE_TICKLESS_IDLE == 1 #if configUSE_TICKLESS_IDLE == 1
__attribute__((weak)) void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime ) __attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{ {
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
portTickType xModifiableIdleTime; TickType_t xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */ /* Make sure the SysTick reload value does not overflow the counter. */
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
@ -481,7 +536,7 @@ void xPortSysTickHandler( void )
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_CLK_BIT | portNVIC_SYSTICK_INT_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
@ -500,8 +555,16 @@ void xPortSysTickHandler( void )
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
this tick period. */
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* Restart SysTick. */ /* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Reset the reload register to the value required for normal tick
periods. */
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. */
@ -517,7 +580,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */ /* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | 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
@ -538,19 +601,32 @@ void xPortSysTickHandler( void )
accounted for as best it can be, but using the tickless mode will 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_CLK_BIT | portNVIC_SYSTICK_INT_BIT; ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
/* Re-enable interrupts - see comments above the cpsid instruction() /* Re-enable interrupts - see comments above the cpsid instruction()
above. */ above. */
__asm volatile( "cpsie i" ); __asm volatile( "cpsie i" );
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{ {
uint32_t ulCalculatedLoadValue;
/* The tick interrupt has already executed, and the SysTick /* The tick interrupt has already executed, and the SysTick
count reloaded with ulReloadValue. Reset the count 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. */
portNVIC_SYSTICK_LOAD_REG = ( 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
underflowed because the post sleep hook did something
that took too long. */
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
{
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
}
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
/* The tick interrupt handler will already have pended the tick /* The tick interrupt handler will already have pended the tick
processing in the kernel. As the pending tick will be processing in the kernel. As the pending tick will be
@ -584,7 +660,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portENTER_CRITICAL(); portENTER_CRITICAL();
{ {
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | 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;
} }
@ -611,8 +687,8 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/* Configure SysTick to interrupt at the requested rate. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;; portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -635,8 +711,8 @@ static void vPortEnableVFP( void )
void vPortValidateInterruptPriority( void ) void vPortValidateInterruptPriority( void )
{ {
unsigned long ulCurrentInterrupt; uint32_t ulCurrentInterrupt;
unsigned char ucCurrentPriority; uint8_t ucCurrentPriority;
/* Obtain the number of the currently executing interrupt. */ /* Obtain the number of the currently executing interrupt. */
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) ); __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -86,29 +87,32 @@ extern "C" {
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE unsigned portLONG #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef unsigned portSHORT portTickType; typedef uint16_t TickType_t;
#define portMAX_DELAY ( portTickType ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef unsigned portLONG portTickType; typedef uint32_t TickType_t;
#define portMAX_DELAY ( portTickType ) 0xffffffff #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specifics. */ /* Architecture specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portBYTE_HEAP_ALIGNMENT 4 // this value is used to allocate heap
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Scheduler utilities. */ /* Scheduler utilities. */
extern void vPortYield( void ); extern void vPortYield( void );
#define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 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
@ -118,14 +122,15 @@ extern void vPortYield( void );
/* Critical section management. */ /* Critical section management. */
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
extern unsigned long ulPortSetInterruptMask( void ); extern uint32_t ulPortSetInterruptMask( void );
extern void vPortClearInterruptMask( unsigned long ulNewMaskValue ); extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
#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)
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() #define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
#define portENABLE_INTERRUPTS() vPortClearInterruptMask(0) #define portENABLE_INTERRUPTS() vPortClearInterruptMask(0)
#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. These are /* Task function macros as described on the FreeRTOS.org WEB site. These are
@ -137,7 +142,7 @@ not necessary for to use this port. They are defined so the common demo files
/* Tickless idle/low power functionality. */ /* Tickless idle/low power functionality. */
#ifndef portSUPPRESS_TICKS_AND_SLEEP #ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( portTickType 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
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -146,9 +151,9 @@ not necessary for to use this port. They are defined so the common demo files
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Generic helper function. */ /* Generic helper function. */
__attribute__( ( always_inline ) ) static inline unsigned char ucPortCountLeadingZeros( unsigned long ulBitmap ) __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
{ {
unsigned char ucReturn; uint8_t ucReturn;
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) ); __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) );
return ucReturn; return ucReturn;

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -82,64 +83,67 @@ task.h is included from an application file. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
static size_t currentTOTAL_HEAP_SIZE = configTOTAL_HEAP_SIZE;
/* A few bytes might be lost to byte aligning the heap start address. */
#define configADJUSTED_HEAP_SIZE ( currentTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )
/* Allocate the memory for the heap. */ /* Allocate the memory for the heap. */
static unsigned char ucHeap[ configTOTAL_HEAP_SIZE ] __attribute__ ((section (".heap"))); static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ] __attribute__ ((section (".heap")));
static size_t xNextFreeByte = ( size_t ) 0; static size_t xNextFreeByte = ( size_t ) 0;
static size_t currentTOTAL_HEAP_SIZE = configTOTAL_HEAP_SIZE;
void *pvPortMallocGeneric( size_t xWantedSize, size_t alignment);
/* A few bytes might be lost to byte aligning the heap start address. */
#define configADJUSTED_HEAP_SIZE (currentTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT)
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void *pvPortMallocGeneric(size_t xWantedSize, size_t alignment) { void *pvPortMalloc( size_t xWantedSize )
void *pvReturn = NULL; {
static unsigned char *pucAlignedHeap = NULL; void *pvReturn = NULL;
size_t mask = alignment - 1; static uint8_t *pucAlignedHeap = NULL;
/* Ensure that blocks are always aligned to the required number of bytes. */
#if portBYTE_ALIGNMENT != 1
if (xWantedSize & mask) {
/* Byte alignment required. */
xWantedSize += (alignment - (xWantedSize & mask));
}
#endif
vTaskSuspendAll(); /* Ensure that blocks are always aligned to the required number of bytes. */
{ #if portBYTE_ALIGNMENT != 1
if (pucAlignedHeap == NULL ) { if( xWantedSize & portBYTE_ALIGNMENT_MASK )
/* Ensure the heap starts on a correctly aligned boundary. */ {
pucAlignedHeap = (unsigned char *) (((portPOINTER_SIZE_TYPE ) &ucHeap[alignment]) & ((portPOINTER_SIZE_TYPE ) ~mask)); /* Byte alignment required. */
} xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
}
#endif
/* Check there is enough room left for the allocation. */ vTaskSuspendAll();
if (((xNextFreeByte + xWantedSize) < configADJUSTED_HEAP_SIZE)&& {
( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) ){ if( pucAlignedHeap == NULL )
/* Check for overflow. */ {
/* Return the next free byte then increment the index past this block. */ /* Ensure the heap starts on a correctly aligned boundary. */
pvReturn = pucAlignedHeap + xNextFreeByte; pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) );
xNextFreeByte += xWantedSize; }
}
}
xTaskResumeAll();
#if( configUSE_MALLOC_FAILED_HOOK == 1 ) /* Check there is enough room left for the allocation. */
{ if( ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) &&
if( pvReturn == NULL ) { ( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) )/* Check for overflow. */
extern void vApplicationMallocFailedHook( void ); {
vApplicationMallocFailedHook(); /* Return the next free byte then increment the index past this
} block. */
} pvReturn = pucAlignedHeap + xNextFreeByte;
#endif xNextFreeByte += xWantedSize;
}
return pvReturn; traceMALLOC( pvReturn, xWantedSize );
}
xTaskResumeAll();
#if( configUSE_MALLOC_FAILED_HOOK == 1 )
{
if( pvReturn == NULL )
{
extern void vApplicationMallocFailedHook( void );
vApplicationMallocFailedHook();
}
}
#endif
return pvReturn;
} }
void *pvPortMalloc(size_t xWantedSize) {
return pvPortMallocGeneric(xWantedSize, portBYTE_HEAP_ALIGNMENT);
}
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -166,7 +170,6 @@ size_t xPortGetFreeHeapSize( void )
{ {
return ( configADJUSTED_HEAP_SIZE - xNextFreeByte ); return ( configADJUSTED_HEAP_SIZE - xNextFreeByte );
} }
/*-----------------------------------------------------------*/
void xPortIncreaseHeapSize( size_t bytes ) void xPortIncreaseHeapSize( size_t bytes )
{ {

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -86,13 +87,13 @@ task.h is included from an application file. */
/* A few bytes might be lost to byte aligning the heap start address. */ /* A few bytes might be lost to byte aligning the heap start address. */
#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT ) #define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )
/* /*
* Initialises the heap structures before their first use. * Initialises the heap structures before their first use.
*/ */
static void prvHeapInit( void ); static void prvHeapInit( void );
/* Allocate the memory for the heap. */ /* Allocate the memory for the heap. */
static unsigned char ucHeap[ configTOTAL_HEAP_SIZE ]; static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
/* Define the linked list structure. This is used to link free blocks in order /* Define the linked list structure. This is used to link free blocks in order
of their size. */ of their size. */
@ -100,14 +101,14 @@ 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. */
} xBlockLink; } BlockLink_t;
static const unsigned short heapSTRUCT_SIZE = ( ( sizeof ( xBlockLink ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK ); static const uint16_t heapSTRUCT_SIZE = ( ( sizeof ( BlockLink_t ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK );
#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) ) #define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) )
/* Create a couple of list links to mark the start and end of the list. */ /* Create a couple of list links to mark the start and end of the list. */
static xBlockLink xStart, xEnd; static BlockLink_t xStart, xEnd;
/* Keeps track of the number of free bytes remaining, but says nothing about /* Keeps track of the number of free bytes remaining, but says nothing about
fragmentation. */ fragmentation. */
@ -122,7 +123,7 @@ static size_t xFreeBytesRemaining = configADJUSTED_HEAP_SIZE;
*/ */
#define prvInsertBlockIntoFreeList( pxBlockToInsert ) \ #define prvInsertBlockIntoFreeList( pxBlockToInsert ) \
{ \ { \
xBlockLink *pxIterator; \ BlockLink_t *pxIterator; \
size_t xBlockSize; \ size_t xBlockSize; \
\ \
xBlockSize = pxBlockToInsert->xBlockSize; \ xBlockSize = pxBlockToInsert->xBlockSize; \
@ -143,8 +144,8 @@ size_t xBlockSize; \
void *pvPortMalloc( size_t xWantedSize ) void *pvPortMalloc( size_t xWantedSize )
{ {
xBlockLink *pxBlock, *pxPreviousBlock, *pxNewBlockLink; BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
static portBASE_TYPE xHeapHasBeenInitialised = pdFALSE; static BaseType_t xHeapHasBeenInitialised = pdFALSE;
void *pvReturn = NULL; void *pvReturn = NULL;
vTaskSuspendAll(); vTaskSuspendAll();
@ -157,7 +158,7 @@ void *pvReturn = NULL;
xHeapHasBeenInitialised = pdTRUE; xHeapHasBeenInitialised = pdTRUE;
} }
/* The wanted size is increased so it can contain a xBlockLink /* The wanted size is increased so it can contain a BlockLink_t
structure in addition to the requested amount of bytes. */ structure in addition to the requested amount of bytes. */
if( xWantedSize > 0 ) if( xWantedSize > 0 )
{ {
@ -186,9 +187,9 @@ void *pvReturn = NULL;
/* If we found the end marker then a block of adequate size was not found. */ /* If we found the end marker then a block of adequate size was not found. */
if( pxBlock != &xEnd ) if( pxBlock != &xEnd )
{ {
/* Return the memory space - jumping over the xBlockLink structure /* Return the memory space - jumping over the BlockLink_t structure
at its start. */ at its start. */
pvReturn = ( void * ) ( ( ( unsigned char * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE ); pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE );
/* This block is being returned for use so must be taken out of the /* This block is being returned for use so must be taken out of the
list of free blocks. */ list of free blocks. */
@ -200,7 +201,7 @@ void *pvReturn = NULL;
/* This block is to be split into two. Create a new block /* This block is to be split into two. Create a new block
following the number of bytes requested. The void cast is following the number of bytes requested. The void cast is
used to prevent byte alignment warnings from the compiler. */ used to prevent byte alignment warnings from the compiler. */
pxNewBlockLink = ( void * ) ( ( ( unsigned char * ) pxBlock ) + xWantedSize ); pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
/* Calculate the sizes of two blocks split from the single /* Calculate the sizes of two blocks split from the single
block. */ block. */
@ -214,6 +215,8 @@ void *pvReturn = NULL;
xFreeBytesRemaining -= pxBlock->xBlockSize; xFreeBytesRemaining -= pxBlock->xBlockSize;
} }
} }
traceMALLOC( pvReturn, xWantedSize );
} }
xTaskResumeAll(); xTaskResumeAll();
@ -233,24 +236,25 @@ void *pvReturn = NULL;
void vPortFree( void *pv ) void vPortFree( void *pv )
{ {
unsigned char *puc = ( unsigned char * ) pv; uint8_t *puc = ( uint8_t * ) pv;
xBlockLink *pxLink; BlockLink_t *pxLink;
if( pv != NULL ) if( pv != NULL )
{ {
/* The memory being freed will have an xBlockLink structure immediately /* The memory being freed will have an BlockLink_t structure immediately
before it. */ before it. */
puc -= heapSTRUCT_SIZE; puc -= heapSTRUCT_SIZE;
/* This unexpected casting is to keep some compilers from issuing /* This unexpected casting is to keep some compilers from issuing
byte alignment warnings. */ byte alignment warnings. */
pxLink = ( void * ) puc; pxLink = ( void * ) puc;
vTaskSuspendAll(); vTaskSuspendAll();
{ {
/* Add this block to the list of free blocks. */ /* Add this block to the list of free blocks. */
prvInsertBlockIntoFreeList( ( ( xBlockLink * ) pxLink ) ); prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
xFreeBytesRemaining += pxLink->xBlockSize; xFreeBytesRemaining += pxLink->xBlockSize;
traceFREE( pv, pxLink->xBlockSize );
} }
xTaskResumeAll(); xTaskResumeAll();
} }
@ -271,11 +275,11 @@ void vPortInitialiseBlocks( void )
static void prvHeapInit( void ) static void prvHeapInit( void )
{ {
xBlockLink *pxFirstFreeBlock; BlockLink_t *pxFirstFreeBlock;
unsigned char *pucAlignedHeap; uint8_t *pucAlignedHeap;
/* Ensure the heap starts on a correctly aligned boundary. */ /* Ensure the heap starts on a correctly aligned boundary. */
pucAlignedHeap = ( unsigned char * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) );
/* xStart is used to hold a pointer to the first item in the list of free /* xStart is used to hold a pointer to the first item in the list of free
blocks. The void cast is used to prevent compiler warnings. */ blocks. The void cast is used to prevent compiler warnings. */

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -95,6 +96,7 @@ void *pvReturn;
vTaskSuspendAll(); vTaskSuspendAll();
{ {
pvReturn = malloc( xWantedSize ); pvReturn = malloc( xWantedSize );
traceMALLOC( pvReturn, xWantedSize );
} }
xTaskResumeAll(); xTaskResumeAll();
@ -119,6 +121,7 @@ void vPortFree( void *pv )
vTaskSuspendAll(); vTaskSuspendAll();
{ {
free( pv ); free( pv );
traceFREE( pv, 0 );
} }
xTaskResumeAll(); xTaskResumeAll();
} }

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -63,11 +64,11 @@
*/ */
/* /*
* A sample implementation of pvPortMalloc() and vPortFree() that combines * A sample implementation of pvPortMalloc() and vPortFree() that combines
* (coalescences) adjacent memory blocks as they are freed, and in so doing * (coalescences) adjacent memory blocks as they are freed, and in so doing
* limits memory fragmentation. * limits memory fragmentation.
* *
* See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the * See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the
* memory management pages of http://www.FreeRTOS.org for more information. * memory management pages of http://www.FreeRTOS.org for more information.
*/ */
#include <stdlib.h> #include <stdlib.h>
@ -92,7 +93,7 @@ task.h is included from an application file. */
#define heapADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT ) #define heapADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )
/* Allocate the memory for the heap. */ /* Allocate the memory for the heap. */
static unsigned char ucHeap[ configTOTAL_HEAP_SIZE ]; static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
/* Define the linked list structure. This is used to link free blocks in order /* Define the linked list structure. This is used to link free blocks in order
of their memory address. */ of their memory address. */
@ -100,17 +101,17 @@ 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. */
} xBlockLink; } BlockLink_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* Inserts a block of memory that is being freed into the correct position in * Inserts a block of memory that is being freed into the correct position in
* the list of free memory blocks. The block being freed will be merged with * the list of free memory blocks. The block being freed will be merged with
* the block in front it and/or the block behind it if the memory blocks are * the block in front it and/or the block behind it if the memory blocks are
* adjacent to each other. * adjacent to each other.
*/ */
static void prvInsertBlockIntoFreeList( xBlockLink *pxBlockToInsert ); static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert );
/* /*
* Called automatically to setup the required heap structures the first time * Called automatically to setup the required heap structures the first time
@ -122,20 +123,21 @@ static void prvHeapInit( void );
/* The size of the structure placed at the beginning of each allocated memory /* The size of the structure placed at the beginning of each allocated memory
block must by correctly byte aligned. */ block must by correctly byte aligned. */
static const unsigned short heapSTRUCT_SIZE = ( ( sizeof ( xBlockLink ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK ); static const uint16_t heapSTRUCT_SIZE = ( ( sizeof ( BlockLink_t ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK );
/* Ensure the pxEnd pointer will end up on the correct byte alignment. */ /* Ensure the pxEnd pointer will end up on the correct byte alignment. */
static const size_t xTotalHeapSize = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK ); static const size_t xTotalHeapSize = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );
/* Create a couple of list links to mark the start and end of the list. */ /* Create a couple of list links to mark the start and end of the list. */
static xBlockLink xStart, *pxEnd = NULL; static BlockLink_t xStart, *pxEnd = NULL;
/* Keeps track of the number of free bytes remaining, but says nothing about /* Keeps track of the number of free bytes remaining, but says nothing about
fragmentation. */ fragmentation. */
static size_t xFreeBytesRemaining = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK ); static size_t xFreeBytesRemaining = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );
static size_t xMinimumEverFreeBytesRemaining = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );
/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize /* Gets set to the top bit of an size_t type. When this bit in the xBlockSize
member of an xBlockLink structure is set then the block belongs to the member of an BlockLink_t structure is set then the block belongs to the
application. When the bit is free the block is still part of the free heap application. When the bit is free the block is still part of the free heap
space. */ space. */
static size_t xBlockAllocatedBit = 0; static size_t xBlockAllocatedBit = 0;
@ -144,7 +146,7 @@ static size_t xBlockAllocatedBit = 0;
void *pvPortMalloc( size_t xWantedSize ) void *pvPortMalloc( size_t xWantedSize )
{ {
xBlockLink *pxBlock, *pxPreviousBlock, *pxNewBlockLink; BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
void *pvReturn = NULL; void *pvReturn = NULL;
vTaskSuspendAll(); vTaskSuspendAll();
@ -155,31 +157,43 @@ void *pvReturn = NULL;
{ {
prvHeapInit(); prvHeapInit();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Check the requested block size is not so large that the top bit is /* Check the requested block size is not so large that the top bit is
set. The top bit of the block size member of the xBlockLink structure set. The top bit of the block size member of the BlockLink_t structure
is used to determine who owns the block - the application or the is used to determine who owns the block - the application or the
kernel, so it must be free. */ kernel, so it must be free. */
if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
{ {
/* The wanted size is increased so it can contain a xBlockLink /* The wanted size is increased so it can contain a BlockLink_t
structure in addition to the requested amount of bytes. */ structure in addition to the requested amount of bytes. */
if( xWantedSize > 0 ) if( xWantedSize > 0 )
{ {
xWantedSize += heapSTRUCT_SIZE; xWantedSize += heapSTRUCT_SIZE;
/* Ensure that blocks are always aligned to the required number /* Ensure that blocks are always aligned to the required number
of bytes. */ of bytes. */
if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
{ {
/* Byte alignment required. */ /* Byte alignment required. */
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
{ {
/* Traverse the list from the start (lowest address) block until /* Traverse the list from the start (lowest address) block until
one of adequate size is found. */ one of adequate size is found. */
pxPreviousBlock = &xStart; pxPreviousBlock = &xStart;
pxBlock = xStart.pxNextFreeBlock; pxBlock = xStart.pxNextFreeBlock;
@ -189,29 +203,29 @@ void *pvReturn = NULL;
pxBlock = pxBlock->pxNextFreeBlock; pxBlock = pxBlock->pxNextFreeBlock;
} }
/* If the end marker was reached then a block of adequate size /* If the end marker was reached then a block of adequate size
was not found. */ was not found. */
if( pxBlock != pxEnd ) if( pxBlock != pxEnd )
{ {
/* Return the memory space pointed to - jumping over the /* Return the memory space pointed to - jumping over the
xBlockLink structure at its start. */ BlockLink_t structure at its start. */
pvReturn = ( void * ) ( ( ( unsigned char * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE ); pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE );
/* This block is being returned for use so must be taken out /* This block is being returned for use so must be taken out
of the list of free blocks. */ of the list of free blocks. */
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
/* If the block is larger than required it can be split into /* If the block is larger than required it can be split into
two. */ two. */
if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
{ {
/* This block is to be split into two. Create a new /* This block is to be split into two. Create a new
block following the number of bytes requested. The void block following the number of bytes requested. The void
cast is used to prevent byte alignment warnings from the cast is used to prevent byte alignment warnings from the
compiler. */ compiler. */
pxNewBlockLink = ( void * ) ( ( ( unsigned char * ) pxBlock ) + xWantedSize ); pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
/* Calculate the sizes of two blocks split from the /* Calculate the sizes of two blocks split from the
single block. */ single block. */
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
pxBlock->xBlockSize = xWantedSize; pxBlock->xBlockSize = xWantedSize;
@ -219,16 +233,43 @@ void *pvReturn = NULL;
/* Insert the new block into the list of free blocks. */ /* Insert the new block into the list of free blocks. */
prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
xFreeBytesRemaining -= pxBlock->xBlockSize; xFreeBytesRemaining -= pxBlock->xBlockSize;
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
{
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* The block is being returned - it is allocated and owned /* The block is being returned - it is allocated and owned
by the application and has no "next" block. */ by the application and has no "next" block. */
pxBlock->xBlockSize |= xBlockAllocatedBit; pxBlock->xBlockSize |= xBlockAllocatedBit;
pxBlock->pxNextFreeBlock = NULL; pxBlock->pxNextFreeBlock = NULL;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
traceMALLOC( pvReturn, xWantedSize );
} }
xTaskResumeAll(); xTaskResumeAll();
@ -239,6 +280,10 @@ void *pvReturn = NULL;
extern void vApplicationMallocFailedHook( void ); extern void vApplicationMallocFailedHook( void );
vApplicationMallocFailedHook(); vApplicationMallocFailedHook();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
#endif #endif
@ -248,12 +293,12 @@ void *pvReturn = NULL;
void vPortFree( void *pv ) void vPortFree( void *pv )
{ {
unsigned char *puc = ( unsigned char * ) pv; uint8_t *puc = ( uint8_t * ) pv;
xBlockLink *pxLink; BlockLink_t *pxLink;
if( pv != NULL ) if( pv != NULL )
{ {
/* The memory being freed will have an xBlockLink structure immediately /* The memory being freed will have an BlockLink_t structure immediately
before it. */ before it. */
puc -= heapSTRUCT_SIZE; puc -= heapSTRUCT_SIZE;
@ -263,7 +308,7 @@ xBlockLink *pxLink;
/* Check the block is actually allocated. */ /* Check the block is actually allocated. */
configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
configASSERT( pxLink->pxNextFreeBlock == NULL ); configASSERT( pxLink->pxNextFreeBlock == NULL );
if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
{ {
if( pxLink->pxNextFreeBlock == NULL ) if( pxLink->pxNextFreeBlock == NULL )
@ -276,10 +321,19 @@ xBlockLink *pxLink;
{ {
/* Add this block to the list of free blocks. */ /* Add this block to the list of free blocks. */
xFreeBytesRemaining += pxLink->xBlockSize; xFreeBytesRemaining += pxLink->xBlockSize;
prvInsertBlockIntoFreeList( ( ( xBlockLink * ) pxLink ) ); traceFREE( pv, pxLink->xBlockSize );
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
} }
xTaskResumeAll(); xTaskResumeAll();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
} }
@ -291,6 +345,12 @@ size_t xPortGetFreeHeapSize( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
size_t xPortGetMinimumEverFreeHeapSize( void )
{
return xMinimumEverFreeBytesRemaining;
}
/*-----------------------------------------------------------*/
void vPortInitialiseBlocks( void ) void vPortInitialiseBlocks( void )
{ {
/* This just exists to keep the linker quiet. */ /* This just exists to keep the linker quiet. */
@ -299,11 +359,11 @@ void vPortInitialiseBlocks( void )
static void prvHeapInit( void ) static void prvHeapInit( void )
{ {
xBlockLink *pxFirstFreeBlock; BlockLink_t *pxFirstFreeBlock;
unsigned char *pucHeapEnd, *pucAlignedHeap; uint8_t *pucHeapEnd, *pucAlignedHeap;
/* Ensure the heap starts on a correctly aligned boundary. */ /* Ensure the heap starts on a correctly aligned boundary. */
pucAlignedHeap = ( unsigned char * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) );
/* xStart is used to hold a pointer to the first item in the list of free /* xStart is used to hold a pointer to the first item in the list of free
blocks. The void cast is used to prevent compiler warnings. */ blocks. The void cast is used to prevent compiler warnings. */
@ -315,7 +375,7 @@ unsigned char *pucHeapEnd, *pucAlignedHeap;
pucHeapEnd = pucAlignedHeap + xTotalHeapSize; pucHeapEnd = pucAlignedHeap + xTotalHeapSize;
pucHeapEnd -= heapSTRUCT_SIZE; pucHeapEnd -= heapSTRUCT_SIZE;
pxEnd = ( void * ) pucHeapEnd; pxEnd = ( void * ) pucHeapEnd;
configASSERT( ( ( ( unsigned long ) pxEnd ) & ( ( unsigned long ) portBYTE_ALIGNMENT_MASK ) ) == 0UL ); configASSERT( ( ( ( uint32_t ) pxEnd ) & ( ( uint32_t ) portBYTE_ALIGNMENT_MASK ) ) == 0UL );
pxEnd->xBlockSize = 0; pxEnd->xBlockSize = 0;
pxEnd->pxNextFreeBlock = NULL; pxEnd->pxNextFreeBlock = NULL;
@ -333,10 +393,10 @@ unsigned char *pucHeapEnd, *pucAlignedHeap;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvInsertBlockIntoFreeList( xBlockLink *pxBlockToInsert ) static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert )
{ {
xBlockLink *pxIterator; BlockLink_t *pxIterator;
unsigned char *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. */
@ -346,18 +406,22 @@ unsigned char *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 = ( unsigned char * ) pxIterator; puc = ( uint8_t * ) pxIterator;
if( ( puc + pxIterator->xBlockSize ) == ( unsigned char * ) pxBlockToInsert ) if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
{ {
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize; pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
pxBlockToInsert = pxIterator; pxBlockToInsert = pxIterator;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
/* 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 = ( unsigned char * ) pxBlockToInsert; puc = ( uint8_t * ) pxBlockToInsert;
if( ( puc + pxBlockToInsert->xBlockSize ) == ( unsigned char * ) pxIterator->pxNextFreeBlock ) if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
{ {
if( pxIterator->pxNextFreeBlock != pxEnd ) if( pxIterator->pxNextFreeBlock != pxEnd )
{ {
@ -372,7 +436,7 @@ unsigned char *puc;
} }
else else
{ {
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
} }
/* If the block being inserted plugged a gab, so was merged with the block /* If the block being inserted plugged a gab, so was merged with the block
@ -383,5 +447,9 @@ unsigned char *puc;
{ {
pxIterator->pxNextFreeBlock = pxBlockToInsert; pxIterator->pxNextFreeBlock = pxBlockToInsert;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -85,13 +86,13 @@ privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
/* Constants used with the cRxLock and xTxLock structure members. */ /* Constants used with the xRxLock and xTxLock structure members. */
#define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 ) #define queueUNLOCKED ( ( BaseType_t ) -1 )
#define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 ) #define queueLOCKED_UNMODIFIED ( ( BaseType_t ) 0 )
/* When the xQUEUE structure is used to represent a base queue its pcHead and /* When the Queue_t structure is used to represent a base queue its pcHead and
pcTail members are used as pointers into the queue storage area. When the pcTail members are used as pointers into the queue storage area. When the
xQUEUE structure is used to represent a mutex pcHead and pcTail pointers are Queue_t structure is used to represent a mutex pcHead and pcTail pointers are
not necessary, and the pcHead pointer is set to NULL to indicate that the not necessary, and the pcHead pointer is set to NULL to indicate that the
pcTail pointer actually points to the mutex holder (if any). Map alternative pcTail pointer actually points to the mutex holder (if any). Map alternative
names to the pcHead and pcTail structure members to ensure the readability of names to the pcHead and pcTail structure members to ensure the readability of
@ -106,9 +107,16 @@ structure member). */
/* Semaphores do not actually store or copy data, so have an item size of /* Semaphores do not actually store or copy data, so have an item size of
zero. */ zero. */
#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portBASE_TYPE ) 0 ) #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( UBaseType_t ) 0 )
#define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0U ) #define queueMUTEX_GIVE_BLOCK_TIME ( ( TickType_t ) 0U )
#if( configUSE_PREEMPTION == 0 )
/* If the cooperative scheduler is being used then a yield should not be
performed just because a higher priority task has been woken. */
#define queueYIELD_IF_USING_PREEMPTION()
#else
#define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
#endif
/* /*
* Definition of the queue used by the scheduler. * Definition of the queue used by the scheduler.
@ -116,30 +124,29 @@ zero. */
*/ */
typedef struct QueueDefinition typedef struct QueueDefinition
{ {
signed char *pcHead; /*< Points to the beginning of the queue storage area. */ int8_t *pcHead; /*< Points to the beginning of the queue storage area. */
signed char *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ int8_t *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */
int8_t *pcWriteTo; /*< Points to the free next place in the storage area. */
signed char *pcWriteTo; /*< Points to the free next place in the storage area. */ union /* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */
union /* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */
{ {
signed char *pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */ int8_t *pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */
unsigned portBASE_TYPE uxRecursiveCallCount;/*< Maintains a count of the numebr of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */ UBaseType_t uxRecursiveCallCount;/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */
} u; } u;
xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ List_t xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */
xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ List_t xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */
volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */ volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */
unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */ UBaseType_t uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */ UBaseType_t uxItemSize; /*< The size of each items that the queue will hold. */
volatile signed portBASE_TYPE xRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ volatile BaseType_t xRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */
volatile signed portBASE_TYPE xTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ volatile BaseType_t xTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
unsigned char ucQueueNumber; UBaseType_t uxQueueNumber;
unsigned char ucQueueType; uint8_t ucQueueType;
#endif #endif
#if ( configUSE_QUEUE_SETS == 1 ) #if ( configUSE_QUEUE_SETS == 1 )
@ -147,6 +154,11 @@ typedef struct QueueDefinition
#endif #endif
} xQUEUE; } xQUEUE;
/* The old xQUEUE name is maintained above then typedefed to the new Queue_t
name below to enable the use of older kernel aware debuggers. */
typedef xQUEUE Queue_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
@ -160,14 +172,19 @@ typedef struct QueueDefinition
more user friendly. */ more user friendly. */
typedef struct QUEUE_REGISTRY_ITEM typedef struct QUEUE_REGISTRY_ITEM
{ {
signed char *pcQueueName; const char *pcQueueName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
xQueueHandle xHandle; QueueHandle_t xHandle;
} xQueueRegistryItem; } xQueueRegistryItem;
/* The queue registry is simply an array of xQueueRegistryItem structures. /* The old xQueueRegistryItem name is maintained above then typedefed to the
new xQueueRegistryItem name below to enable the use of older kernel aware
debuggers. */
typedef xQueueRegistryItem QueueRegistryItem_t;
/* The queue registry is simply an array of QueueRegistryItem_t structures.
The pcQueueName member of a structure being NULL is indicative of the The pcQueueName member of a structure being NULL is indicative of the
array position being vacant. */ array position being vacant. */
xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ]; QueueRegistryItem_t xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
#endif /* configQUEUE_REGISTRY_SIZE */ #endif /* configQUEUE_REGISTRY_SIZE */
@ -179,39 +196,39 @@ typedef struct QueueDefinition
* to indicate that a task may require unblocking. When the queue in unlocked * to indicate that a task may require unblocking. When the queue in unlocked
* these lock counts are inspected, and the appropriate action taken. * these lock counts are inspected, and the appropriate action taken.
*/ */
static void prvUnlockQueue( xQUEUE *pxQueue ) PRIVILEGED_FUNCTION; static void prvUnlockQueue( Queue_t * const pxQueue ) PRIVILEGED_FUNCTION;
/* /*
* Uses a critical section to determine if there is any data in a queue. * Uses a critical section to determine if there is any data in a queue.
* *
* @return pdTRUE if the queue contains no items, otherwise pdFALSE. * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
*/ */
static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue ) PRIVILEGED_FUNCTION; static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue ) PRIVILEGED_FUNCTION;
/* /*
* Uses a critical section to determine if there is any space in a queue. * Uses a critical section to determine if there is any space in a queue.
* *
* @return pdTRUE if there is no space, otherwise pdFALSE; * @return pdTRUE if there is no space, otherwise pdFALSE;
*/ */
static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue ) PRIVILEGED_FUNCTION; static BaseType_t prvIsQueueFull( const Queue_t *pxQueue ) PRIVILEGED_FUNCTION;
/* /*
* Copies an item into the queue, either at the front of the queue or the * Copies an item into the queue, either at the front of the queue or the
* back of the queue. * back of the queue.
*/ */
static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION; static void prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) PRIVILEGED_FUNCTION;
/* /*
* Copies an item out of a queue. * Copies an item out of a queue.
*/ */
static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void * const pvBuffer ) PRIVILEGED_FUNCTION; static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION;
#if ( configUSE_QUEUE_SETS == 1 ) #if ( configUSE_QUEUE_SETS == 1 )
/* /*
* Checks to see if a queue is a member of a queue set, and if so, notifies * Checks to see if a queue is a member of a queue set, and if so, notifies
* the queue set that the queue contains data. * the queue set that the queue contains data.
*/ */
static portBASE_TYPE prvNotifyQueueSetContainer( const xQUEUE * const pxQueue, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION; static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION;
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -235,18 +252,18 @@ static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void * const pvB
taskEXIT_CRITICAL() taskEXIT_CRITICAL()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
portBASE_TYPE xQueueGenericReset( xQueueHandle xQueue, portBASE_TYPE xNewQueue ) BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue )
{ {
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; Queue_t * const pxQueue = ( Queue_t * ) xQueue;
configASSERT( pxQueue ); configASSERT( pxQueue );
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize ); pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize );
pxQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U; pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U;
pxQueue->pcWriteTo = pxQueue->pcHead; pxQueue->pcWriteTo = pxQueue->pcHead;
pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( unsigned portBASE_TYPE ) 1U ) * pxQueue->uxItemSize ); pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( UBaseType_t ) 1U ) * pxQueue->uxItemSize );
pxQueue->xRxLock = queueUNLOCKED; pxQueue->xRxLock = queueUNLOCKED;
pxQueue->xTxLock = queueUNLOCKED; pxQueue->xTxLock = queueUNLOCKED;
@ -254,15 +271,23 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
{ {
/* If there are tasks blocked waiting to read from the queue, then /* If there are tasks blocked waiting to read from the queue, then
the tasks will remain blocked as after this function exits the queue the tasks will remain blocked as after this function exits the queue
will still be empty. If there are tasks blocked waiting to write to will still be empty. If there are tasks blocked waiting to write to
the queue, then one should be unblocked as after this function exits the queue, then one should be unblocked as after this function exits
it will be possible to write to it. */ it will be possible to write to it. */
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
{ {
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
{ {
portYIELD_WITHIN_API(); queueYIELD_IF_USING_PREEMPTION();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
else else
@ -280,27 +305,27 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType ) QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType )
{ {
xQUEUE *pxNewQueue; Queue_t *pxNewQueue;
size_t xQueueSizeInBytes; size_t xQueueSizeInBytes;
xQueueHandle xReturn = NULL; QueueHandle_t xReturn = NULL;
/* Remove compiler warnings about unused parameters should /* Remove compiler warnings about unused parameters should
configUSE_TRACE_FACILITY not be set to 1. */ configUSE_TRACE_FACILITY not be set to 1. */
( void ) ucQueueType; ( void ) ucQueueType;
/* Allocate the new queue structure. */ /* Allocate the new queue structure. */
if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 ) if( uxQueueLength > ( UBaseType_t ) 0 )
{ {
pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) ); pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) );
if( pxNewQueue != NULL ) if( pxNewQueue != NULL )
{ {
/* Create the list of pointers to queue items. The queue is one byte /* Create the list of pointers to queue items. The queue is one byte
longer than asked for to make wrap checking easier/faster. */ longer than asked for to make wrap checking easier/faster. */
xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes ); pxNewQueue->pcHead = ( int8_t * ) pvPortMalloc( xQueueSizeInBytes );
if( pxNewQueue->pcHead != NULL ) if( pxNewQueue->pcHead != NULL )
{ {
/* Initialise the queue members as described above where the /* Initialise the queue members as described above where the
@ -330,6 +355,14 @@ xQueueHandle xReturn = NULL;
vPortFree( pxNewQueue ); vPortFree( pxNewQueue );
} }
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
configASSERT( xReturn ); configASSERT( xReturn );
@ -340,16 +373,16 @@ xQueueHandle xReturn = NULL;
#if ( configUSE_MUTEXES == 1 ) #if ( configUSE_MUTEXES == 1 )
xQueueHandle xQueueCreateMutex( unsigned char ucQueueType ) QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
{ {
xQUEUE *pxNewQueue; Queue_t *pxNewQueue;
/* Prevent compiler warnings about unused parameters if /* Prevent compiler warnings about unused parameters if
configUSE_TRACE_FACILITY does not equal 1. */ configUSE_TRACE_FACILITY does not equal 1. */
( void ) ucQueueType; ( void ) ucQueueType;
/* Allocate the new queue structure. */ /* Allocate the new queue structure. */
pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) ); pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) );
if( pxNewQueue != NULL ) if( pxNewQueue != NULL )
{ {
/* Information required for priority inheritance. */ /* Information required for priority inheritance. */
@ -364,9 +397,9 @@ xQueueHandle xReturn = NULL;
/* Each mutex has a length of 1 (like a binary semaphore) and /* Each mutex has a length of 1 (like a binary semaphore) and
an item size of 0 as nothing is actually copied into or out an item size of 0 as nothing is actually copied into or out
of the mutex. */ of the mutex. */
pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U; pxNewQueue->uxMessagesWaiting = ( UBaseType_t ) 0U;
pxNewQueue->uxLength = ( unsigned portBASE_TYPE ) 1U; pxNewQueue->uxLength = ( UBaseType_t ) 1U;
pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 0U; pxNewQueue->uxItemSize = ( UBaseType_t ) 0U;
pxNewQueue->xRxLock = queueUNLOCKED; pxNewQueue->xRxLock = queueUNLOCKED;
pxNewQueue->xTxLock = queueUNLOCKED; pxNewQueue->xTxLock = queueUNLOCKED;
@ -389,7 +422,7 @@ xQueueHandle xReturn = NULL;
traceCREATE_MUTEX( pxNewQueue ); traceCREATE_MUTEX( pxNewQueue );
/* Start with the semaphore in the expected state. */ /* Start with the semaphore in the expected state. */
( void ) xQueueGenericSend( pxNewQueue, NULL, ( portTickType ) 0U, queueSEND_TO_BACK ); ( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK );
} }
else else
{ {
@ -405,20 +438,20 @@ xQueueHandle xReturn = NULL;
#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) #if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
void* xQueueGetMutexHolder( xQueueHandle xSemaphore ) void* xQueueGetMutexHolder( QueueHandle_t xSemaphore )
{ {
void *pxReturn; void *pxReturn;
/* This function is called by xSemaphoreGetMutexHolder(), and should not /* This function is called by xSemaphoreGetMutexHolder(), and should not
be called directly. Note: This is is a good way of determining if the be called directly. Note: This is a good way of determining if the
calling task is the mutex holder, but not a good way of determining the calling task is the mutex holder, but not a good way of determining the
identity of the mutex holder, as the holder may change between the identity of the mutex holder, as the holder may change between the
following critical section exiting and the function returning. */ following critical section exiting and the function returning. */
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
if( ( ( xQUEUE * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX ) if( ( ( Queue_t * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX )
{ {
pxReturn = ( void * ) ( ( xQUEUE * ) xSemaphore )->pxMutexHolder; pxReturn = ( void * ) ( ( Queue_t * ) xSemaphore )->pxMutexHolder;
} }
else else
{ {
@ -435,10 +468,10 @@ xQueueHandle xReturn = NULL;
#if ( configUSE_RECURSIVE_MUTEXES == 1 ) #if ( configUSE_RECURSIVE_MUTEXES == 1 )
portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ) BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex )
{ {
portBASE_TYPE xReturn; BaseType_t xReturn;
xQUEUE * const pxMutex = ( xQUEUE * ) xMutex; Queue_t * const pxMutex = ( Queue_t * ) xMutex;
configASSERT( pxMutex ); configASSERT( pxMutex );
@ -448,7 +481,7 @@ xQueueHandle xReturn = NULL;
this is the only condition we are interested in it does not matter if this is the only condition we are interested in it does not matter if
pxMutexHolder is accessed simultaneously by another task. Therefore no pxMutexHolder is accessed simultaneously by another task. Therefore no
mutual exclusion is required to test the pxMutexHolder variable. */ mutual exclusion is required to test the pxMutexHolder variable. */
if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Not a redundant cast as xTaskHandle is a typedef. */ if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Not a redundant cast as TaskHandle_t is a typedef. */
{ {
traceGIVE_MUTEX_RECURSIVE( pxMutex ); traceGIVE_MUTEX_RECURSIVE( pxMutex );
@ -460,12 +493,16 @@ xQueueHandle xReturn = NULL;
( pxMutex->u.uxRecursiveCallCount )--; ( pxMutex->u.uxRecursiveCallCount )--;
/* Have we unwound the call count? */ /* Have we unwound the call count? */
if( pxMutex->u.uxRecursiveCallCount == ( unsigned portBASE_TYPE ) 0 ) if( pxMutex->u.uxRecursiveCallCount == ( UBaseType_t ) 0 )
{ {
/* Return the mutex. This will automatically unblock any other /* Return the mutex. This will automatically unblock any other
task that might be waiting to access the mutex. */ task that might be waiting to access the mutex. */
( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK ); ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
xReturn = pdPASS; xReturn = pdPASS;
} }
@ -485,10 +522,10 @@ xQueueHandle xReturn = NULL;
#if ( configUSE_RECURSIVE_MUTEXES == 1 ) #if ( configUSE_RECURSIVE_MUTEXES == 1 )
portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait )
{ {
portBASE_TYPE xReturn; BaseType_t xReturn;
xQUEUE * const pxMutex = ( xQUEUE * ) xMutex; Queue_t * const pxMutex = ( Queue_t * ) xMutex;
configASSERT( pxMutex ); configASSERT( pxMutex );
@ -497,14 +534,14 @@ xQueueHandle xReturn = NULL;
traceTAKE_MUTEX_RECURSIVE( pxMutex ); traceTAKE_MUTEX_RECURSIVE( pxMutex );
if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Cast is not redundant as xTaskHandle is a typedef. */ if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */
{ {
( pxMutex->u.uxRecursiveCallCount )++; ( pxMutex->u.uxRecursiveCallCount )++;
xReturn = pdPASS; xReturn = pdPASS;
} }
else else
{ {
xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE ); xReturn = xQueueGenericReceive( pxMutex, NULL, xTicksToWait, pdFALSE );
/* pdPASS will only be returned if we successfully obtained the mutex, /* pdPASS will only be returned if we successfully obtained the mutex,
we may have blocked to reach here. */ we may have blocked to reach here. */
@ -526,15 +563,18 @@ xQueueHandle xReturn = NULL;
#if ( configUSE_COUNTING_SEMAPHORES == 1 ) #if ( configUSE_COUNTING_SEMAPHORES == 1 )
xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount )
{ {
xQueueHandle xHandle; QueueHandle_t xHandle;
xHandle = xQueueGenericCreate( uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); configASSERT( uxMaxCount != 0 );
configASSERT( uxInitialCount <= uxMaxCount );
xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
if( xHandle != NULL ) if( xHandle != NULL )
{ {
( ( xQUEUE * ) xHandle )->uxMessagesWaiting = uxInitialCount; ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;
traceCREATE_COUNTING_SEMAPHORE(); traceCREATE_COUNTING_SEMAPHORE();
} }
@ -550,15 +590,21 @@ xQueueHandle xReturn = NULL;
#endif /* configUSE_COUNTING_SEMAPHORES */ #endif /* configUSE_COUNTING_SEMAPHORES */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition )
{ {
signed portBASE_TYPE xEntryTimeSet = pdFALSE; BaseType_t xEntryTimeSet = pdFALSE;
xTimeOutType xTimeOut; TimeOut_t xTimeOut;
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; Queue_t * const pxQueue = ( Queue_t * ) xQueue;
configASSERT( pxQueue ); configASSERT( pxQueue );
configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
{
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
}
#endif
/* This function relaxes the coding standard somewhat to allow return /* This function relaxes the coding standard somewhat to allow return
statements within the function itself. This is done in the interest statements within the function itself. This is done in the interest
@ -585,7 +631,11 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
/* The queue is a member of a queue set, and posting /* The queue is a member of a queue set, and posting
to the queue set caused a higher priority task to to the queue set caused a higher priority task to
unblock. A context switch is required. */ unblock. A context switch is required. */
portYIELD_WITHIN_API(); queueYIELD_IF_USING_PREEMPTION();
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
else else
@ -600,8 +650,16 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
our own so yield immediately. Yes it is ok to our own so yield immediately. Yes it is ok to
do this from within the critical section - the do this from within the critical section - the
kernel takes care of that. */ kernel takes care of that. */
portYIELD_WITHIN_API(); queueYIELD_IF_USING_PREEMPTION();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
} }
@ -617,8 +675,16 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
our own so yield immediately. Yes it is ok to do our own so yield immediately. Yes it is ok to do
this from within the critical section - the kernel this from within the critical section - the kernel
takes care of that. */ takes care of that. */
portYIELD_WITHIN_API(); queueYIELD_IF_USING_PREEMPTION();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
#endif /* configUSE_QUEUE_SETS */ #endif /* configUSE_QUEUE_SETS */
@ -631,7 +697,7 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
} }
else else
{ {
if( xTicksToWait == ( portTickType ) 0 ) if( xTicksToWait == ( TickType_t ) 0 )
{ {
/* The queue was full and no block time is specified (or /* The queue was full and no block time is specified (or
the block time has expired) so leave now. */ the block time has expired) so leave now. */
@ -651,7 +717,8 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
} }
else else
{ {
/* Entry time was already set. */ /* Entry time was already set. */
mtCOVERAGE_TEST_MARKER();
} }
} }
} }
@ -712,14 +779,14 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
#if ( configUSE_ALTERNATIVE_API == 1 ) #if ( configUSE_ALTERNATIVE_API == 1 )
signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) BaseType_t xQueueAltGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition )
{ {
signed portBASE_TYPE xEntryTimeSet = pdFALSE; BaseType_t xEntryTimeSet = pdFALSE;
xTimeOutType xTimeOut; TimeOut_t xTimeOut;
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; Queue_t * const pxQueue = ( Queue_t * ) xQueue;
configASSERT( pxQueue ); configASSERT( pxQueue );
configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
for( ;; ) for( ;; )
{ {
@ -742,6 +809,14 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
our own so yield immediately. */ our own so yield immediately. */
portYIELD_WITHIN_API(); portYIELD_WITHIN_API();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
@ -749,7 +824,7 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
} }
else else
{ {
if( xTicksToWait == ( portTickType ) 0 ) if( xTicksToWait == ( TickType_t ) 0 )
{ {
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
return errQUEUE_FULL; return errQUEUE_FULL;
@ -773,6 +848,10 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
portYIELD_WITHIN_API(); portYIELD_WITHIN_API();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
else else
{ {
@ -790,21 +869,21 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
#if ( configUSE_ALTERNATIVE_API == 1 ) #if ( configUSE_ALTERNATIVE_API == 1 )
signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) BaseType_t xQueueAltGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking )
{ {
signed portBASE_TYPE xEntryTimeSet = pdFALSE; BaseType_t xEntryTimeSet = pdFALSE;
xTimeOutType xTimeOut; TimeOut_t xTimeOut;
signed char *pcOriginalReadPosition; int8_t *pcOriginalReadPosition;
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; Queue_t * const pxQueue = ( Queue_t * ) xQueue;
configASSERT( pxQueue ); configASSERT( pxQueue );
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
for( ;; ) for( ;; )
{ {
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
{ {
/* Remember our read position in case we are just peeking. */ /* Remember our read position in case we are just peeking. */
pcOriginalReadPosition = pxQueue->u.pcReadFrom; pcOriginalReadPosition = pxQueue->u.pcReadFrom;
@ -824,7 +903,11 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
{ {
/* Record the information required to implement /* Record the information required to implement
priority inheritance should it become necessary. */ priority inheritance should it become necessary. */
pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle(); pxQueue->pxMutexHolder = ( int8_t * ) xTaskGetCurrentTaskHandle();
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
#endif #endif
@ -835,6 +918,10 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
{ {
portYIELD_WITHIN_API(); portYIELD_WITHIN_API();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
} }
else else
@ -856,8 +943,15 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
/* The task waiting has a higher priority than this task. */ /* The task waiting has a higher priority than this task. */
portYIELD_WITHIN_API(); portYIELD_WITHIN_API();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
@ -865,7 +959,7 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
} }
else else
{ {
if( xTicksToWait == ( portTickType ) 0 ) if( xTicksToWait == ( TickType_t ) 0 )
{ {
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
traceQUEUE_RECEIVE_FAILED( pxQueue ); traceQUEUE_RECEIVE_FAILED( pxQueue );
@ -892,11 +986,15 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
{ {
if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
{ {
portENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
} }
portEXIT_CRITICAL(); taskEXIT_CRITICAL();
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
#endif #endif
@ -904,6 +1002,10 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
portYIELD_WITHIN_API(); portYIELD_WITHIN_API();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
else else
{ {
@ -920,19 +1022,19 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
#endif /* configUSE_ALTERNATIVE_API */ #endif /* configUSE_ALTERNATIVE_API */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition )
{ {
signed portBASE_TYPE xReturn; BaseType_t xReturn;
unsigned portBASE_TYPE uxSavedInterruptStatus; UBaseType_t uxSavedInterruptStatus;
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; Queue_t * const pxQueue = ( Queue_t * ) xQueue;
configASSERT( pxQueue ); configASSERT( pxQueue );
configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
/* RTOS ports that support interrupt nesting have the concept of a maximum /* RTOS ports that support interrupt nesting have the concept of a maximum
system call (or maximum API call) interrupt priority. Interrupts that are system call (or maximum API call) interrupt priority. Interrupts that are
above the maximum system call priority are keep permanently enabled, even above the maximum system call priority are kept permanently enabled, even
when the RTOS kernel is in a critical section, but cannot make any calls to when the RTOS kernel is in a critical section, but cannot make any calls to
FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
@ -946,11 +1048,11 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
/* Similar to xQueueGenericSend, except we don't block if there is no room /* Similar to xQueueGenericSend, except without blocking if there is no room
in the queue. Also we don't directly wake a task that was blocked on a in the queue. Also don't directly wake a task that was blocked on a queue
queue read, instead we return a flag to say whether a context switch is read, instead return a flag to say whether a context switch is required or
required or not (i.e. has a task with a higher priority than us been woken not (i.e. has a task with a higher priority than us been woken by this
by this post). */ post). */
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{ {
if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
@ -959,7 +1061,7 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
/* If the queue is locked we do not alter the event list. This will /* The event list is not altered if the queue is locked. This will
be done when the queue is unlocked later. */ be done when the queue is unlocked later. */
if( pxQueue->xTxLock == queueUNLOCKED ) if( pxQueue->xTxLock == queueUNLOCKED )
{ {
@ -976,6 +1078,14 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
{ {
*pxHigherPriorityTaskWoken = pdTRUE; *pxHigherPriorityTaskWoken = pdTRUE;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
else else
@ -990,7 +1100,19 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
{ {
*pxHigherPriorityTaskWoken = pdTRUE; *pxHigherPriorityTaskWoken = pdTRUE;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
} }
@ -1006,7 +1128,19 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
{ {
*pxHigherPriorityTaskWoken = pdTRUE; *pxHigherPriorityTaskWoken = pdTRUE;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
#endif /* configUSE_QUEUE_SETS */ #endif /* configUSE_QUEUE_SETS */
@ -1032,15 +1166,20 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeeking )
{ {
signed portBASE_TYPE xEntryTimeSet = pdFALSE; BaseType_t xEntryTimeSet = pdFALSE;
xTimeOutType xTimeOut; TimeOut_t xTimeOut;
signed char *pcOriginalReadPosition; int8_t *pcOriginalReadPosition;
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; Queue_t * const pxQueue = ( Queue_t * ) xQueue;
configASSERT( pxQueue ); configASSERT( pxQueue );
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
{
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
}
#endif
/* This function relaxes the coding standard somewhat to allow return /* This function relaxes the coding standard somewhat to allow return
statements within the function itself. This is done in the interest statements within the function itself. This is done in the interest
@ -1052,7 +1191,7 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
{ {
/* Is there data in the queue now? To be running we must be /* Is there data in the queue now? To be running we must be
the highest priority task wanting to access the queue. */ the highest priority task wanting to access the queue. */
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
{ {
/* Remember the read position in case the queue is only being /* Remember the read position in case the queue is only being
peeked. */ peeked. */
@ -1073,7 +1212,11 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
{ {
/* Record the information required to implement /* Record the information required to implement
priority inheritance should it become necessary. */ priority inheritance should it become necessary. */
pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle(); /*lint !e961 Cast is not redundant as xTaskHandle is a typedef. */ pxQueue->pxMutexHolder = ( int8_t * ) xTaskGetCurrentTaskHandle(); /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
#endif #endif
@ -1082,8 +1225,16 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
{ {
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
{ {
portYIELD_WITHIN_API(); queueYIELD_IF_USING_PREEMPTION();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
else else
@ -1103,8 +1254,16 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{ {
/* The task waiting has a higher priority than this task. */ /* The task waiting has a higher priority than this task. */
portYIELD_WITHIN_API(); queueYIELD_IF_USING_PREEMPTION();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
@ -1113,7 +1272,7 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
} }
else else
{ {
if( xTicksToWait == ( portTickType ) 0 ) if( xTicksToWait == ( TickType_t ) 0 )
{ {
/* The queue was empty and no block time is specified (or /* The queue was empty and no block time is specified (or
the block time has expired) so leave now. */ the block time has expired) so leave now. */
@ -1131,6 +1290,7 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
else else
{ {
/* Entry time was already set. */ /* Entry time was already set. */
mtCOVERAGE_TEST_MARKER();
} }
} }
} }
@ -1153,11 +1313,15 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
{ {
if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
{ {
portENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
} }
portEXIT_CRITICAL(); taskEXIT_CRITICAL();
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
#endif #endif
@ -1168,6 +1332,10 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
{ {
portYIELD_WITHIN_API(); portYIELD_WITHIN_API();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
else else
{ {
@ -1187,35 +1355,35 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle xQueue, const void * const pvBuffer, signed portBASE_TYPE *pxHigherPriorityTaskWoken ) BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken )
{ {
signed portBASE_TYPE xReturn; BaseType_t xReturn;
unsigned portBASE_TYPE uxSavedInterruptStatus; UBaseType_t uxSavedInterruptStatus;
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; Queue_t * const pxQueue = ( Queue_t * ) xQueue;
configASSERT( pxQueue ); configASSERT( pxQueue );
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
/* RTOS ports that support interrupt nesting have the concept of a maximum /* RTOS ports that support interrupt nesting have the concept of a maximum
system call (or maximum API call) interrupt priority. Interrupts that are system call (or maximum API call) interrupt priority. Interrupts that are
above the maximum system call priority are keep permanently enabled, even above the maximum system call priority are kept permanently enabled, even
when the RTOS kernel is in a critical section, but cannot make any calls to when the RTOS kernel is in a critical section, but cannot make any calls to
FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
failure if a FreeRTOS API function is called from an interrupt that has been failure if a FreeRTOS API function is called from an interrupt that has been
assigned a priority above the configured maximum system call priority. assigned a priority above the configured maximum system call priority.
Only FreeRTOS functions that end in FromISR can be called from interrupts Only FreeRTOS functions that end in FromISR can be called from interrupts
that have been assigned a priority at or (logically) below the maximum that have been assigned a priority at or (logically) below the maximum
system call interrupt priority. FreeRTOS maintains a separate interrupt system call interrupt priority. FreeRTOS maintains a separate interrupt
safe API to ensure interrupt entry is as fast and as simple as possible. safe API to ensure interrupt entry is as fast and as simple as possible.
More information (albeit Cortex-M specific) is provided on the following More information (albeit Cortex-M specific) is provided on the following
link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{ {
/* Cannot block in an ISR, so check there is data available. */ /* Cannot block in an ISR, so check there is data available. */
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
{ {
traceQUEUE_RECEIVE_FROM_ISR( pxQueue ); traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
@ -1238,7 +1406,19 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
{ {
*pxHigherPriorityTaskWoken = pdTRUE; *pxHigherPriorityTaskWoken = pdTRUE;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
else else
@ -1262,36 +1442,36 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const pvBuffer ) BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer )
{ {
signed portBASE_TYPE xReturn; BaseType_t xReturn;
unsigned portBASE_TYPE uxSavedInterruptStatus; UBaseType_t uxSavedInterruptStatus;
signed char *pcOriginalReadPosition; int8_t *pcOriginalReadPosition;
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; Queue_t * const pxQueue = ( Queue_t * ) xQueue;
configASSERT( pxQueue ); configASSERT( pxQueue );
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
/* RTOS ports that support interrupt nesting have the concept of a maximum /* RTOS ports that support interrupt nesting have the concept of a maximum
system call (or maximum API call) interrupt priority. Interrupts that are system call (or maximum API call) interrupt priority. Interrupts that are
above the maximum system call priority are keep permanently enabled, even above the maximum system call priority are kept permanently enabled, even
when the RTOS kernel is in a critical section, but cannot make any calls to when the RTOS kernel is in a critical section, but cannot make any calls to
FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
failure if a FreeRTOS API function is called from an interrupt that has been failure if a FreeRTOS API function is called from an interrupt that has been
assigned a priority above the configured maximum system call priority. assigned a priority above the configured maximum system call priority.
Only FreeRTOS functions that end in FromISR can be called from interrupts Only FreeRTOS functions that end in FromISR can be called from interrupts
that have been assigned a priority at or (logically) below the maximum that have been assigned a priority at or (logically) below the maximum
system call interrupt priority. FreeRTOS maintains a separate interrupt system call interrupt priority. FreeRTOS maintains a separate interrupt
safe API to ensure interrupt entry is as fast and as simple as possible. safe API to ensure interrupt entry is as fast and as simple as possible.
More information (albeit Cortex-M specific) is provided on the following More information (albeit Cortex-M specific) is provided on the following
link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{ {
/* Cannot block in an ISR, so check there is data available. */ /* Cannot block in an ISR, so check there is data available. */
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
{ {
traceQUEUE_PEEK_FROM_ISR( pxQueue ); traceQUEUE_PEEK_FROM_ISR( pxQueue );
@ -1315,35 +1495,55 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue ) UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue )
{ {
unsigned portBASE_TYPE uxReturn; UBaseType_t uxReturn;
configASSERT( xQueue ); configASSERT( xQueue );
taskENTER_CRITICAL(); taskENTER_CRITICAL();
uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting; {
uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting;
}
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
return uxReturn; return uxReturn;
} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle xQueue ) UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue )
{ {
unsigned portBASE_TYPE uxReturn; UBaseType_t uxReturn;
Queue_t *pxQueue;
configASSERT( xQueue ); pxQueue = ( Queue_t * ) xQueue;
configASSERT( pxQueue );
uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting; taskENTER_CRITICAL();
{
uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting;
}
taskEXIT_CRITICAL();
return uxReturn; return uxReturn;
} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vQueueDelete( xQueueHandle xQueue ) UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue )
{ {
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; UBaseType_t uxReturn;
configASSERT( xQueue );
uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting;
return uxReturn;
} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
/*-----------------------------------------------------------*/
void vQueueDelete( QueueHandle_t xQueue )
{
Queue_t * const pxQueue = ( Queue_t * ) xQueue;
configASSERT( pxQueue ); configASSERT( pxQueue );
@ -1353,16 +1553,19 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
vQueueUnregisterQueue( pxQueue ); vQueueUnregisterQueue( pxQueue );
} }
#endif #endif
vPortFree( pxQueue->pcHead ); if( pxQueue->pcHead != NULL )
{
vPortFree( pxQueue->pcHead );
}
vPortFree( pxQueue ); vPortFree( pxQueue );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
unsigned char ucQueueGetQueueNumber( xQueueHandle xQueue ) UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue )
{ {
return ( ( xQUEUE * ) xQueue )->ucQueueNumber; return ( ( Queue_t * ) xQueue )->uxQueueNumber;
} }
#endif /* configUSE_TRACE_FACILITY */ #endif /* configUSE_TRACE_FACILITY */
@ -1370,9 +1573,9 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
void vQueueSetQueueNumber( xQueueHandle xQueue, unsigned char ucQueueNumber ) void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber )
{ {
( ( xQUEUE * ) xQueue )->ucQueueNumber = ucQueueNumber; ( ( Queue_t * ) xQueue )->uxQueueNumber = uxQueueNumber;
} }
#endif /* configUSE_TRACE_FACILITY */ #endif /* configUSE_TRACE_FACILITY */
@ -1380,17 +1583,17 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
unsigned char ucQueueGetQueueType( xQueueHandle xQueue ) uint8_t ucQueueGetQueueType( QueueHandle_t xQueue )
{ {
return ( ( xQUEUE * ) xQueue )->ucQueueType; return ( ( Queue_t * ) xQueue )->ucQueueType;
} }
#endif /* configUSE_TRACE_FACILITY */ #endif /* configUSE_TRACE_FACILITY */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) static void prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition )
{ {
if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 ) if( pxQueue->uxItemSize == ( UBaseType_t ) 0 )
{ {
#if ( configUSE_MUTEXES == 1 ) #if ( configUSE_MUTEXES == 1 )
{ {
@ -1400,6 +1603,10 @@ static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, port
vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder ); vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
pxQueue->pxMutexHolder = NULL; pxQueue->pxMutexHolder = NULL;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
#endif /* configUSE_MUTEXES */ #endif /* configUSE_MUTEXES */
} }
@ -1411,6 +1618,10 @@ static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, port
{ {
pxQueue->pcWriteTo = pxQueue->pcHead; pxQueue->pcWriteTo = pxQueue->pcHead;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
else else
{ {
@ -1420,10 +1631,14 @@ static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, port
{ {
pxQueue->u.pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize ); pxQueue->u.pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
if( xPosition == queueOVERWRITE ) if( xPosition == queueOVERWRITE )
{ {
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
{ {
/* An item is not being added but overwritten, so subtract /* An item is not being added but overwritten, so subtract
one from the recorded number of items in the queue so when one from the recorded number of items in the queue so when
@ -1431,6 +1646,14 @@ static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, port
correct. */ correct. */
--( pxQueue->uxMessagesWaiting ); --( pxQueue->uxMessagesWaiting );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
@ -1438,7 +1661,7 @@ static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, port
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void * const pvBuffer ) static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer )
{ {
if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX ) if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
{ {
@ -1447,12 +1670,20 @@ static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void * const pvB
{ {
pxQueue->u.pcReadFrom = pxQueue->pcHead; pxQueue->u.pcReadFrom = pxQueue->pcHead;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. */ ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. */
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvUnlockQueue( xQUEUE *pxQueue ) static void prvUnlockQueue( Queue_t * const pxQueue )
{ {
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */ /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
@ -1478,6 +1709,10 @@ static void prvUnlockQueue( xQUEUE *pxQueue )
A context switch is required. */ A context switch is required. */
vTaskMissedYield(); vTaskMissedYield();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
else else
{ {
@ -1491,6 +1726,10 @@ static void prvUnlockQueue( xQUEUE *pxQueue )
context switch is required. */ context switch is required. */
vTaskMissedYield(); vTaskMissedYield();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
else else
{ {
@ -1510,6 +1749,10 @@ static void prvUnlockQueue( xQUEUE *pxQueue )
context switch is required. */ context switch is required. */
vTaskMissedYield(); vTaskMissedYield();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
else else
{ {
@ -1536,6 +1779,10 @@ static void prvUnlockQueue( xQUEUE *pxQueue )
{ {
vTaskMissedYield(); vTaskMissedYield();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
--( pxQueue->xRxLock ); --( pxQueue->xRxLock );
} }
@ -1551,13 +1798,13 @@ static void prvUnlockQueue( xQUEUE *pxQueue )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue ) static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue )
{ {
signed portBASE_TYPE xReturn; BaseType_t xReturn;
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ) if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 )
{ {
xReturn = pdTRUE; xReturn = pdTRUE;
} }
@ -1572,12 +1819,12 @@ signed portBASE_TYPE xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle xQueue ) BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue )
{ {
signed portBASE_TYPE xReturn; BaseType_t xReturn;
configASSERT( xQueue ); configASSERT( xQueue );
if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ) if( ( ( Queue_t * ) xQueue )->uxMessagesWaiting == ( UBaseType_t ) 0 )
{ {
xReturn = pdTRUE; xReturn = pdTRUE;
} }
@ -1590,9 +1837,9 @@ signed portBASE_TYPE xReturn;
} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue ) static BaseType_t prvIsQueueFull( const Queue_t *pxQueue )
{ {
signed portBASE_TYPE xReturn; BaseType_t xReturn;
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
@ -1611,12 +1858,12 @@ signed portBASE_TYPE xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle xQueue ) BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue )
{ {
signed portBASE_TYPE xReturn; BaseType_t xReturn;
configASSERT( xQueue ); configASSERT( xQueue );
if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( ( xQUEUE * ) xQueue )->uxLength ) if( ( ( Queue_t * ) xQueue )->uxMessagesWaiting == ( ( Queue_t * ) xQueue )->uxLength )
{ {
xReturn = pdTRUE; xReturn = pdTRUE;
} }
@ -1631,10 +1878,10 @@ signed portBASE_TYPE xReturn;
#if ( configUSE_CO_ROUTINES == 1 ) #if ( configUSE_CO_ROUTINES == 1 )
signed portBASE_TYPE xQueueCRSend( xQueueHandle xQueue, const void *pvItemToQueue, portTickType xTicksToWait ) BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait )
{ {
signed portBASE_TYPE xReturn; BaseType_t xReturn;
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; Queue_t * const pxQueue = ( Queue_t * ) xQueue;
/* If the queue is already full we may have to block. A critical section /* If the queue is already full we may have to block. A critical section
is required to prevent an interrupt removing something from the queue is required to prevent an interrupt removing something from the queue
@ -1645,7 +1892,7 @@ signed portBASE_TYPE xReturn;
{ {
/* The queue is full - do we want to block or just leave without /* The queue is full - do we want to block or just leave without
posting? */ posting? */
if( xTicksToWait > ( portTickType ) 0 ) if( xTicksToWait > ( TickType_t ) 0 )
{ {
/* As this is called from a coroutine we cannot block directly, but /* As this is called from a coroutine we cannot block directly, but
return indicating that we need to block. */ return indicating that we need to block. */
@ -1683,6 +1930,14 @@ signed portBASE_TYPE xReturn;
that a yield might be appropriate. */ that a yield might be appropriate. */
xReturn = errQUEUE_YIELD; xReturn = errQUEUE_YIELD;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
else else
@ -1700,21 +1955,21 @@ signed portBASE_TYPE xReturn;
#if ( configUSE_CO_ROUTINES == 1 ) #if ( configUSE_CO_ROUTINES == 1 )
signed portBASE_TYPE xQueueCRReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait ) BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait )
{ {
signed portBASE_TYPE xReturn; BaseType_t xReturn;
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; Queue_t * const pxQueue = ( Queue_t * ) xQueue;
/* If the queue is already empty we may have to block. A critical section /* If the queue is already empty we may have to block. A critical section
is required to prevent an interrupt adding something to the queue is required to prevent an interrupt adding something to the queue
between the check to see if the queue is empty and blocking on the queue. */ between the check to see if the queue is empty and blocking on the queue. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
{ {
if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ) if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 )
{ {
/* There are no messages in the queue, do we want to block or just /* There are no messages in the queue, do we want to block or just
leave with nothing? */ leave with nothing? */
if( xTicksToWait > ( portTickType ) 0 ) if( xTicksToWait > ( TickType_t ) 0 )
{ {
/* As this is a co-routine we cannot block directly, but return /* As this is a co-routine we cannot block directly, but return
indicating that we need to block. */ indicating that we need to block. */
@ -1728,12 +1983,16 @@ signed portBASE_TYPE xReturn;
return errQUEUE_FULL; return errQUEUE_FULL;
} }
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
{ {
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
{ {
/* Data is available from the queue. */ /* Data is available from the queue. */
pxQueue->u.pcReadFrom += pxQueue->uxItemSize; pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
@ -1741,6 +2000,10 @@ signed portBASE_TYPE xReturn;
{ {
pxQueue->u.pcReadFrom = pxQueue->pcHead; pxQueue->u.pcReadFrom = pxQueue->pcHead;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
--( pxQueue->uxMessagesWaiting ); --( pxQueue->uxMessagesWaiting );
( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
@ -1757,6 +2020,14 @@ signed portBASE_TYPE xReturn;
{ {
xReturn = errQUEUE_YIELD; xReturn = errQUEUE_YIELD;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
else else
@ -1774,9 +2045,9 @@ signed portBASE_TYPE xReturn;
#if ( configUSE_CO_ROUTINES == 1 ) #if ( configUSE_CO_ROUTINES == 1 )
signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken )
{ {
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; Queue_t * const pxQueue = ( Queue_t * ) xQueue;
/* Cannot block within an ISR so if there is no space on the queue then /* Cannot block within an ISR so if there is no space on the queue then
exit without doing anything. */ exit without doing anything. */
@ -1794,8 +2065,24 @@ signed portBASE_TYPE xReturn;
{ {
return pdTRUE; return pdTRUE;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
return xCoRoutinePreviouslyWoken; return xCoRoutinePreviouslyWoken;
@ -1806,14 +2093,14 @@ signed portBASE_TYPE xReturn;
#if ( configUSE_CO_ROUTINES == 1 ) #if ( configUSE_CO_ROUTINES == 1 )
signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle xQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken ) BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxCoRoutineWoken )
{ {
signed portBASE_TYPE xReturn; BaseType_t xReturn;
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; Queue_t * const pxQueue = ( Queue_t * ) xQueue;
/* We cannot block from an ISR, so check there is data available. If /* We cannot block from an ISR, so check there is data available. If
not then just leave without doing anything. */ not then just leave without doing anything. */
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
{ {
/* Copy the data from the queue. */ /* Copy the data from the queue. */
pxQueue->u.pcReadFrom += pxQueue->uxItemSize; pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
@ -1821,6 +2108,10 @@ signed portBASE_TYPE xReturn;
{ {
pxQueue->u.pcReadFrom = pxQueue->pcHead; pxQueue->u.pcReadFrom = pxQueue->pcHead;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
--( pxQueue->uxMessagesWaiting ); --( pxQueue->uxMessagesWaiting );
( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
@ -1832,7 +2123,19 @@ signed portBASE_TYPE xReturn;
{ {
*pxCoRoutineWoken = pdTRUE; *pxCoRoutineWoken = pdTRUE;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
xReturn = pdPASS; xReturn = pdPASS;
@ -1850,21 +2153,27 @@ signed portBASE_TYPE xReturn;
#if ( configQUEUE_REGISTRY_SIZE > 0 ) #if ( configQUEUE_REGISTRY_SIZE > 0 )
void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName ) void vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcQueueName ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
{ {
unsigned portBASE_TYPE ux; UBaseType_t ux;
/* See if there is an empty space in the registry. A NULL name denotes /* See if there is an empty space in the registry. A NULL name denotes
a free slot. */ a free slot. */
for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ ) for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ )
{ {
if( xQueueRegistry[ ux ].pcQueueName == NULL ) if( xQueueRegistry[ ux ].pcQueueName == NULL )
{ {
/* Store the information on this queue. */ /* Store the information on this queue. */
xQueueRegistry[ ux ].pcQueueName = pcQueueName; xQueueRegistry[ ux ].pcQueueName = pcQueueName;
xQueueRegistry[ ux ].xHandle = xQueue; xQueueRegistry[ ux ].xHandle = xQueue;
traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName );
break; break;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
} }
@ -1873,13 +2182,13 @@ signed portBASE_TYPE xReturn;
#if ( configQUEUE_REGISTRY_SIZE > 0 ) #if ( configQUEUE_REGISTRY_SIZE > 0 )
void vQueueUnregisterQueue( xQueueHandle xQueue ) void vQueueUnregisterQueue( QueueHandle_t xQueue )
{ {
unsigned portBASE_TYPE ux; UBaseType_t ux;
/* See if the handle of the queue being unregistered in actually in the /* See if the handle of the queue being unregistered in actually in the
registry. */ registry. */
for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ ) for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ )
{ {
if( xQueueRegistry[ ux ].xHandle == xQueue ) if( xQueueRegistry[ ux ].xHandle == xQueue )
{ {
@ -1887,6 +2196,10 @@ signed portBASE_TYPE xReturn;
xQueueRegistry[ ux ].pcQueueName = NULL; xQueueRegistry[ ux ].pcQueueName = NULL;
break; break;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
@ -1896,9 +2209,9 @@ signed portBASE_TYPE xReturn;
#if ( configUSE_TIMERS == 1 ) #if ( configUSE_TIMERS == 1 )
void vQueueWaitForMessageRestricted( xQueueHandle xQueue, portTickType xTicksToWait ) void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait )
{ {
xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; Queue_t * const pxQueue = ( Queue_t * ) xQueue;
/* This function should not be called by application code hence the /* This function should not be called by application code hence the
'Restricted' in its name. It is not part of the public API. It is 'Restricted' in its name. It is not part of the public API. It is
@ -1915,11 +2228,15 @@ signed portBASE_TYPE xReturn;
the queue is locked, and the calling task blocks on the queue, then the the queue is locked, and the calling task blocks on the queue, then the
calling task will be immediately unblocked when the queue is unlocked. */ calling task will be immediately unblocked when the queue is unlocked. */
prvLockQueue( pxQueue ); prvLockQueue( pxQueue );
if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U ) if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0U )
{ {
/* There is nothing in the queue, block for the specified period. */ /* There is nothing in the queue, block for the specified period. */
vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
prvUnlockQueue( pxQueue ); prvUnlockQueue( pxQueue );
} }
@ -1928,11 +2245,11 @@ signed portBASE_TYPE xReturn;
#if ( configUSE_QUEUE_SETS == 1 ) #if ( configUSE_QUEUE_SETS == 1 )
xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength ) QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength )
{ {
xQueueSetHandle pxQueue; QueueSetHandle_t pxQueue;
pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( xQUEUE * ), queueQUEUE_TYPE_SET ); pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( Queue_t * ), queueQUEUE_TYPE_SET );
return pxQueue; return pxQueue;
} }
@ -1942,30 +2259,30 @@ signed portBASE_TYPE xReturn;
#if ( configUSE_QUEUE_SETS == 1 ) #if ( configUSE_QUEUE_SETS == 1 )
portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet ) BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet )
{ {
portBASE_TYPE xReturn; BaseType_t xReturn;
if( ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) taskENTER_CRITICAL();
{ {
/* Cannot add a queue/semaphore to more than one queue set. */ if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )
xReturn = pdFAIL;
}
else if( ( ( xQUEUE * ) xQueueOrSemaphore )->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 )
{
/* Cannot add a queue/semaphore to a queue set if there are already
items in the queue/semaphore. */
xReturn = pdFAIL;
}
else
{
taskENTER_CRITICAL();
{ {
( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet; /* Cannot add a queue/semaphore to more than one queue set. */
xReturn = pdFAIL;
}
else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting != ( UBaseType_t ) 0 )
{
/* Cannot add a queue/semaphore to a queue set if there are already
items in the queue/semaphore. */
xReturn = pdFAIL;
}
else
{
( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet;
xReturn = pdPASS;
} }
taskEXIT_CRITICAL();
xReturn = pdPASS;
} }
taskEXIT_CRITICAL();
return xReturn; return xReturn;
} }
@ -1975,17 +2292,17 @@ signed portBASE_TYPE xReturn;
#if ( configUSE_QUEUE_SETS == 1 ) #if ( configUSE_QUEUE_SETS == 1 )
portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet ) BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet )
{ {
portBASE_TYPE xReturn; BaseType_t xReturn;
xQUEUE * const pxQueueOrSemaphore = ( xQUEUE * ) xQueueOrSemaphore; Queue_t * const pxQueueOrSemaphore = ( Queue_t * ) xQueueOrSemaphore;
if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet ) if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet )
{ {
/* The queue was not a member of the set. */ /* The queue was not a member of the set. */
xReturn = pdFAIL; xReturn = pdFAIL;
} }
else if( pxQueueOrSemaphore->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 ) else if( pxQueueOrSemaphore->uxMessagesWaiting != ( UBaseType_t ) 0 )
{ {
/* It is dangerous to remove a queue from a set when the queue is /* It is dangerous to remove a queue from a set when the queue is
not empty because the queue set will still hold pending events for not empty because the queue set will still hold pending events for
@ -2011,11 +2328,11 @@ signed portBASE_TYPE xReturn;
#if ( configUSE_QUEUE_SETS == 1 ) #if ( configUSE_QUEUE_SETS == 1 )
xQueueSetMemberHandle xQueueSelectFromSet( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks ) QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t const xTicksToWait )
{ {
xQueueSetMemberHandle xReturn = NULL; QueueSetMemberHandle_t xReturn = NULL;
( void ) xQueueGenericReceive( ( xQueueHandle ) xQueueSet, &xReturn, xBlockTimeTicks, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */ ( void ) xQueueGenericReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */
return xReturn; return xReturn;
} }
@ -2024,11 +2341,11 @@ signed portBASE_TYPE xReturn;
#if ( configUSE_QUEUE_SETS == 1 ) #if ( configUSE_QUEUE_SETS == 1 )
xQueueSetMemberHandle xQueueSelectFromSetFromISR( xQueueSetHandle xQueueSet ) QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet )
{ {
xQueueSetMemberHandle xReturn = NULL; QueueSetMemberHandle_t xReturn = NULL;
( void ) xQueueReceiveFromISR( ( xQueueHandle ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */ ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */
return xReturn; return xReturn;
} }
@ -2037,10 +2354,12 @@ signed portBASE_TYPE xReturn;
#if ( configUSE_QUEUE_SETS == 1 ) #if ( configUSE_QUEUE_SETS == 1 )
static portBASE_TYPE prvNotifyQueueSetContainer( const xQUEUE * const pxQueue, portBASE_TYPE xCopyPosition ) static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition )
{ {
xQUEUE *pxQueueSetContainer = pxQueue->pxQueueSetContainer; Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer;
portBASE_TYPE xReturn = pdFALSE; BaseType_t xReturn = pdFALSE;
/* This function must be called form a critical section. */
configASSERT( pxQueueSetContainer ); configASSERT( pxQueueSetContainer );
configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ); configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );
@ -2057,7 +2376,19 @@ signed portBASE_TYPE xReturn;
/* The task waiting has a higher priority */ /* The task waiting has a higher priority */
xReturn = pdTRUE; xReturn = pdTRUE;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
return xReturn; return xReturn;
@ -2065,3 +2396,14 @@ signed portBASE_TYPE xReturn;
#endif /* configUSE_QUEUE_SETS */ #endif /* configUSE_QUEUE_SETS */

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -89,7 +90,7 @@ privileged Vs unprivileged linkage and placement. */
uxTaskGetSystemState() function. Note the formatting functions are provided uxTaskGetSystemState() function. Note the formatting functions are provided
for convenience only, and are NOT considered part of the kernel. */ for convenience only, and are NOT considered part of the kernel. */
#include <stdio.h> #include <stdio.h>
#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) */ #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
/* Sanity check the configuration. */ /* Sanity check the configuration. */
#if configUSE_TICKLESS_IDLE != 0 #if configUSE_TICKLESS_IDLE != 0
@ -103,6 +104,14 @@ privileged Vs unprivileged linkage and placement. */
*/ */
#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE #define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE
#if( configUSE_PREEMPTION == 0 )
/* If the cooperative scheduler is being used then a yield should not be
performed just because a higher priority task has been woken. */
#define taskYIELD_IF_USING_PREEMPTION()
#else
#define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
#endif
/* /*
* Task control block. A task control block (TCB) is allocated for each task, * Task control block. A task control block (TCB) is allocated for each task,
* and stores task state information, including a pointer to the task's context * and stores task state information, including a pointer to the task's context
@ -110,41 +119,41 @@ privileged Vs unprivileged linkage and placement. */
*/ */
typedef struct tskTaskControlBlock typedef struct tskTaskControlBlock
{ {
volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */ volatile StackType_t *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
#if ( portUSING_MPU_WRAPPERS == 1 ) #if ( portUSING_MPU_WRAPPERS == 1 )
xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */ xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
#endif #endif
xListItem xGenericListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */ ListItem_t xGenericListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
xListItem xEventListItem; /*< Used to reference a task from an event list. */ ListItem_t xEventListItem; /*< Used to reference a task from an event list. */
unsigned portBASE_TYPE uxPriority; /*< The priority of the task. 0 is the lowest priority. */ UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */
portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */ StackType_t *pxStack; /*< Points to the start of the stack. */
signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
#if ( portSTACK_GROWTH > 0 ) #if ( portSTACK_GROWTH > 0 )
portSTACK_TYPE *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */ StackType_t *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */
#endif #endif
#if ( portCRITICAL_NESTING_IN_TCB == 1 ) #if ( portCRITICAL_NESTING_IN_TCB == 1 )
unsigned portBASE_TYPE uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */ UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
#endif #endif
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
unsigned portBASE_TYPE uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */ UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */
unsigned portBASE_TYPE uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */ UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
#endif #endif
#if ( configUSE_MUTEXES == 1 ) #if ( configUSE_MUTEXES == 1 )
unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
#endif #endif
#if ( configUSE_APPLICATION_TASK_TAG == 1 ) #if ( configUSE_APPLICATION_TASK_TAG == 1 )
pdTASK_HOOK_CODE pxTaskTag; TaskHookFunction_t pxTaskTag;
#endif #endif
#if ( configGENERATE_RUN_TIME_STATS == 1 ) #if ( configGENERATE_RUN_TIME_STATS == 1 )
unsigned long ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */ uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
#endif #endif
#if ( configUSE_NEWLIB_REENTRANT == 1 ) #if ( configUSE_NEWLIB_REENTRANT == 1 )
@ -155,11 +164,14 @@ typedef struct tskTaskControlBlock
newlib and must provide system-wide implementations of the necessary newlib and must provide system-wide implementations of the necessary
stubs. Be warned that (at the time of writing) the current newlib design stubs. Be warned that (at the time of writing) the current newlib design
implements a system-wide malloc() that must be provided with locks. */ implements a system-wide malloc() that must be provided with locks. */
struct _reent xNewLib_reent; struct _reent xNewLib_reent;
#endif #endif
} tskTCB; } tskTCB;
/* The old tskTCB name is maintained above then typedefed to the new TCB_t name
below to enable the use of older kernel aware debuggers. */
typedef tskTCB TCB_t;
/* /*
* Some kernel aware debuggers require the data the debugger needs access to to * Some kernel aware debuggers require the data the debugger needs access to to
@ -172,51 +184,60 @@ typedef struct tskTaskControlBlock
/*lint -e956 A manual analysis and inspection has been used to determine which /*lint -e956 A manual analysis and inspection has been used to determine which
static variables must be declared volatile. */ static variables must be declared volatile. */
PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL; PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
/* Lists for ready and blocked tasks. --------------------*/ /* Lists for ready and blocked tasks. --------------------*/
PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */ PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */
PRIVILEGED_DATA static xList xDelayedTaskList1; /*< Delayed tasks. */ PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */
PRIVILEGED_DATA static xList xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
PRIVILEGED_DATA static xList * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */ PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */
PRIVILEGED_DATA static xList * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */ PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */
PRIVILEGED_DATA static xList xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */ PRIVILEGED_DATA static List_t xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */
#if ( INCLUDE_vTaskDelete == 1 ) #if ( INCLUDE_vTaskDelete == 1 )
PRIVILEGED_DATA static xList xTasksWaitingTermination; /*< Tasks that have been deleted - but the their memory not yet freed. */ PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */
PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTasksDeleted = ( unsigned portBASE_TYPE ) 0U; PRIVILEGED_DATA static volatile UBaseType_t uxTasksDeleted = ( UBaseType_t ) 0U;
#endif #endif
#if ( INCLUDE_vTaskSuspend == 1 ) #if ( INCLUDE_vTaskSuspend == 1 )
PRIVILEGED_DATA static xList xSuspendedTaskList; /*< Tasks that are currently suspended. */ PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */
#endif #endif
#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
PRIVILEGED_DATA static xTaskHandle xIdleTaskHandle = NULL; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */ PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle = NULL; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */
#endif #endif
/* Other file private variables. --------------------------------*/ /* Other file private variables. --------------------------------*/
PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0U; PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
PRIVILEGED_DATA static volatile portTickType xTickCount = ( portTickType ) 0U; PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U;
PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTopReadyPriority = tskIDLE_PRIORITY; PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
PRIVILEGED_DATA static volatile signed portBASE_TYPE xSchedulerRunning = pdFALSE; PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended = ( unsigned portBASE_TYPE ) pdFALSE; PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U;
PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxPendedTicks = ( unsigned portBASE_TYPE ) 0U; PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE;
PRIVILEGED_DATA static volatile portBASE_TYPE xYieldPending = pdFALSE; PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0; PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0U; PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = portMAX_DELAY;
PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = portMAX_DELAY;
/* Context switches are held pending while the scheduler is suspended. Also,
interrupts must not manipulate the xStateListItem of a TCB, or any of the
lists the xStateListItem can be referenced from, if the scheduler is suspended.
If an interrupt needs to unblock a task while the scheduler is suspended then it
moves the task's event list item into the xPendingReadyList, ready for the
kernel to move the task from the pending ready list into the real ready list
when the scheduler is unsuspended. The pending ready list itself can only be
accessed from a critical section. */
PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE;
#if ( configGENERATE_RUN_TIME_STATS == 1 ) #if ( configGENERATE_RUN_TIME_STATS == 1 )
PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */ PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
PRIVILEGED_DATA static unsigned long ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */ PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */
#endif #endif
@ -233,10 +254,10 @@ PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = portMAX_D
/* /*
* Macros used by vListTask to indicate which state a task is in. * Macros used by vListTask to indicate which state a task is in.
*/ */
#define tskBLOCKED_CHAR ( ( signed char ) 'B' ) #define tskBLOCKED_CHAR ( 'B' )
#define tskREADY_CHAR ( ( signed char ) 'R' ) #define tskREADY_CHAR ( 'R' )
#define tskDELETED_CHAR ( ( signed char ) 'D' ) #define tskDELETED_CHAR ( 'D' )
#define tskSUSPENDED_CHAR ( ( signed char ) 'S' ) #define tskSUSPENDED_CHAR ( 'S' )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -248,28 +269,28 @@ PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = portMAX_D
/* uxTopReadyPriority holds the priority of the highest priority ready /* uxTopReadyPriority holds the priority of the highest priority ready
state task. */ state task. */
#define taskRECORD_READY_PRIORITY( uxPriority ) \ #define taskRECORD_READY_PRIORITY( uxPriority ) \
{ \ { \
if( ( uxPriority ) > uxTopReadyPriority ) \ if( ( uxPriority ) > uxTopReadyPriority ) \
{ \ { \
uxTopReadyPriority = ( uxPriority ); \ uxTopReadyPriority = ( uxPriority ); \
} \ } \
} /* taskRECORD_READY_PRIORITY */ } /* taskRECORD_READY_PRIORITY */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define taskSELECT_HIGHEST_PRIORITY_TASK() \ #define taskSELECT_HIGHEST_PRIORITY_TASK() \
{ \ { \
/* Find the highest priority queue that contains ready tasks. */ \ /* Find the highest priority queue that contains ready tasks. */ \
while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) \ while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) \
{ \ { \
configASSERT( uxTopReadyPriority ); \ configASSERT( uxTopReadyPriority ); \
--uxTopReadyPriority; \ --uxTopReadyPriority; \
} \ } \
\ \
/* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \ /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
the same priority get an equal share of the processor time. */ \ the same priority get an equal share of the processor time. */ \
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \ listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \
} /* taskSELECT_HIGHEST_PRIORITY_TASK */ } /* taskSELECT_HIGHEST_PRIORITY_TASK */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -293,7 +314,7 @@ PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = portMAX_D
#define taskSELECT_HIGHEST_PRIORITY_TASK() \ #define taskSELECT_HIGHEST_PRIORITY_TASK() \
{ \ { \
unsigned portBASE_TYPE uxTopPriority; \ UBaseType_t uxTopPriority; \
\ \
/* Find the highest priority queue that contains ready tasks. */ \ /* Find the highest priority queue that contains ready tasks. */ \
portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \ portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
@ -322,7 +343,7 @@ PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = portMAX_D
count overflows. */ count overflows. */
#define taskSWITCH_DELAYED_LISTS() \ #define taskSWITCH_DELAYED_LISTS() \
{ \ { \
xList *pxTemp; \ List_t *pxTemp; \
\ \
/* The delayed tasks list should be empty when the lists are switched. */ \ /* The delayed tasks list should be empty when the lists are switched. */ \
configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \ configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \
@ -331,25 +352,7 @@ count overflows. */
pxDelayedTaskList = pxOverflowDelayedTaskList; \ pxDelayedTaskList = pxOverflowDelayedTaskList; \
pxOverflowDelayedTaskList = pxTemp; \ pxOverflowDelayedTaskList = pxTemp; \
xNumOfOverflows++; \ xNumOfOverflows++; \
\ prvResetNextTaskUnblockTime(); \
if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) \
{ \
/* The new current delayed list is empty. Set \
xNextTaskUnblockTime to the maximum possible value so it is \
extremely unlikely that the \
if( xTickCount >= xNextTaskUnblockTime ) test will pass until \
there is an item in the delayed list. */ \
xNextTaskUnblockTime = portMAX_DELAY; \
} \
else \
{ \
/* The new current delayed list is not empty, get the value of \
the item at the head of the delayed list. This is the time at \
which the task at the head of the delayed list should be removed \
from the Blocked state. */ \
pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); \
xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ); \
} \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -358,23 +361,42 @@ count overflows. */
* Place the task represented by pxTCB into the appropriate ready list for * Place the task represented by pxTCB into the appropriate ready list for
* the task. It is inserted at the end of the list. * the task. It is inserted at the end of the list.
*/ */
#define prvAddTaskToReadyList( pxTCB ) \ #define prvAddTaskToReadyList( pxTCB ) \
traceMOVED_TASK_TO_READY_STATE( pxTCB ) \ traceMOVED_TASK_TO_READY_STATE( pxTCB ) \
taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \ taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) ) vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* Several functions take an xTaskHandle parameter that can optionally be NULL, * Several functions take an TaskHandle_t parameter that can optionally be NULL,
* where NULL is used to indicate that the handle of the currently executing * where NULL is used to indicate that the handle of the currently executing
* task should be used in place of the parameter. This macro simply checks to * task should be used in place of the parameter. This macro simply checks to
* see if the parameter is NULL and returns a pointer to the appropriate TCB. * see if the parameter is NULL and returns a pointer to the appropriate TCB.
*/ */
#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( tskTCB * ) pxCurrentTCB : ( tskTCB * ) ( pxHandle ) ) #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TCB_t * ) pxCurrentTCB : ( TCB_t * ) ( pxHandle ) )
/* The item value of the event list item is normally used to hold the priority
of the task to which it belongs (coded to allow it to be held in reverse
priority order). However, it is occasionally borrowed for other purposes. It
is important its value is not updated due to a task priority change while it is
being used for another purpose. The following bit definition is used to inform
the scheduler that the value should not be changed - in which case it is the
responsibility of whichever module is using the value to ensure it gets set back
to its original value when it is released. */
#if configUSE_16_BIT_TICKS == 1
#define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U
#else
#define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL
#endif
/* Callback function prototypes. --------------------------*/ /* Callback function prototypes. --------------------------*/
extern void vApplicationStackOverflowHook( xTaskHandle xTask, signed char *pcTaskName ); #if configCHECK_FOR_STACK_OVERFLOW > 0
extern void vApplicationTickHook( void ); extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName );
#endif
#if configUSE_TICK_HOOK > 0
extern void vApplicationTickHook( void );
#endif
/* File private functions. --------------------------------*/ /* File private functions. --------------------------------*/
@ -382,7 +404,14 @@ extern void vApplicationTickHook( void );
* Utility to ready a TCB for a given task. Mainly just copies the parameters * Utility to ready a TCB for a given task. Mainly just copies the parameters
* into the TCB structure. * into the TCB structure.
*/ */
static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) PRIVILEGED_FUNCTION; static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
/**
* Utility task that simply returns pdTRUE if the task referenced by xTask is
* currently in the Suspended state, or pdFALSE if the task referenced by xTask
* is in any other state.
*/
static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
/* /*
* 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
@ -412,7 +441,7 @@ static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
*/ */
#if ( INCLUDE_vTaskDelete == 1 ) #if ( INCLUDE_vTaskDelete == 1 )
static void prvDeleteTCB( tskTCB *pxTCB ) PRIVILEGED_FUNCTION; static void prvDeleteTCB( TCB_t *pxTCB ) PRIVILEGED_FUNCTION;
#endif #endif
@ -427,16 +456,16 @@ static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
* The currently executing task is entering the Blocked state. Add the task to * The currently executing task is entering the Blocked state. Add the task to
* either the current or the overflow delayed task list. * either the current or the overflow delayed task list.
*/ */
static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake ) PRIVILEGED_FUNCTION; static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake ) PRIVILEGED_FUNCTION;
/* /*
* Allocates memory from the heap for a TCB and associated stack. Checks the * Allocates memory from the heap for a TCB and associated stack. Checks the
* allocation was successful. * allocation was successful.
*/ */
static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) PRIVILEGED_FUNCTION; static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer ) PRIVILEGED_FUNCTION;
/* /*
* Fills an xTaskStatusType structure with information on each task that is * Fills an TaskStatus_t structure with information on each task that is
* referenced from the pxList list (which may be a ready list, a delayed list, * referenced from the pxList list (which may be a ready list, a delayed list,
* a suspended list, etc.). * a suspended list, etc.).
* *
@ -445,7 +474,7 @@ static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TY
*/ */
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
static unsigned portBASE_TYPE prvListTaskWithinSingleList( xTaskStatusType *pxTaskStatusArray, xList *pxList, eTaskState eState ) PRIVILEGED_FUNCTION; static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;
#endif #endif
@ -456,7 +485,7 @@ static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TY
*/ */
#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
static unsigned short prvTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) PRIVILEGED_FUNCTION; static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
#endif #endif
@ -471,14 +500,22 @@ static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TY
*/ */
#if ( configUSE_TICKLESS_IDLE != 0 ) #if ( configUSE_TICKLESS_IDLE != 0 )
static portTickType prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION; static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
#endif #endif
signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) /*
* Set xNextTaskUnblockTime to the time at which the next Blocked state task
* will exit the Blocked state.
*/
static void prvResetNextTaskUnblockTime( void );
/*-----------------------------------------------------------*/
BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
{ {
signed portBASE_TYPE xReturn; BaseType_t xReturn;
tskTCB * pxNewTCB; TCB_t * pxNewTCB;
configASSERT( pxTaskCode ); configASSERT( pxTaskCode );
configASSERT( ( ( uxPriority & ( ~portPRIVILEGE_BIT ) ) < configMAX_PRIORITIES ) ); configASSERT( ( ( uxPriority & ( ~portPRIVILEGE_BIT ) ) < configMAX_PRIORITIES ) );
@ -489,11 +526,11 @@ tskTCB * pxNewTCB;
if( pxNewTCB != NULL ) if( pxNewTCB != NULL )
{ {
portSTACK_TYPE *pxTopOfStack; StackType_t *pxTopOfStack;
#if( portUSING_MPU_WRAPPERS == 1 ) #if( portUSING_MPU_WRAPPERS == 1 )
/* Should the task be created in privileged mode? */ /* Should the task be created in privileged mode? */
portBASE_TYPE xRunPrivileged; BaseType_t xRunPrivileged;
if( ( uxPriority & portPRIVILEGE_BIT ) != 0U ) if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
{ {
xRunPrivileged = pdTRUE; xRunPrivileged = pdTRUE;
@ -506,23 +543,23 @@ tskTCB * pxNewTCB;
#endif /* portUSING_MPU_WRAPPERS == 1 */ #endif /* portUSING_MPU_WRAPPERS == 1 */
/* Calculate the top of stack address. This depends on whether the /* Calculate the top of stack address. This depends on whether the
stack grows from high memory to low (as per the 80x86) or visa versa. stack grows from high memory to low (as per the 80x86) or vice versa.
portSTACK_GROWTH is used to make the result positive or negative as portSTACK_GROWTH is used to make the result positive or negative as
required by the port. */ required by the port. */
#if( portSTACK_GROWTH < 0 ) #if( portSTACK_GROWTH < 0 )
{ {
pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( unsigned short ) 1 ); pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( uint16_t ) 1 );
pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); /*lint !e923 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. */ pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); /*lint !e923 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. */
/* Check the alignment of the calculated top of stack is correct. */ /* Check the alignment of the calculated top of stack is correct. */
configASSERT( ( ( ( unsigned long ) pxTopOfStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); configASSERT( ( ( ( uint32_t ) pxTopOfStack & ( uint32_t ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
} }
#else /* portSTACK_GROWTH */ #else /* portSTACK_GROWTH */
{ {
pxTopOfStack = pxNewTCB->pxStack; pxTopOfStack = pxNewTCB->pxStack;
/* Check the alignment of the stack buffer is correct. */ /* Check the alignment of the stack buffer is correct. */
configASSERT( ( ( ( unsigned long ) pxNewTCB->pxStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); configASSERT( ( ( ( uint32_t ) pxNewTCB->pxStack & ( uint32_t ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
/* If we want to use stack checking on architectures that use /* If we want to use stack checking on architectures that use
a positive stack growth direction then we also need to store the a positive stack growth direction then we also need to store the
@ -553,7 +590,11 @@ tskTCB * pxNewTCB;
/* Pass the TCB out - in an anonymous way. The calling function/ /* Pass the TCB out - in an anonymous way. The calling function/
task can use this as a handle to delete the task later if task can use this as a handle to delete the task later if
required.*/ required.*/
*pxCreatedTask = ( xTaskHandle ) pxNewTCB; *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
/* Ensure interrupts don't access the task lists while they are being /* Ensure interrupts don't access the task lists while they are being
@ -567,13 +608,17 @@ tskTCB * pxNewTCB;
the suspended state - make this the current task. */ the suspended state - make this the current task. */
pxCurrentTCB = pxNewTCB; pxCurrentTCB = pxNewTCB;
if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 ) if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
{ {
/* This is the first task to be created so do the preliminary /* This is the first task to be created so do the preliminary
initialisation required. We will not recover if this call initialisation required. We will not recover if this call
fails, but we will report the failure. */ fails, but we will report the failure. */
prvInitialiseTaskLists(); prvInitialiseTaskLists();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
else else
{ {
@ -586,6 +631,14 @@ tskTCB * pxNewTCB;
{ {
pxCurrentTCB = pxNewTCB; pxCurrentTCB = pxNewTCB;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
@ -620,8 +673,16 @@ tskTCB * pxNewTCB;
then it should run now. */ then it should run now. */
if( pxCurrentTCB->uxPriority < uxPriority ) if( pxCurrentTCB->uxPriority < uxPriority )
{ {
portYIELD_WITHIN_API(); taskYIELD_IF_USING_PREEMPTION();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
@ -631,29 +692,38 @@ tskTCB * pxNewTCB;
#if ( INCLUDE_vTaskDelete == 1 ) #if ( INCLUDE_vTaskDelete == 1 )
void vTaskDelete( xTaskHandle xTaskToDelete ) void vTaskDelete( TaskHandle_t xTaskToDelete )
{ {
tskTCB *pxTCB; TCB_t *pxTCB;
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
/* If null is passed in here then we are deleting ourselves. */ /* If null is passed in here then it is the calling task that is
being deleted. */
pxTCB = prvGetTCBFromHandle( xTaskToDelete ); pxTCB = prvGetTCBFromHandle( xTaskToDelete );
/* Remove task from the ready list and place in the termination list. /* Remove task from the ready list and place in the termination list.
This will stop the task from be scheduled. The idle task will check This will stop the task from be scheduled. The idle task will check
the termination list and free up any memory allocated by the the termination list and free up any memory allocated by the
scheduler for the TCB and stack. */ scheduler for the TCB and stack. */
if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{ {
taskRESET_READY_PRIORITY( pxTCB->uxPriority ); taskRESET_READY_PRIORITY( pxTCB->uxPriority );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Is the task waiting on an event also? */ /* Is the task waiting on an event also? */
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
{ {
( void ) uxListRemove( &( pxTCB->xEventListItem ) ); ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) ); vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );
@ -670,13 +740,28 @@ tskTCB * pxNewTCB;
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
/* Force a reschedule if we have just deleted the current task. */ /* Force a reschedule if it is the currently running task that has just
been deleted. */
if( xSchedulerRunning != pdFALSE ) if( xSchedulerRunning != pdFALSE )
{ {
if( pxTCB == pxCurrentTCB ) if( pxTCB == pxCurrentTCB )
{ {
configASSERT( uxSchedulerSuspended == 0 );
/* The pre-delete hook is primarily for the Windows simulator,
in which Windows specific clean up operations are performed,
after which it is not possible to yield away from this task -
hence xYieldPending is used to latch that a context switch is
required. */
portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
portYIELD_WITHIN_API(); portYIELD_WITHIN_API();
} }
else
{
/* Reset the next expected unblock time in case it referred to
the task that has just been deleted. */
prvResetNextTaskUnblockTime();
}
} }
} }
@ -685,19 +770,20 @@ tskTCB * pxNewTCB;
#if ( INCLUDE_vTaskDelayUntil == 1 ) #if ( INCLUDE_vTaskDelayUntil == 1 )
void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement ) void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
{ {
portTickType xTimeToWake; TickType_t xTimeToWake;
portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE; BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
configASSERT( pxPreviousWakeTime ); configASSERT( pxPreviousWakeTime );
configASSERT( ( xTimeIncrement > 0U ) ); configASSERT( ( xTimeIncrement > 0U ) );
configASSERT( uxSchedulerSuspended == 0 );
vTaskSuspendAll(); vTaskSuspendAll();
{ {
/* Minor optimisation. The tick count cannot change in this /* Minor optimisation. The tick count cannot change in this
block. */ block. */
const portTickType xConstTickCount = xTickCount; const TickType_t xConstTickCount = xTickCount;
/* Generate the tick time at which the task wants to wake. */ /* Generate the tick time at which the task wants to wake. */
xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
@ -713,6 +799,10 @@ tskTCB * pxNewTCB;
{ {
xShouldDelay = pdTRUE; xShouldDelay = pdTRUE;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
else else
{ {
@ -723,6 +813,10 @@ tskTCB * pxNewTCB;
{ {
xShouldDelay = pdTRUE; xShouldDelay = pdTRUE;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
/* Update the wake time ready for the next call. */ /* Update the wake time ready for the next call. */
@ -732,19 +826,26 @@ tskTCB * pxNewTCB;
{ {
traceTASK_DELAY_UNTIL(); traceTASK_DELAY_UNTIL();
/* We must remove ourselves from the ready list before adding /* Remove the task from the ready list before adding it to the
ourselves to the blocked list as the same list item is used for blocked list as the same list item is used for both lists. */
both lists. */ if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
{ {
/* The current task must be in a ready list, so there is /* The current task must be in a ready list, so there is
no need to check, and the port reset macro can be called no need to check, and the port reset macro can be called
directly. */ directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
prvAddCurrentTaskToDelayedList( xTimeToWake ); prvAddCurrentTaskToDelayedList( xTimeToWake );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
xAlreadyYielded = xTaskResumeAll(); xAlreadyYielded = xTaskResumeAll();
@ -754,6 +855,10 @@ tskTCB * pxNewTCB;
{ {
portYIELD_WITHIN_API(); portYIELD_WITHIN_API();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
#endif /* INCLUDE_vTaskDelayUntil */ #endif /* INCLUDE_vTaskDelayUntil */
@ -761,14 +866,16 @@ tskTCB * pxNewTCB;
#if ( INCLUDE_vTaskDelay == 1 ) #if ( INCLUDE_vTaskDelay == 1 )
void vTaskDelay( portTickType xTicksToDelay ) void vTaskDelay( const TickType_t xTicksToDelay )
{ {
portTickType xTimeToWake; TickType_t xTimeToWake;
signed portBASE_TYPE xAlreadyYielded = pdFALSE; BaseType_t xAlreadyYielded = pdFALSE;
/* A delay time of zero just forces a reschedule. */ /* A delay time of zero just forces a reschedule. */
if( xTicksToDelay > ( portTickType ) 0U ) if( xTicksToDelay > ( TickType_t ) 0U )
{ {
configASSERT( uxSchedulerSuspended == 0 );
vTaskSuspendAll(); vTaskSuspendAll();
{ {
traceTASK_DELAY(); traceTASK_DELAY();
@ -788,17 +895,25 @@ tskTCB * pxNewTCB;
/* 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. */
if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{ {
/* The current task must be in a ready list, so there is /* The current task must be in a ready list, so there is
no need to check, and the port reset macro can be called no need to check, and the port reset macro can be called
directly. */ directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
prvAddCurrentTaskToDelayedList( xTimeToWake ); prvAddCurrentTaskToDelayedList( xTimeToWake );
} }
xAlreadyYielded = xTaskResumeAll(); xAlreadyYielded = xTaskResumeAll();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Force a reschedule if xTaskResumeAll has not already done so, we may /* Force a reschedule if xTaskResumeAll has not already done so, we may
have put ourselves to sleep. */ have put ourselves to sleep. */
@ -806,6 +921,10 @@ tskTCB * pxNewTCB;
{ {
portYIELD_WITHIN_API(); portYIELD_WITHIN_API();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
#endif /* INCLUDE_vTaskDelay */ #endif /* INCLUDE_vTaskDelay */
@ -813,11 +932,13 @@ tskTCB * pxNewTCB;
#if ( INCLUDE_eTaskGetState == 1 ) #if ( INCLUDE_eTaskGetState == 1 )
eTaskState eTaskGetState( xTaskHandle xTask ) eTaskState eTaskGetState( TaskHandle_t xTask )
{ {
eTaskState eReturn; eTaskState eReturn;
xList *pxStateList; List_t *pxStateList;
const tskTCB * const pxTCB = ( tskTCB * ) xTask; const TCB_t * const pxTCB = ( TCB_t * ) xTask;
configASSERT( pxTCB );
if( pxTCB == pxCurrentTCB ) if( pxTCB == pxCurrentTCB )
{ {
@ -828,7 +949,7 @@ tskTCB * pxNewTCB;
{ {
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
pxStateList = ( xList * ) listLIST_ITEM_CONTAINER( &( pxTCB->xGenericListItem ) ); pxStateList = ( List_t * ) listLIST_ITEM_CONTAINER( &( pxTCB->xGenericListItem ) );
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
@ -843,8 +964,16 @@ tskTCB * pxNewTCB;
else if( pxStateList == &xSuspendedTaskList ) else if( pxStateList == &xSuspendedTaskList )
{ {
/* The task being queried is referenced from the suspended /* The task being queried is referenced from the suspended
list. */ list. Is it genuinely suspended or is it block
eReturn = eSuspended; indefinitely? */
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
{
eReturn = eSuspended;
}
else
{
eReturn = eBlocked;
}
} }
#endif #endif
@ -873,10 +1002,10 @@ tskTCB * pxNewTCB;
#if ( INCLUDE_uxTaskPriorityGet == 1 ) #if ( INCLUDE_uxTaskPriorityGet == 1 )
unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle xTask ) UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask )
{ {
tskTCB *pxTCB; TCB_t *pxTCB;
unsigned portBASE_TYPE uxReturn; UBaseType_t uxReturn;
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
@ -895,18 +1024,22 @@ tskTCB * pxNewTCB;
#if ( INCLUDE_vTaskPrioritySet == 1 ) #if ( INCLUDE_vTaskPrioritySet == 1 )
void vTaskPrioritySet( xTaskHandle xTask, unsigned portBASE_TYPE uxNewPriority ) void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )
{ {
tskTCB *pxTCB; TCB_t *pxTCB;
unsigned portBASE_TYPE uxCurrentBasePriority, uxPriorityUsedOnEntry; UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;
portBASE_TYPE xYieldRequired = pdFALSE; BaseType_t xYieldRequired = pdFALSE;
configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) ); configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
/* Ensure the new priority is valid. */ /* Ensure the new priority is valid. */
if( uxNewPriority >= ( unsigned portBASE_TYPE ) configMAX_PRIORITIES ) if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
{ {
uxNewPriority = ( unsigned portBASE_TYPE ) configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U; uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
taskENTER_CRITICAL(); taskENTER_CRITICAL();
@ -939,9 +1072,13 @@ tskTCB * pxNewTCB;
running task is being raised. Is the priority being running task is being raised. Is the priority being
raised above that of the running task? */ raised above that of the running task? */
if( uxNewPriority >= pxCurrentTCB->uxPriority ) if( uxNewPriority >= pxCurrentTCB->uxPriority )
{ {
xYieldRequired = pdTRUE; xYieldRequired = pdTRUE;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
else else
{ {
@ -952,8 +1089,8 @@ tskTCB * pxNewTCB;
} }
else if( pxTCB == pxCurrentTCB ) else if( pxTCB == pxCurrentTCB )
{ {
/* Setting the priority of the running task down means /* Setting the priority of the running task down means
there may now be another task of higher priority that there may now be another task of higher priority that
is ready to execute. */ is ready to execute. */
xYieldRequired = pdTRUE; xYieldRequired = pdTRUE;
} }
@ -977,6 +1114,10 @@ tskTCB * pxNewTCB;
{ {
pxTCB->uxPriority = uxNewPriority; pxTCB->uxPriority = uxNewPriority;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
/* The base priority gets set whatever. */ /* The base priority gets set whatever. */
pxTCB->uxBasePriority = uxNewPriority; pxTCB->uxBasePriority = uxNewPriority;
@ -987,7 +1128,16 @@ tskTCB * pxNewTCB;
} }
#endif #endif
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( portTickType ) configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ /* Only reset the event list item value if the value is not
being used for anything else. */
if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
{
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* If the task is in the blocked or suspended list we need do /* If the task is in the blocked or suspended list we need do
nothing more than change it's priority variable. However, if nothing more than change it's priority variable. However, if
@ -998,19 +1148,31 @@ tskTCB * pxNewTCB;
/* The task is currently in its ready list - remove before adding /* The task is currently in its ready list - remove before adding
it to it's new ready list. As we are in a critical section we it to it's new ready list. As we are in a critical section we
can do this even if the scheduler is suspended. */ can do this even if the scheduler is suspended. */
if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{ {
/* It is known that the task is in its ready list so /* It is known that the task is in its ready list so
there is no need to check again and the port level there is no need to check again and the port level
reset macro can be called directly. */ reset macro can be called directly. */
portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority ); portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
prvAddTaskToReadyList( pxTCB ); prvAddTaskToReadyList( pxTCB );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
if( xYieldRequired == pdTRUE ) if( xYieldRequired == pdTRUE )
{ {
portYIELD_WITHIN_API(); taskYIELD_IF_USING_PREEMPTION();
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
/* Remove compiler warning about unused variables when the port /* Remove compiler warning about unused variables when the port
@ -1026,9 +1188,9 @@ tskTCB * pxNewTCB;
#if ( INCLUDE_vTaskSuspend == 1 ) #if ( INCLUDE_vTaskSuspend == 1 )
void vTaskSuspend( xTaskHandle xTaskToSuspend ) void vTaskSuspend( TaskHandle_t xTaskToSuspend )
{ {
tskTCB *pxTCB; TCB_t *pxTCB;
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
@ -1038,17 +1200,26 @@ tskTCB * pxNewTCB;
traceTASK_SUSPEND( pxTCB ); traceTASK_SUSPEND( pxTCB );
/* Remove task from the ready/delayed list and place in the suspended list. */ /* Remove task from the ready/delayed list and place in the
if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) suspended list. */
if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{ {
taskRESET_READY_PRIORITY( pxTCB->uxPriority ); taskRESET_READY_PRIORITY( pxTCB->uxPriority );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Is the task waiting on an event also? */ /* Is the task waiting on an event also? */
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
{ {
( void ) uxListRemove( &( pxTCB->xEventListItem ) ); ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ); vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) );
} }
@ -1059,6 +1230,7 @@ tskTCB * pxNewTCB;
if( xSchedulerRunning != pdFALSE ) if( xSchedulerRunning != pdFALSE )
{ {
/* The current task has just been suspended. */ /* The current task has just been suspended. */
configASSERT( uxSchedulerSuspended == 0 );
portYIELD_WITHIN_API(); portYIELD_WITHIN_API();
} }
else else
@ -1080,6 +1252,20 @@ tskTCB * pxNewTCB;
} }
} }
} }
else
{
if( xSchedulerRunning != pdFALSE )
{
/* A task other than the currently running task was suspended,
reset the next expected unblock time in case it referred to the
task that is now in the Suspended state. */
prvResetNextTaskUnblockTime();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
} }
#endif /* INCLUDE_vTaskSuspend */ #endif /* INCLUDE_vTaskSuspend */
@ -1087,30 +1273,42 @@ tskTCB * pxNewTCB;
#if ( INCLUDE_vTaskSuspend == 1 ) #if ( INCLUDE_vTaskSuspend == 1 )
signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask ) static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
{ {
portBASE_TYPE xReturn = pdFALSE; BaseType_t xReturn = pdFALSE;
const tskTCB * const pxTCB = ( tskTCB * ) xTask; const TCB_t * const pxTCB = ( TCB_t * ) xTask;
/* Accesses xPendingReadyList so must be called from a critical
section. */
/* It does not make sense to check if the calling task is suspended. */ /* It does not make sense to check if the calling task is suspended. */
configASSERT( xTask ); configASSERT( xTask );
/* Is the task we are attempting to resume actually in the /* Is the task being resumed actually in the suspended list? */
suspended list? */
if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE ) if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
{ {
/* Has the task already been resumed from within an ISR? */ /* Has the task already been resumed from within an ISR? */
if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE ) if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
{ {
/* Is it in the suspended list because it is in the /* Is it in the suspended list because it is in the Suspended
Suspended state? It is possible to be in the suspended state, or because is is blocked with no timeout? */
list because it is blocked on a task with no timeout
specified. */
if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )
{ {
xReturn = pdTRUE; xReturn = pdTRUE;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
return xReturn; return xReturn;
@ -1121,9 +1319,9 @@ tskTCB * pxNewTCB;
#if ( INCLUDE_vTaskSuspend == 1 ) #if ( INCLUDE_vTaskSuspend == 1 )
void vTaskResume( xTaskHandle xTaskToResume ) void vTaskResume( TaskHandle_t xTaskToResume )
{ {
tskTCB * const pxTCB = ( tskTCB * ) xTaskToResume; TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
/* It does not make sense to resume the calling task. */ /* It does not make sense to resume the calling task. */
configASSERT( xTaskToResume ); configASSERT( xTaskToResume );
@ -1134,7 +1332,7 @@ tskTCB * pxNewTCB;
{ {
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE ) if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE )
{ {
traceTASK_RESUME( pxTCB ); traceTASK_RESUME( pxTCB );
@ -1146,14 +1344,27 @@ tskTCB * pxNewTCB;
/* We may have just resumed a higher priority task. */ /* We may have just resumed a higher priority task. */
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
{ {
/* This yield may not cause the task just resumed to run, but /* This yield may not cause the task just resumed to run,
will leave the lists in the correct state for the next yield. */ but will leave the lists in the correct state for the
portYIELD_WITHIN_API(); next yield. */
taskYIELD_IF_USING_PREEMPTION();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
#endif /* INCLUDE_vTaskSuspend */ #endif /* INCLUDE_vTaskSuspend */
@ -1162,11 +1373,11 @@ tskTCB * pxNewTCB;
#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
portBASE_TYPE xTaskResumeFromISR( xTaskHandle xTaskToResume ) BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
{ {
portBASE_TYPE xYieldRequired = pdFALSE; BaseType_t xYieldRequired = pdFALSE;
tskTCB * const pxTCB = ( tskTCB * ) xTaskToResume; TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
unsigned portBASE_TYPE uxSavedInterruptStatus; UBaseType_t uxSavedInterruptStatus;
configASSERT( xTaskToResume ); configASSERT( xTaskToResume );
@ -1190,24 +1401,39 @@ tskTCB * pxNewTCB;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{ {
if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE ) if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE )
{ {
traceTASK_RESUME_FROM_ISR( pxTCB ); traceTASK_RESUME_FROM_ISR( pxTCB );
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) /* Check the ready lists can be accessed. */
if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
{ {
xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ); /* Ready lists can be accessed so move the task from the
suspended list to the ready list directly. */
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
{
xYieldRequired = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
prvAddTaskToReadyList( pxTCB ); prvAddTaskToReadyList( pxTCB );
} }
else else
{ {
/* We cannot access the delayed or ready lists, so will hold this /* The delayed or ready lists cannot be accessed so the task
task pending until the scheduler is resumed, at which point a is held in the pending ready list until the scheduler is
yield will be performed if necessary. */ unsuspended. */
vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
} }
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
@ -1219,19 +1445,19 @@ tskTCB * pxNewTCB;
void vTaskStartScheduler( void ) void vTaskStartScheduler( void )
{ {
portBASE_TYPE xReturn; BaseType_t xReturn;
/* Add the idle task at the lowest priority. */ /* Add the idle task at the lowest priority. */
#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
{ {
/* Create the idle task, storing its handle in xIdleTaskHandle so it can /* Create the idle task, storing its handle in xIdleTaskHandle so it can
be returned by the xTaskGetIdleTaskHandle() function. */ be returned by the xTaskGetIdleTaskHandle() function. */
xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ xReturn = xTaskCreate( prvIdleTask, "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
} }
#else #else
{ {
/* Create the idle task without storing its handle. */ /* Create the idle task without storing its handle. */
xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), NULL ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ xReturn = xTaskCreate( prvIdleTask, "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), NULL ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
} }
#endif /* INCLUDE_xTaskGetIdleTaskHandle */ #endif /* INCLUDE_xTaskGetIdleTaskHandle */
@ -1241,6 +1467,10 @@ portBASE_TYPE xReturn;
{ {
xReturn = xTimerCreateTimerTask(); xReturn = xTimerCreateTimerTask();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
#endif /* configUSE_TIMERS */ #endif /* configUSE_TIMERS */
@ -1250,14 +1480,19 @@ portBASE_TYPE xReturn;
before or during the call to xPortStartScheduler(). The stacks of before or during the call to xPortStartScheduler(). The stacks of
the created tasks contain a status word with interrupts switched on the created tasks contain a status word with interrupts switched on
so interrupts will automatically get re-enabled when the first task so interrupts will automatically get re-enabled when the first task
starts to run. starts to run. */
STEPPING THROUGH HERE USING A DEBUGGER CAN CAUSE BIG PROBLEMS IF THE
DEBUGGER ALLOWS INTERRUPTS TO BE PROCESSED. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
#if ( configUSE_NEWLIB_REENTRANT == 1 )
{
/* Switch Newlib's _impure_ptr variable to point to the _reent
structure specific to the task that will run first. */
_impure_ptr = &( pxCurrentTCB->xNewLib_reent );
}
#endif /* configUSE_NEWLIB_REENTRANT */
xSchedulerRunning = pdTRUE; xSchedulerRunning = pdTRUE;
xTickCount = ( portTickType ) 0U; xTickCount = ( TickType_t ) 0U;
/* If configGENERATE_RUN_TIME_STATS is defined then the following /* If configGENERATE_RUN_TIME_STATS is defined then the following
macro must be defined to configure the timer/counter used to generate macro must be defined to configure the timer/counter used to generate
@ -1300,16 +1535,18 @@ void vTaskEndScheduler( void )
void vTaskSuspendAll( void ) void vTaskSuspendAll( void )
{ {
/* A critical section is not required as the variable is of type /* A critical section is not required as the variable is of type
portBASE_TYPE. */ BaseType_t. Please read Richard Barry's reply in the following link to a
post in the FreeRTOS support forum before reporting this as a bug! -
http://goo.gl/wu4acr */
++uxSchedulerSuspended; ++uxSchedulerSuspended;
} }
/*----------------------------------------------------------*/ /*----------------------------------------------------------*/
#if ( configUSE_TICKLESS_IDLE != 0 ) #if ( configUSE_TICKLESS_IDLE != 0 )
static portTickType prvGetExpectedIdleTime( void ) static TickType_t prvGetExpectedIdleTime( void )
{ {
portTickType xReturn; TickType_t xReturn;
if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY ) if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
{ {
@ -1333,11 +1570,10 @@ void vTaskSuspendAll( void )
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/*----------------------------------------------------------*/ /*----------------------------------------------------------*/
signed portBASE_TYPE xTaskResumeAll( void ) BaseType_t xTaskResumeAll( void )
{ {
tskTCB *pxTCB; TCB_t *pxTCB;
portBASE_TYPE xAlreadyYielded = pdFALSE; BaseType_t xAlreadyYielded = pdFALSE;
portBASE_TYPE xYieldRequired = pdFALSE;
/* If uxSchedulerSuspended is zero then this function does not match a /* If uxSchedulerSuspended is zero then this function does not match a
previous call to vTaskSuspendAll(). */ previous call to vTaskSuspendAll(). */
@ -1352,15 +1588,15 @@ portBASE_TYPE xYieldRequired = pdFALSE;
{ {
--uxSchedulerSuspended; --uxSchedulerSuspended;
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
{ {
if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0U ) if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )
{ {
/* Move any readied tasks from the pending list into the /* Move any readied tasks from the pending list into the
appropriate ready list. */ appropriate ready list. */
while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE ) while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
{ {
pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );
( void ) uxListRemove( &( pxTCB->xEventListItem ) ); ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
prvAddTaskToReadyList( pxTCB ); prvAddTaskToReadyList( pxTCB );
@ -1369,33 +1605,57 @@ portBASE_TYPE xYieldRequired = pdFALSE;
the current task then we should yield. */ the current task then we should yield. */
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
{ {
xYieldRequired = pdTRUE; xYieldPending = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
/* If any ticks occurred while the scheduler was suspended then /* If any ticks occurred while the scheduler was suspended then
they should be processed now. This ensures the tick count does not they should be processed now. This ensures the tick count does
slip, and that any delayed tasks are resumed at the correct time. */ not slip, and that any delayed tasks are resumed at the correct
if( uxPendedTicks > ( unsigned portBASE_TYPE ) 0U ) time. */
if( uxPendedTicks > ( UBaseType_t ) 0U )
{ {
while( uxPendedTicks > ( unsigned portBASE_TYPE ) 0U ) while( uxPendedTicks > ( UBaseType_t ) 0U )
{ {
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
xYieldRequired = pdTRUE; xYieldPending = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
--uxPendedTicks; --uxPendedTicks;
} }
} }
else
if( ( xYieldRequired == pdTRUE ) || ( xYieldPending == pdTRUE ) )
{ {
xAlreadyYielded = pdTRUE; mtCOVERAGE_TEST_MARKER();
xYieldPending = pdFALSE; }
portYIELD_WITHIN_API();
if( xYieldPending == pdTRUE )
{
#if( configUSE_PREEMPTION != 0 )
{
xAlreadyYielded = pdTRUE;
}
#endif
taskYIELD_IF_USING_PREEMPTION();
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
@ -1403,9 +1663,9 @@ portBASE_TYPE xYieldRequired = pdFALSE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
portTickType xTaskGetTickCount( void ) TickType_t xTaskGetTickCount( void )
{ {
portTickType xTicks; TickType_t xTicks;
/* Critical section required if running on a 16 bit processor. */ /* Critical section required if running on a 16 bit processor. */
taskENTER_CRITICAL(); taskENTER_CRITICAL();
@ -1418,14 +1678,14 @@ portTickType xTicks;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
portTickType xTaskGetTickCountFromISR( void ) TickType_t xTaskGetTickCountFromISR( void )
{ {
portTickType xReturn; TickType_t xReturn;
unsigned portBASE_TYPE uxSavedInterruptStatus; UBaseType_t uxSavedInterruptStatus;
/* RTOS ports that support interrupt nesting have the concept of a maximum /* RTOS ports that support interrupt nesting have the concept of a maximum
system call (or maximum API call) interrupt priority. Interrupts that are system call (or maximum API call) interrupt priority. Interrupts that are
above the maximum system call priority are keep permanently enabled, even above the maximum system call priority are kept permanently enabled, even
when the RTOS kernel is in a critical section, but cannot make any calls to when the RTOS kernel is in a critical section, but cannot make any calls to
FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
@ -1440,26 +1700,28 @@ unsigned portBASE_TYPE uxSavedInterruptStatus;
portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
xReturn = xTickCount; {
xReturn = xTickCount;
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
return xReturn; return xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) UBaseType_t uxTaskGetNumberOfTasks( void )
{ {
/* A critical section is not required because the variables are of type /* A critical section is not required because the variables are of type
portBASE_TYPE. */ BaseType_t. */
return uxCurrentNumberOfTasks; return uxCurrentNumberOfTasks;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if ( INCLUDE_pcTaskGetTaskName == 1 ) #if ( INCLUDE_pcTaskGetTaskName == 1 )
signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery ) char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery )
{ {
tskTCB *pxTCB; TCB_t *pxTCB;
/* If null is passed in here then the name of the calling task is being queried. */ /* If null is passed in here then the name of the calling task is being queried. */
pxTCB = prvGetTCBFromHandle( xTaskToQuery ); pxTCB = prvGetTCBFromHandle( xTaskToQuery );
@ -1472,32 +1734,32 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
unsigned portBASE_TYPE uxTaskGetSystemState( xTaskStatusType *pxTaskStatusArray, unsigned portBASE_TYPE uxArraySize, unsigned long *pulTotalRunTime ) UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime )
{ {
unsigned portBASE_TYPE uxTask = 0, uxQueue = configMAX_PRIORITIES; UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
vTaskSuspendAll(); vTaskSuspendAll();
{ {
/* Is there a space in the array for each task in the system? */ /* Is there a space in the array for each task in the system? */
if( uxArraySize >= uxCurrentNumberOfTasks ) if( uxArraySize >= uxCurrentNumberOfTasks )
{ {
/* Fill in an xTaskStatusType structure with information on each /* Fill in an TaskStatus_t structure with information on each
task in the Ready state. */ task in the Ready state. */
do do
{ {
uxQueue--; uxQueue--;
uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady ); uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
} while( uxQueue > ( unsigned portBASE_TYPE ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
/* Fill in an xTaskStatusType structure with information on each /* Fill in an TaskStatus_t structure with information on each
task in the Blocked state. */ task in the Blocked state. */
uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( xList * ) pxDelayedTaskList, eBlocked ); uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );
uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( xList * ) pxOverflowDelayedTaskList, eBlocked ); uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );
#if( INCLUDE_vTaskDelete == 1 ) #if( INCLUDE_vTaskDelete == 1 )
{ {
/* Fill in an xTaskStatusType structure with information on /* Fill in an TaskStatus_t structure with information on
each task that has been deleted but not yet cleaned up. */ each task that has been deleted but not yet cleaned up. */
uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted ); uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
} }
@ -1505,7 +1767,7 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
#if ( INCLUDE_vTaskSuspend == 1 ) #if ( INCLUDE_vTaskSuspend == 1 )
{ {
/* Fill in an xTaskStatusType structure with information on /* Fill in an TaskStatus_t structure with information on
each task in the Suspended state. */ each task in the Suspended state. */
uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended ); uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
} }
@ -1515,7 +1777,11 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
{ {
if( pulTotalRunTime != NULL ) if( pulTotalRunTime != NULL )
{ {
*pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
#else
*pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
#endif
} }
} }
#else #else
@ -1527,6 +1793,10 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
} }
#endif #endif
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
( void ) xTaskResumeAll(); ( void ) xTaskResumeAll();
@ -1538,7 +1808,7 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
#if ( INCLUDE_uxTaskGetRunTime == 1 ) #if ( INCLUDE_uxTaskGetRunTime == 1 )
unsigned portBASE_TYPE uxTaskGetRunTime( xTaskHandle xTask ) UBaseType_t uxTaskGetRunTime( TaskHandle_t xTask )
{ {
unsigned long runTime; unsigned long runTime;
@ -1553,7 +1823,7 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
xTaskHandle xTaskGetIdleTaskHandle( void ) TaskHandle_t xTaskGetIdleTaskHandle( void )
{ {
/* If xTaskGetIdleTaskHandle() is called before the scheduler has been /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
started, then xIdleTaskHandle will be NULL. */ started, then xIdleTaskHandle will be NULL. */
@ -1570,7 +1840,7 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than
1. */ 1. */
#if ( configUSE_TICKLESS_IDLE != 0 ) #if ( configUSE_TICKLESS_IDLE != 0 )
void vTaskStepTick( portTickType xTicksToJump ) void vTaskStepTick( const TickType_t xTicksToJump )
{ {
/* Correct the tick count value after a period during which the tick /* Correct the tick count value after a period during which the tick
was suppressed. Note this does *not* call the tick hook function for was suppressed. Note this does *not* call the tick hook function for
@ -1583,17 +1853,17 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/*----------------------------------------------------------*/ /*----------------------------------------------------------*/
portBASE_TYPE xTaskIncrementTick( void ) BaseType_t xTaskIncrementTick( void )
{ {
tskTCB * pxTCB; TCB_t * pxTCB;
portTickType xItemValue; TickType_t xItemValue;
portBASE_TYPE xSwitchRequired = pdFALSE; BaseType_t xSwitchRequired = pdFALSE;
/* Called by the portable layer each time a tick interrupt occurs. /* Called by the portable layer each time a tick interrupt occurs.
Increments the tick then checks to see if the new tick value will cause any Increments the tick then checks to see if the new tick value will cause any
tasks to be unblocked. */ tasks to be unblocked. */
traceTASK_INCREMENT_TICK( xTickCount ); traceTASK_INCREMENT_TICK( xTickCount );
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
{ {
/* Increment the RTOS tick, switching the delayed and overflowed /* Increment the RTOS tick, switching the delayed and overflowed
delayed lists if it wraps to 0. */ delayed lists if it wraps to 0. */
@ -1602,75 +1872,93 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
{ {
/* Minor optimisation. The tick count cannot change in this /* Minor optimisation. The tick count cannot change in this
block. */ block. */
const portTickType xConstTickCount = xTickCount; const TickType_t xConstTickCount = xTickCount;
if( xConstTickCount == ( portTickType ) 0U ) if( xConstTickCount == ( TickType_t ) 0U )
{ {
taskSWITCH_DELAYED_LISTS(); taskSWITCH_DELAYED_LISTS();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
/* See if this tick has made a timeout expire. Tasks are stored in the /* See if this tick has made a timeout expire. Tasks are stored in
queue in the order of their wake time - meaning once one tasks has been the queue in the order of their wake time - meaning once one task
found whose block time has not expired there is no need not look any has been found whose block time has not expired there is no need to
further down the list. */ look any further down the list. */
if( xConstTickCount >= xNextTaskUnblockTime ) if( xConstTickCount >= xNextTaskUnblockTime )
{ {
for( ;; ) for( ;; )
{ {
if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
{ {
/* The delayed list is empty. Set xNextTaskUnblockTime to /* The delayed list is empty. Set xNextTaskUnblockTime
the maximum possible value so it is extremely unlikely that to the maximum possible value so it is extremely
the if( xTickCount >= xNextTaskUnblockTime ) test will pass unlikely that the
if( xTickCount >= xNextTaskUnblockTime ) test will pass
next time through. */ next time through. */
xNextTaskUnblockTime = portMAX_DELAY; xNextTaskUnblockTime = portMAX_DELAY;
break; break;
} }
else else
{ {
/* The delayed list is not empty, get the value of the item /* The delayed list is not empty, get the value of the
at the head of the delayed list. This is the time at which item at the head of the delayed list. This is the time
the task at the head of the delayed list must be removed at which the task at the head of the delayed list must
from the Blocked state. */ be removed from the Blocked state. */
pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ); xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
if( xConstTickCount < xItemValue ) if( xConstTickCount < xItemValue )
{ {
/* It is not time to unblock this item yet, but the item /* It is not time to unblock this item yet, but the
value is the time at which the task at the head of the item value is the time at which the task at the head
blocked list must be removed from the Blocked state - of the blocked list must be removed from the Blocked
so record the item value in xNextTaskUnblockTime. */ state - so record the item value in
xNextTaskUnblockTime. */
xNextTaskUnblockTime = xItemValue; xNextTaskUnblockTime = xItemValue;
break; break;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
/* It is time to remove the item from the Blocked state. */ /* It is time to remove the item from the Blocked state. */
( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
/* Is the task waiting on an event also? If so remove it /* Is the task waiting on an event also? If so remove
from the event list. */ it from the event list. */
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
{ {
( void ) uxListRemove( &( pxTCB->xEventListItem ) ); ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Place the unblocked task into the appropriate ready /* Place the unblocked task into the appropriate ready
list. */ list. */
prvAddTaskToReadyList( pxTCB ); prvAddTaskToReadyList( pxTCB );
/* A task being unblocked cannot cause an immediate context /* A task being unblocked cannot cause an immediate
switch if preemption is turned off. */ context switch if preemption is turned off. */
#if ( configUSE_PREEMPTION == 1 ) #if ( configUSE_PREEMPTION == 1 )
{ {
/* Preemption is on, but a context switch should only /* Preemption is on, but a context switch should
be performed if the unblocked task has a priority that only be performed if the unblocked task has a
is equal to or higher than the currently executing priority that is equal to or higher than the
task. */ currently executing task. */
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
{ {
xSwitchRequired = pdTRUE; xSwitchRequired = pdTRUE;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
#endif /* configUSE_PREEMPTION */ #endif /* configUSE_PREEMPTION */
} }
@ -1683,12 +1971,31 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
writer has not explicitly turned time slicing off. */ writer has not explicitly turned time slicing off. */
#if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
{ {
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( unsigned portBASE_TYPE ) 1 ) if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )
{ {
xSwitchRequired = pdTRUE; xSwitchRequired = pdTRUE;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
#endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */ #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
#if ( configUSE_TICK_HOOK == 1 )
{
/* Guard against the tick hook being called when the pended tick
count is being unwound (when the scheduler is being unlocked). */
if( uxPendedTicks == ( UBaseType_t ) 0U )
{
vApplicationTickHook();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* configUSE_TICK_HOOK */
} }
else else
{ {
@ -1703,16 +2010,18 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
#endif #endif
} }
#if ( configUSE_TICK_HOOK == 1 ) #if ( configUSE_PREEMPTION == 1 )
{ {
/* Guard against the tick hook being called when the missed tick if( xYieldPending != pdFALSE )
count is being unwound (when the scheduler is being unlocked). */
if( uxPendedTicks == ( unsigned portBASE_TYPE ) 0U )
{ {
vApplicationTickHook(); xSwitchRequired = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
#endif /* configUSE_TICK_HOOK */ #endif /* configUSE_PREEMPTION */
return xSwitchRequired; return xSwitchRequired;
} }
@ -1720,18 +2029,19 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
#if ( configUSE_APPLICATION_TASK_TAG == 1 ) #if ( configUSE_APPLICATION_TASK_TAG == 1 )
void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction ) void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction )
{ {
tskTCB *xTCB; TCB_t *xTCB;
/* If xTask is NULL then we are setting our own task hook. */ /* If xTask is NULL then it is the task hook of the calling task that is
getting set. */
if( xTask == NULL ) if( xTask == NULL )
{ {
xTCB = ( tskTCB * ) pxCurrentTCB; xTCB = ( TCB_t * ) pxCurrentTCB;
} }
else else
{ {
xTCB = ( tskTCB * ) xTask; xTCB = ( TCB_t * ) xTask;
} }
/* Save the hook function in the TCB. A critical section is required as /* Save the hook function in the TCB. A critical section is required as
@ -1746,25 +2056,27 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
#if ( configUSE_APPLICATION_TASK_TAG == 1 ) #if ( configUSE_APPLICATION_TASK_TAG == 1 )
pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask ) TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
{ {
tskTCB *xTCB; TCB_t *xTCB;
pdTASK_HOOK_CODE xReturn; TaskHookFunction_t xReturn;
/* If xTask is NULL then we are setting our own task hook. */ /* If xTask is NULL then we are setting our own task hook. */
if( xTask == NULL ) if( xTask == NULL )
{ {
xTCB = ( tskTCB * ) pxCurrentTCB; xTCB = ( TCB_t * ) pxCurrentTCB;
} }
else else
{ {
xTCB = ( tskTCB * ) xTask; xTCB = ( TCB_t * ) xTask;
} }
/* Save the hook function in the TCB. A critical section is required as /* Save the hook function in the TCB. A critical section is required as
the value can be accessed from an interrupt. */ the value can be accessed from an interrupt. */
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{
xReturn = xTCB->pxTaskTag; xReturn = xTCB->pxTaskTag;
}
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
return xReturn; return xReturn;
@ -1775,19 +2087,19 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
#if ( configUSE_APPLICATION_TASK_TAG == 1 ) #if ( configUSE_APPLICATION_TASK_TAG == 1 )
portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter ) BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter )
{ {
tskTCB *xTCB; TCB_t *xTCB;
portBASE_TYPE xReturn; BaseType_t xReturn;
/* If xTask is NULL then we are calling our own task hook. */ /* If xTask is NULL then we are calling our own task hook. */
if( xTask == NULL ) if( xTask == NULL )
{ {
xTCB = ( tskTCB * ) pxCurrentTCB; xTCB = ( TCB_t * ) pxCurrentTCB;
} }
else else
{ {
xTCB = ( tskTCB * ) xTask; xTCB = ( TCB_t * ) xTask;
} }
if( xTCB->pxTaskTag != NULL ) if( xTCB->pxTaskTag != NULL )
@ -1807,7 +2119,7 @@ portBASE_TYPE xSwitchRequired = pdFALSE;
void vTaskSwitchContext( void ) void vTaskSwitchContext( void )
{ {
if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE ) if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )
{ {
/* The scheduler is currently suspended - do not allow a context /* The scheduler is currently suspended - do not allow a context
switch. */ switch. */
@ -1815,6 +2127,7 @@ void vTaskSwitchContext( void )
} }
else else
{ {
xYieldPending = pdFALSE;
traceTASK_SWITCHED_OUT(); traceTASK_SWITCHED_OUT();
#if ( configGENERATE_RUN_TIME_STATS == 1 ) #if ( configGENERATE_RUN_TIME_STATS == 1 )
@ -1836,6 +2149,10 @@ void vTaskSwitchContext( void )
{ {
pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime ); pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
ulTaskSwitchedInTime = ulTotalRunTime; ulTaskSwitchedInTime = ulTotalRunTime;
} }
#endif /* configGENERATE_RUN_TIME_STATS */ #endif /* configGENERATE_RUN_TIME_STATS */
@ -1858,43 +2175,49 @@ void vTaskSwitchContext( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vTaskPlaceOnEventList( xList * const pxEventList, portTickType xTicksToWait ) void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )
{ {
portTickType xTimeToWake; TickType_t xTimeToWake;
configASSERT( pxEventList ); configASSERT( pxEventList );
/* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
SCHEDULER SUSPENDED. */ SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
/* Place the event list item of the TCB in the appropriate event list. /* Place the event list item of the TCB in the appropriate event list.
This is placed in the list in priority order so the highest priority task This is placed in the list in priority order so the highest priority task
is the first to be woken by the event. */ is the first to be woken by the event. The queue that contains the event
list is locked, preventing simultaneous access from interrupts. */
vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) ); vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
/* We must remove ourselves from the ready list before adding ourselves /* The task must be removed from from the ready list before it is added to
to the blocked list as the same list item is used for both lists. We have the blocked list as the same list item is used for both lists. Exclusive
exclusive access to the ready lists as the scheduler is locked. */ access to the ready lists guaranteed because the scheduler is locked. */
if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{ {
/* The current task must be in a ready list, so there is no need to /* The current task must be in a ready list, so there is no need to
check, and the port reset macro can be called directly. */ check, and the port reset macro can be called directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
#if ( INCLUDE_vTaskSuspend == 1 ) #if ( INCLUDE_vTaskSuspend == 1 )
{ {
if( xTicksToWait == portMAX_DELAY ) if( xTicksToWait == portMAX_DELAY )
{ {
/* Add ourselves to the suspended task list instead of a delayed task /* Add the task to the suspended task list instead of a delayed task
list to ensure we are not woken by a timing event. We will block list to ensure the task is not woken by a timing event. It will
indefinitely. */ block indefinitely. */
vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) ); vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
} }
else else
{ {
/* Calculate the time at which the task should be woken if the event does /* Calculate the time at which the task should be woken if the event
not occur. This may overflow but this doesn't matter. */ does not occur. This may overflow but this doesn't matter, the
scheduler will handle it. */
xTimeToWake = xTickCount + xTicksToWait; xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake ); prvAddCurrentTaskToDelayedList( xTimeToWake );
} }
@ -1902,7 +2225,74 @@ portTickType xTimeToWake;
#else /* INCLUDE_vTaskSuspend */ #else /* INCLUDE_vTaskSuspend */
{ {
/* Calculate the time at which the task should be woken if the event does /* Calculate the time at which the task should be woken if the event does
not occur. This may overflow but this doesn't matter. */ not occur. This may overflow but this doesn't matter, the scheduler
will handle it. */
xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
#endif /* INCLUDE_vTaskSuspend */
}
/*-----------------------------------------------------------*/
void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait )
{
TickType_t xTimeToWake;
configASSERT( pxEventList );
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
the event groups implementation. */
configASSERT( uxSchedulerSuspended != 0 );
/* Store the item value in the event list item. It is safe to access the
event list item here as interrupts won't access the event list item of a
task that is not in the Blocked state. */
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
/* Place the event list item of the TCB at the end of the appropriate event
list. It is safe to access the event list here because it is part of an
event group implementation - and interrupts don't access event groups
directly (instead they access them indirectly by pending function calls to
the task level). */
vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
/* The task must be removed from the ready list before it is added to the
blocked list. Exclusive access can be assured to the ready list as the
scheduler is locked. */
if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{
/* The current task must be in a ready list, so there is no need to
check, and the port reset macro can be called directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
#if ( INCLUDE_vTaskSuspend == 1 )
{
if( xTicksToWait == portMAX_DELAY )
{
/* Add the task to the suspended task list instead of a delayed task
list to ensure it is not woken by a timing event. It will block
indefinitely. */
vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
}
else
{
/* Calculate the time at which the task should be woken if the event
does not occur. This may overflow but this doesn't matter, the
kernel will manage it correctly. */
xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
}
#else /* INCLUDE_vTaskSuspend */
{
/* Calculate the time at which the task should be woken if the event does
not occur. This may overflow but this doesn't matter, the kernel
will manage it correctly. */
xTimeToWake = xTickCount + xTicksToWait; xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake ); prvAddCurrentTaskToDelayedList( xTimeToWake );
} }
@ -1912,9 +2302,9 @@ portTickType xTimeToWake;
#if configUSE_TIMERS == 1 #if configUSE_TIMERS == 1
void vTaskPlaceOnEventListRestricted( xList * const pxEventList, portTickType xTicksToWait ) void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait )
{ {
portTickType xTimeToWake; TickType_t xTimeToWake;
configASSERT( pxEventList ); configASSERT( pxEventList );
@ -1933,12 +2323,16 @@ portTickType xTimeToWake;
/* We must remove this task from the ready list before adding it to the /* We must remove this task from the ready list before adding it to the
blocked list as the same list item is used for both lists. This blocked list as the same list item is used for both lists. This
function is called form a critical section. */ function is called form a critical section. */
if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{ {
/* The current task must be in a ready list, so there is no need to /* The current task must be in a ready list, so there is no need to
check, and the port reset macro can be called directly. */ check, and the port reset macro can be called directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Calculate the time at which the task should be woken if the event does /* Calculate the time at which the task should be woken if the event does
not occur. This may overflow but this doesn't matter. */ not occur. This may overflow but this doesn't matter. */
@ -1951,47 +2345,50 @@ portTickType xTimeToWake;
#endif /* configUSE_TIMERS */ #endif /* configUSE_TIMERS */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList ) BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
{ {
tskTCB *pxUnblockedTCB; TCB_t *pxUnblockedTCB;
portBASE_TYPE xReturn; BaseType_t xReturn;
/* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be
SCHEDULER SUSPENDED. It can also be called from within an ISR. */ called from a critical section within an ISR. */
/* The event list is sorted in priority order, so we can remove the /* The event list is sorted in priority order, so the first in the list can
first in the list, remove the TCB from the delayed list, and add be removed as it is known to be the highest priority. Remove the TCB from
it to the ready list. the delayed list, and add it to the ready list.
If an event is for a queue that is locked then this function will never If an event is for a queue that is locked then this function will never
get called - the lock count on the queue will get modified instead. This get called - the lock count on the queue will get modified instead. This
means we can always expect exclusive access to the event list here. means exclusive access to the event list is guaranteed here.
This function assumes that a check has already been made to ensure that This function assumes that a check has already been made to ensure that
pxEventList is not empty. */ pxEventList is not empty. */
pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
configASSERT( pxUnblockedTCB ); configASSERT( pxUnblockedTCB );
( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) ); ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
{ {
( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) ); ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
prvAddTaskToReadyList( pxUnblockedTCB ); prvAddTaskToReadyList( pxUnblockedTCB );
} }
else else
{ {
/* We cannot access the delayed or ready lists, so will hold this /* The delayed and ready lists cannot be accessed, so hold this task
task pending until the scheduler is resumed. */ pending until the scheduler is resumed. */
vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) ); vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
} }
if( pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority ) if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
{ {
/* Return true if the task removed from the event list has /* Return true if the task removed from the event list has a higher
a higher priority than the calling task. This allows priority than the calling task. This allows the calling task to know if
the calling task to know if it should force a context it should force a context switch now. */
switch now. */
xReturn = pdTRUE; xReturn = pdTRUE;
/* Mark that a yield is pending in case the user is not using the
"xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
xYieldPending = pdTRUE;
} }
else else
{ {
@ -2002,7 +2399,52 @@ portBASE_TYPE xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut ) BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )
{
TCB_t *pxUnblockedTCB;
BaseType_t xReturn;
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
the event flags implementation. */
configASSERT( uxSchedulerSuspended != pdFALSE );
/* Store the new item value in the event list. */
listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
/* Remove the event list form the event flag. Interrupts do not access
event flags. */
pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem );
configASSERT( pxUnblockedTCB );
( void ) uxListRemove( pxEventListItem );
/* Remove the task from the delayed list and add it to the ready list. The
scheduler is suspended so interrupts will not be accessing the ready
lists. */
( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
prvAddTaskToReadyList( pxUnblockedTCB );
if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
{
/* Return true if the task removed from the event list has
a higher priority than the calling task. This allows
the calling task to know if it should force a context
switch now. */
xReturn = pdTRUE;
/* Mark that a yield is pending in case the user is not using the
"xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
xYieldPending = pdTRUE;
}
else
{
xReturn = pdFALSE;
}
return xReturn;
}
/*-----------------------------------------------------------*/
void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
{ {
configASSERT( pxTimeOut ); configASSERT( pxTimeOut );
pxTimeOut->xOverflowCount = xNumOfOverflows; pxTimeOut->xOverflowCount = xNumOfOverflows;
@ -2010,9 +2452,9 @@ void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait ) BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait )
{ {
portBASE_TYPE xReturn; BaseType_t xReturn;
configASSERT( pxTimeOut ); configASSERT( pxTimeOut );
configASSERT( pxTicksToWait ); configASSERT( pxTicksToWait );
@ -2020,7 +2462,7 @@ portBASE_TYPE xReturn;
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
/* Minor optimisation. The tick count cannot change in this block. */ /* Minor optimisation. The tick count cannot change in this block. */
const portTickType xConstTickCount = xTickCount; const TickType_t xConstTickCount = xTickCount;
#if ( INCLUDE_vTaskSuspend == 1 ) #if ( INCLUDE_vTaskSuspend == 1 )
/* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is
@ -2067,14 +2509,14 @@ void vTaskMissedYield( void )
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask ) UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )
{ {
unsigned portBASE_TYPE uxReturn; UBaseType_t uxReturn;
tskTCB *pxTCB; TCB_t *pxTCB;
if( xTask != NULL ) if( xTask != NULL )
{ {
pxTCB = ( tskTCB * ) xTask; pxTCB = ( TCB_t * ) xTask;
uxReturn = pxTCB->uxTaskNumber; uxReturn = pxTCB->uxTaskNumber;
} }
else else
@ -2090,13 +2532,13 @@ void vTaskMissedYield( void )
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle ) void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle )
{ {
tskTCB *pxTCB; TCB_t *pxTCB;
if( xTask != NULL ) if( xTask != NULL )
{ {
pxTCB = ( tskTCB * ) xTask; pxTCB = ( TCB_t * ) xTask;
pxTCB->uxTaskNumber = uxHandle; pxTCB->uxTaskNumber = uxHandle;
} }
} }
@ -2145,10 +2587,14 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
the list, and an occasional incorrect value will not matter. If the list, and an occasional incorrect value will not matter. If
the ready list at the idle priority contains more than one task the ready list at the idle priority contains more than one task
then a task other than the idle task is ready to execute. */ then a task other than the idle task is ready to execute. */
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( unsigned portBASE_TYPE ) 1 ) if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )
{ {
taskYIELD(); taskYIELD();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
#endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */ #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
@ -2171,7 +2617,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
configUSE_TICKLESS_IDLE to be set to a value other than 1. */ configUSE_TICKLESS_IDLE to be set to a value other than 1. */
#if ( configUSE_TICKLESS_IDLE != 0 ) #if ( configUSE_TICKLESS_IDLE != 0 )
{ {
portTickType xExpectedIdleTime; TickType_t xExpectedIdleTime;
/* It is not desirable to suspend then resume the scheduler on /* It is not desirable to suspend then resume the scheduler on
each iteration of the idle task. Therefore, a preliminary each iteration of the idle task. Therefore, a preliminary
@ -2196,9 +2642,17 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
traceLOW_POWER_IDLE_END(); traceLOW_POWER_IDLE_END();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
( void ) xTaskResumeAll(); ( void ) xTaskResumeAll();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
} }
@ -2226,7 +2680,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
#if configUSE_TIMERS == 0 #if configUSE_TIMERS == 0
{ {
/* The idle task exists in addition to the application tasks. */ /* The idle task exists in addition to the application tasks. */
const unsigned portBASE_TYPE uxNonApplicationTasks = 1; const UBaseType_t uxNonApplicationTasks = 1;
/* If timers are not being used and all the tasks are in the /* If timers are not being used and all the tasks are in the
suspended list (which might mean they have an infinite block suspended list (which might mean they have an infinite block
@ -2236,6 +2690,10 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
{ {
eReturn = eNoTasksWaitingTimeout; eReturn = eNoTasksWaitingTimeout;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
#endif /* configUSE_TIMERS */ #endif /* configUSE_TIMERS */
} }
@ -2245,12 +2703,12 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
{ {
unsigned portBASE_TYPE x; UBaseType_t x;
/* Store the task name in the TCB. */ /* Store the task name in the TCB. */
for( x = ( unsigned portBASE_TYPE ) 0; x < ( unsigned portBASE_TYPE ) configMAX_TASK_NAME_LEN; x++ ) for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
{ {
pxTCB->pcTaskName[ x ] = pcName[ x ]; pxTCB->pcTaskName[ x ] = pcName[ x ];
@ -2261,17 +2719,25 @@ unsigned portBASE_TYPE x;
{ {
break; break;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
/* Ensure the name string is terminated in the case that the string length /* Ensure the name string is terminated in the case that the string length
was greater or equal to configMAX_TASK_NAME_LEN. */ was greater or equal to configMAX_TASK_NAME_LEN. */
pxTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = ( signed char ) '\0'; pxTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
/* This is used as an array index so must ensure it's not too large. First /* This is used as an array index so must ensure it's not too large. First
remove the privilege bit if one is present. */ remove the privilege bit if one is present. */
if( uxPriority >= ( unsigned portBASE_TYPE ) configMAX_PRIORITIES ) if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
{ {
uxPriority = ( unsigned portBASE_TYPE ) configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U; uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
pxTCB->uxPriority = uxPriority; pxTCB->uxPriority = uxPriority;
@ -2284,17 +2750,17 @@ unsigned portBASE_TYPE x;
vListInitialiseItem( &( pxTCB->xGenericListItem ) ); vListInitialiseItem( &( pxTCB->xGenericListItem ) );
vListInitialiseItem( &( pxTCB->xEventListItem ) ); vListInitialiseItem( &( pxTCB->xEventListItem ) );
/* Set the pxTCB as a link back from the xListItem. This is so we can get /* Set the pxTCB as a link back from the ListItem_t. This is so we can get
back to the containing TCB from a generic item in a list. */ back to the containing TCB from a generic item in a list. */
listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB ); listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB );
/* Event lists are always in priority order. */ /* Event lists are always in priority order. */
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( portTickType ) configMAX_PRIORITIES - ( portTickType ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB ); listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB );
#if ( portCRITICAL_NESTING_IN_TCB == 1 ) #if ( portCRITICAL_NESTING_IN_TCB == 1 )
{ {
pxTCB->uxCriticalNesting = ( unsigned portBASE_TYPE ) 0U; pxTCB->uxCriticalNesting = ( UBaseType_t ) 0U;
} }
#endif /* portCRITICAL_NESTING_IN_TCB */ #endif /* portCRITICAL_NESTING_IN_TCB */
@ -2332,9 +2798,9 @@ unsigned portBASE_TYPE x;
#if ( portUSING_MPU_WRAPPERS == 1 ) #if ( portUSING_MPU_WRAPPERS == 1 )
void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions ) void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions )
{ {
tskTCB *pxTCB; TCB_t *pxTCB;
/* If null is passed in here then we are deleting ourselves. */ /* If null is passed in here then we are deleting ourselves. */
pxTCB = prvGetTCBFromHandle( xTaskToModify ); pxTCB = prvGetTCBFromHandle( xTaskToModify );
@ -2347,9 +2813,9 @@ unsigned portBASE_TYPE x;
static void prvInitialiseTaskLists( void ) static void prvInitialiseTaskLists( void )
{ {
unsigned portBASE_TYPE uxPriority; UBaseType_t uxPriority;
for( uxPriority = ( unsigned portBASE_TYPE ) 0U; uxPriority < ( unsigned portBASE_TYPE ) configMAX_PRIORITIES; uxPriority++ ) for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
{ {
vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) ); vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
} }
@ -2381,23 +2847,25 @@ static void prvCheckTasksWaitingTermination( void )
{ {
#if ( INCLUDE_vTaskDelete == 1 ) #if ( INCLUDE_vTaskDelete == 1 )
{ {
portBASE_TYPE xListIsEmpty; BaseType_t xListIsEmpty;
/* ucTasksDeleted is used to prevent vTaskSuspendAll() being called /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
too often in the idle task. */ too often in the idle task. */
while( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0U ) while( uxTasksDeleted > ( UBaseType_t ) 0U )
{ {
vTaskSuspendAll(); vTaskSuspendAll();
{
xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
}
( void ) xTaskResumeAll(); ( void ) xTaskResumeAll();
if( xListIsEmpty == pdFALSE ) if( xListIsEmpty == pdFALSE )
{ {
tskTCB *pxTCB; TCB_t *pxTCB;
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
--uxCurrentNumberOfTasks; --uxCurrentNumberOfTasks;
--uxTasksDeleted; --uxTasksDeleted;
@ -2406,13 +2874,17 @@ static void prvCheckTasksWaitingTermination( void )
prvDeleteTCB( pxTCB ); prvDeleteTCB( pxTCB );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
} }
#endif /* vTaskDelete */ #endif /* vTaskDelete */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake ) static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake )
{ {
/* The list item will be inserted in wake time order. */ /* The list item will be inserted in wake time order. */
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
@ -2424,7 +2896,7 @@ static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake )
} }
else else
{ {
/* The wake time has not overflowed, so we can use the current block list. */ /* The wake time has not overflowed, so the current block list is used. */
vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) ); vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
/* If the task entering the blocked state was placed at the head of the /* If the task entering the blocked state was placed at the head of the
@ -2434,24 +2906,28 @@ static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake )
{ {
xNextTaskUnblockTime = xTimeToWake; xNextTaskUnblockTime = xTimeToWake;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer )
{ {
tskTCB *pxNewTCB; TCB_t *pxNewTCB;
/* Allocate space for the TCB. Where the memory comes from depends on /* Allocate space for the TCB. Where the memory comes from depends on
the implementation of the port malloc function. */ the implementation of the port malloc function. */
pxNewTCB = ( tskTCB * ) pvPortMalloc( sizeof( tskTCB ) ); pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
if( pxNewTCB != NULL ) if( pxNewTCB != NULL )
{ {
/* Allocate space for the stack used by the task being created. /* Allocate space for the stack used by the task being created.
The base of the stack memory stored in the TCB so the task can The base of the stack memory stored in the TCB so the task can
be deleted later if required. */ be deleted later if required. */
pxNewTCB->pxStack = ( portSTACK_TYPE * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( portSTACK_TYPE ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
if( pxNewTCB->pxStack == NULL ) if( pxNewTCB->pxStack == NULL )
{ {
@ -2461,8 +2937,13 @@ tskTCB *pxNewTCB;
} }
else else
{ {
/* Just to help debugging. */ /* Avoid dependency on memset() if it is not required. */
( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( portSTACK_TYPE ) ); #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
{
/* Just to help debugging. */
( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( StackType_t ) );
}
#endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */
} }
} }
@ -2472,29 +2953,44 @@ tskTCB *pxNewTCB;
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
static unsigned portBASE_TYPE prvListTaskWithinSingleList( xTaskStatusType *pxTaskStatusArray, xList *pxList, eTaskState eState ) static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )
{ {
volatile tskTCB *pxNextTCB, *pxFirstTCB; volatile TCB_t *pxNextTCB, *pxFirstTCB;
unsigned portBASE_TYPE uxTask = 0; UBaseType_t uxTask = 0;
if( listCURRENT_LIST_LENGTH( pxList ) > ( unsigned portBASE_TYPE ) 0 ) if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
{ {
listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
/* Populate an xTaskStatusType structure within the /* Populate an TaskStatus_t structure within the
pxTaskStatusArray array for each task that is referenced from pxTaskStatusArray array for each task that is referenced from
pxList. See the definition of xTaskStatusType in task.h for the pxList. See the definition of TaskStatus_t in task.h for the
meaning of each xTaskStatusType structure member. */ meaning of each TaskStatus_t structure member. */
do do
{ {
listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
pxTaskStatusArray[ uxTask ].xHandle = ( xTaskHandle ) pxNextTCB; pxTaskStatusArray[ uxTask ].xHandle = ( TaskHandle_t ) pxNextTCB;
pxTaskStatusArray[ uxTask ].pcTaskName = ( const signed char * ) &( pxNextTCB->pcTaskName [ 0 ] ); pxTaskStatusArray[ uxTask ].pcTaskName = ( const char * ) &( pxNextTCB->pcTaskName [ 0 ] );
pxTaskStatusArray[ uxTask ].xTaskNumber = pxNextTCB->uxTCBNumber; pxTaskStatusArray[ uxTask ].xTaskNumber = pxNextTCB->uxTCBNumber;
pxTaskStatusArray[ uxTask ].eCurrentState = eState; pxTaskStatusArray[ uxTask ].eCurrentState = eState;
pxTaskStatusArray[ uxTask ].uxCurrentPriority = pxNextTCB->uxPriority; pxTaskStatusArray[ uxTask ].uxCurrentPriority = pxNextTCB->uxPriority;
#if ( INCLUDE_vTaskSuspend == 1 )
{
/* If the task is in the suspended list then there is a chance
it is actually just blocked indefinitely - so really it should
be reported as being in the Blocked state. */
if( eState == eSuspended )
{
if( listLIST_ITEM_CONTAINER( &( pxNextTCB->xEventListItem ) ) != NULL )
{
pxTaskStatusArray[ uxTask ].eCurrentState = eBlocked;
}
}
}
#endif /* INCLUDE_vTaskSuspend */
#if ( configUSE_MUTEXES == 1 ) #if ( configUSE_MUTEXES == 1 )
{ {
pxTaskStatusArray[ uxTask ].uxBasePriority = pxNextTCB->uxBasePriority; pxTaskStatusArray[ uxTask ].uxBasePriority = pxNextTCB->uxBasePriority;
@ -2517,11 +3013,11 @@ tskTCB *pxNewTCB;
#if ( portSTACK_GROWTH > 0 ) #if ( portSTACK_GROWTH > 0 )
{ {
ppxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxEndOfStack ); pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxEndOfStack );
} }
#else #else
{ {
pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack ); pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxStack );
} }
#endif #endif
@ -2529,6 +3025,10 @@ tskTCB *pxNewTCB;
} while( pxNextTCB != pxFirstTCB ); } while( pxNextTCB != pxFirstTCB );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
return uxTask; return uxTask;
} }
@ -2538,19 +3038,19 @@ tskTCB *pxNewTCB;
#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
static unsigned short prvTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
{ {
register unsigned short usCount = 0U; uint32_t ulCount = 0U;
while( *pucStackByte == tskSTACK_FILL_BYTE ) while( *pucStackByte == tskSTACK_FILL_BYTE )
{ {
pucStackByte -= portSTACK_GROWTH; pucStackByte -= portSTACK_GROWTH;
usCount++; ulCount++;
} }
usCount /= sizeof( portSTACK_TYPE ); ulCount /= ( uint32_t ) sizeof( StackType_t );
return usCount; return ( uint16_t ) ulCount;
} }
#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */ #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */
@ -2558,25 +3058,25 @@ tskTCB *pxNewTCB;
#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask ) UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
{ {
tskTCB *pxTCB; TCB_t *pxTCB;
unsigned char *pcEndOfStack; uint8_t *pucEndOfStack;
unsigned portBASE_TYPE uxReturn; UBaseType_t uxReturn;
pxTCB = prvGetTCBFromHandle( xTask ); pxTCB = prvGetTCBFromHandle( xTask );
#if portSTACK_GROWTH < 0 #if portSTACK_GROWTH < 0
{ {
pcEndOfStack = ( unsigned char * ) pxTCB->pxStack; pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
} }
#else #else
{ {
pcEndOfStack = ( unsigned char * ) pxTCB->pxEndOfStack; pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
} }
#endif #endif
uxReturn = ( unsigned portBASE_TYPE ) prvTaskCheckFreeStackSpace( pcEndOfStack ); uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );
return uxReturn; return uxReturn;
} }
@ -2586,7 +3086,7 @@ tskTCB *pxNewTCB;
#if ( INCLUDE_vTaskDelete == 1 ) #if ( INCLUDE_vTaskDelete == 1 )
static void prvDeleteTCB( tskTCB *pxTCB ) static void prvDeleteTCB( TCB_t *pxTCB )
{ {
/* This call is required specifically for the TriCore port. It must be /* This call is required specifically for the TriCore port. It must be
above the vPortFree() calls. The call is also used by ports/demos that above the vPortFree() calls. The call is also used by ports/demos that
@ -2602,11 +3102,36 @@ tskTCB *pxNewTCB;
#endif /* INCLUDE_vTaskDelete */ #endif /* INCLUDE_vTaskDelete */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvResetNextTaskUnblockTime( void )
{
TCB_t *pxTCB;
if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
{
/* The new current delayed list is empty. Set
xNextTaskUnblockTime to the maximum possible value so it is
extremely unlikely that the
if( xTickCount >= xNextTaskUnblockTime ) test will pass until
there is an item in the delayed list. */
xNextTaskUnblockTime = portMAX_DELAY;
}
else
{
/* The new current delayed list is not empty, get the value of
the item at the head of the delayed list. This is the time at
which the task at the head of the delayed list should be removed
from the Blocked state. */
( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xGenericListItem ) );
}
}
/*-----------------------------------------------------------*/
#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
xTaskHandle xTaskGetCurrentTaskHandle( void ) TaskHandle_t xTaskGetCurrentTaskHandle( void )
{ {
xTaskHandle xReturn; TaskHandle_t xReturn;
/* A critical section is not required as this is not called from /* A critical section is not required as this is not called from
an interrupt and the current TCB will always be the same for any an interrupt and the current TCB will always be the same for any
@ -2621,9 +3146,9 @@ tskTCB *pxNewTCB;
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
portBASE_TYPE xTaskGetSchedulerState( void ) BaseType_t xTaskGetSchedulerState( void )
{ {
portBASE_TYPE xReturn; BaseType_t xReturn;
if( xSchedulerRunning == pdFALSE ) if( xSchedulerRunning == pdFALSE )
{ {
@ -2631,7 +3156,7 @@ tskTCB *pxNewTCB;
} }
else else
{ {
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
{ {
xReturn = taskSCHEDULER_RUNNING; xReturn = taskSCHEDULER_RUNNING;
} }
@ -2649,9 +3174,9 @@ tskTCB *pxNewTCB;
#if ( configUSE_MUTEXES == 1 ) #if ( configUSE_MUTEXES == 1 )
void vTaskPriorityInherit( xTaskHandle const pxMutexHolder ) void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
{ {
tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
/* If the mutex was given back by an interrupt while the queue was /* If the mutex was given back by an interrupt while the queue was
locked then the mutex holder might now be NULL. */ locked then the mutex holder might now be NULL. */
@ -2659,17 +3184,30 @@ tskTCB *pxNewTCB;
{ {
if( pxTCB->uxPriority < pxCurrentTCB->uxPriority ) if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
{ {
/* Adjust the mutex holder state to account for its new priority. */ /* Adjust the mutex holder state to account for its new
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( portTickType ) configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ priority. Only reset the event list item value if the value is
not being used for anything else. */
if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
{
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* If the task being modified is in the ready state it will need to /* If the task being modified is in the ready state it will need to
be moved into a new list. */ be moved into a new list. */
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE ) if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
{ {
if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{ {
taskRESET_READY_PRIORITY( pxTCB->uxPriority ); taskRESET_READY_PRIORITY( pxTCB->uxPriority );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Inherit the priority before being moved into the new list. */ /* Inherit the priority before being moved into the new list. */
pxTCB->uxPriority = pxCurrentTCB->uxPriority; pxTCB->uxPriority = pxCurrentTCB->uxPriority;
@ -2683,6 +3221,14 @@ tskTCB *pxNewTCB;
traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority ); traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
@ -2691,9 +3237,9 @@ tskTCB *pxNewTCB;
#if ( configUSE_MUTEXES == 1 ) #if ( configUSE_MUTEXES == 1 )
void vTaskPriorityDisinherit( xTaskHandle const pxMutexHolder ) void vTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )
{ {
tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
if( pxMutexHolder != NULL ) if( pxMutexHolder != NULL )
{ {
@ -2701,18 +3247,40 @@ tskTCB *pxNewTCB;
{ {
/* We must be the running task to be able to give the mutex back. /* We must be the running task to be able to give the mutex back.
Remove ourselves from the ready list we currently appear in. */ Remove ourselves from the ready list we currently appear in. */
if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{ {
taskRESET_READY_PRIORITY( pxTCB->uxPriority ); taskRESET_READY_PRIORITY( pxTCB->uxPriority );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Disinherit the priority before adding the task into the new /* Disinherit the priority before adding the task into the new
ready list. */ ready list. */
traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority ); traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
pxTCB->uxPriority = pxTCB->uxBasePriority; pxTCB->uxPriority = pxTCB->uxBasePriority;
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( portTickType ) configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
/* Only reset the event list item value if the value is not
being used for anything else. */
if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
{
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
}
else
{
mtCOVERAGE_TEST_MARKER();
}
prvAddTaskToReadyList( pxTCB ); prvAddTaskToReadyList( pxTCB );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
@ -2729,6 +3297,10 @@ tskTCB *pxNewTCB;
{ {
( pxCurrentTCB->uxCriticalNesting )++; ( pxCurrentTCB->uxCriticalNesting )++;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
#endif /* portCRITICAL_NESTING_IN_TCB */ #endif /* portCRITICAL_NESTING_IN_TCB */
@ -2748,7 +3320,19 @@ tskTCB *pxNewTCB;
{ {
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
@ -2757,10 +3341,10 @@ tskTCB *pxNewTCB;
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) )
void vTaskList( signed char *pcWriteBuffer ) void vTaskList( char * pcWriteBuffer )
{ {
xTaskStatusType *pxTaskStatusArray; TaskStatus_t *pxTaskStatusArray;
volatile unsigned portBASE_TYPE uxArraySize, x; volatile UBaseType_t uxArraySize, x;
char cStatus; char cStatus;
/* /*
@ -2796,7 +3380,7 @@ tskTCB *pxNewTCB;
uxArraySize = uxCurrentNumberOfTasks; uxArraySize = uxCurrentNumberOfTasks;
/* Allocate an array index for each task. */ /* Allocate an array index for each task. */
pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( xTaskStatusType ) ); pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
if( pxTaskStatusArray != NULL ) if( pxTaskStatusArray != NULL )
{ {
@ -2826,25 +3410,35 @@ tskTCB *pxNewTCB;
break; break;
} }
sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxTaskStatusArray[ x ].pcTaskName, cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber ); sprintf( pcWriteBuffer, "%s\t\t%c\t%u\t%u\t%u\r\n", pxTaskStatusArray[ x ].pcTaskName, cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber );
pcWriteBuffer += strlen( ( char * ) pcWriteBuffer ); pcWriteBuffer += strlen( pcWriteBuffer );
} }
/* Free the array again. */ /* Free the array again. */
vPortFree( pxTaskStatusArray ); vPortFree( pxTaskStatusArray );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
#endif /* configUSE_TRACE_FACILITY */ #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) */
/*----------------------------------------------------------*/ /*----------------------------------------------------------*/
#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) )
void vTaskGetRunTimeStats( signed char *pcWriteBuffer ) void vTaskGetRunTimeStats( char *pcWriteBuffer )
{ {
xTaskStatusType *pxTaskStatusArray; TaskStatus_t *pxTaskStatusArray;
volatile unsigned portBASE_TYPE uxArraySize, x; volatile UBaseType_t uxArraySize, x;
unsigned long ulTotalTime, ulStatsAsPercentage; uint32_t ulTotalTime, ulStatsAsPercentage;
#if( configUSE_TRACE_FACILITY != 1 )
{
#error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats().
}
#endif
/* /*
* PLEASE NOTE: * PLEASE NOTE:
@ -2879,7 +3473,7 @@ tskTCB *pxNewTCB;
uxArraySize = uxCurrentNumberOfTasks; uxArraySize = uxCurrentNumberOfTasks;
/* Allocate an array index for each task. */ /* Allocate an array index for each task. */
pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( xTaskStatusType ) ); pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
if( pxTaskStatusArray != NULL ) if( pxTaskStatusArray != NULL )
{ {
@ -2904,13 +3498,13 @@ tskTCB *pxNewTCB;
{ {
#ifdef portLU_PRINTF_SPECIFIER_REQUIRED #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
{ {
sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
} }
#else #else
{ {
/* sizeof( int ) == sizeof( long ) so a smaller /* sizeof( int ) == sizeof( long ) so a smaller
printf() library can be used. */ printf() library can be used. */
sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%u\t\t%u%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); sprintf( pcWriteBuffer, "%s\t\t%u\t\t%u%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );
} }
#endif #endif
} }
@ -2920,27 +3514,52 @@ tskTCB *pxNewTCB;
consumed less than 1% of the total run time. */ consumed less than 1% of the total run time. */
#ifdef portLU_PRINTF_SPECIFIER_REQUIRED #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
{ {
sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter ); sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );
} }
#else #else
{ {
/* sizeof( int ) == sizeof( long ) so a smaller /* sizeof( int ) == sizeof( long ) so a smaller
printf() library can be used. */ printf() library can be used. */
sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%u\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); sprintf( pcWriteBuffer, "%s\t\t%u\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter );
} }
#endif #endif
} }
pcWriteBuffer += strlen( ( char * ) pcWriteBuffer ); pcWriteBuffer += strlen( pcWriteBuffer );
} }
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Free the array again. */ /* Free the array again. */
vPortFree( pxTaskStatusArray ); vPortFree( pxTaskStatusArray );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
#endif /* configGENERATE_RUN_TIME_STATS */ #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) */
/*-----------------------------------------------------------*/
TickType_t uxTaskResetEventItemValue( void )
{
TickType_t uxReturn;
uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );
/* Reset the event list item to its normal value - so it can be used with
queues and semaphores. */
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
return uxReturn;
}
/*-----------------------------------------------------------*/
#ifdef FREERTOS_MODULE_TEST
#include "tasks_test_access_functions.h"
#endif

View File

@ -1,5 +1,6 @@
/* /*
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -75,6 +76,10 @@ task.h is included from an application file. */
#include "queue.h" #include "queue.h"
#include "timers.h" #include "timers.h"
#if ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 0 )
#error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available.
#endif
/* Lint e961 and e750 are suppressed as a MISRA exception justified because the /* Lint e961 and e750 are suppressed as a MISRA exception justified because the
MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
header files above, but not in this file, in order to generate the correct header files above, but not in this file, in order to generate the correct
@ -89,45 +94,79 @@ configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
#if ( configUSE_TIMERS == 1 ) #if ( configUSE_TIMERS == 1 )
/* Misc definitions. */ /* Misc definitions. */
#define tmrNO_DELAY ( portTickType ) 0U #define tmrNO_DELAY ( TickType_t ) 0U
/* The definition of the timers themselves. */ /* The definition of the timers themselves. */
typedef struct tmrTimerControl typedef struct tmrTimerControl
{ {
const signed char *pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ const char *pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
xListItem xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */ ListItem_t xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */
portTickType xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */ TickType_t xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */
unsigned portBASE_TYPE uxAutoReload; /*<< Set to pdTRUE if the timer should be automatically restarted once expired. Set to pdFALSE if the timer is, in effect, a one shot timer. */ UBaseType_t uxAutoReload; /*<< Set to pdTRUE if the timer should be automatically restarted once expired. Set to pdFALSE if the timer is, in effect, a one-shot timer. */
void *pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */ void *pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */
tmrTIMER_CALLBACK pxCallbackFunction; /*<< The function that will be called when the timer expires. */ TimerCallbackFunction_t pxCallbackFunction; /*<< The function that will be called when the timer expires. */
#if( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxTimerNumber; /*<< An ID assigned by trace tools such as FreeRTOS+Trace */
#endif
} xTIMER; } xTIMER;
/* The definition of messages that can be sent and received on the timer /* The old xTIMER name is maintained above then typedefed to the new Timer_t
queue. */ name below to enable the use of older kernel aware debuggers. */
typedef xTIMER Timer_t;
/* The definition of messages that can be sent and received on the timer queue.
Two types of message can be queued - messages that manipulate a software timer,
and messages that request the execution of a non-timer related callback. The
two message types are defined in two separate structures, xTimerParametersType
and xCallbackParametersType respectively. */
typedef struct tmrTimerParameters
{
TickType_t xMessageValue; /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */
Timer_t * pxTimer; /*<< The timer to which the command will be applied. */
} TimerParameter_t;
typedef struct tmrCallbackParameters
{
PendedFunction_t pxCallbackFunction; /* << The callback function to execute. */
void *pvParameter1; /* << The value that will be used as the callback functions first parameter. */
uint32_t ulParameter2; /* << The value that will be used as the callback functions second parameter. */
} CallbackParameters_t;
/* The structure that contains the two message types, along with an identifier
that is used to determine which message type is valid. */
typedef struct tmrTimerQueueMessage typedef struct tmrTimerQueueMessage
{ {
portBASE_TYPE xMessageID; /*<< The command being sent to the timer service task. */ BaseType_t xMessageID; /*<< The command being sent to the timer service task. */
portTickType xMessageValue; /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */ union
xTIMER * pxTimer; /*<< The timer to which the command will be applied. */ {
} xTIMER_MESSAGE; TimerParameter_t xTimerParameters;
/* Don't include xCallbackParameters if it is not going to be used as
it makes the structure (and therefore the timer queue) larger. */
#if ( INCLUDE_xTimerPendFunctionCall == 1 )
CallbackParameters_t xCallbackParameters;
#endif /* INCLUDE_xTimerPendFunctionCall */
} u;
} DaemonTaskMessage_t;
/*lint -e956 A manual analysis and inspection has been used to determine which /*lint -e956 A manual analysis and inspection has been used to determine which
static variables must be declared volatile. */ static variables must be declared volatile. */
/* The list in which active timers are stored. Timers are referenced in expire /* The list in which active timers are stored. Timers are referenced in expire
time order, with the nearest expiry time at the front of the list. Only the time order, with the nearest expiry time at the front of the list. Only the
timer service task is allowed to access xActiveTimerList. */ timer service task is allowed to access these lists. */
PRIVILEGED_DATA static xList xActiveTimerList1; PRIVILEGED_DATA static List_t xActiveTimerList1;
PRIVILEGED_DATA static xList xActiveTimerList2; PRIVILEGED_DATA static List_t xActiveTimerList2;
PRIVILEGED_DATA static xList *pxCurrentTimerList; PRIVILEGED_DATA static List_t *pxCurrentTimerList;
PRIVILEGED_DATA static xList *pxOverflowTimerList; PRIVILEGED_DATA static List_t *pxOverflowTimerList;
/* A queue that is used to send commands to the timer service task. */ /* A queue that is used to send commands to the timer service task. */
PRIVILEGED_DATA static xQueueHandle xTimerQueue = NULL; PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;
#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )
PRIVILEGED_DATA static xTaskHandle xTimerTaskHandle = NULL; PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;
#endif #endif
@ -158,25 +197,25 @@ static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION;
* Insert the timer into either xActiveTimerList1, or xActiveTimerList2, * Insert the timer into either xActiveTimerList1, or xActiveTimerList2,
* depending on if the expire time causes a timer counter overflow. * depending on if the expire time causes a timer counter overflow.
*/ */
static portBASE_TYPE prvInsertTimerInActiveList( xTIMER *pxTimer, portTickType xNextExpiryTime, portTickType xTimeNow, portTickType xCommandTime ) PRIVILEGED_FUNCTION; static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) PRIVILEGED_FUNCTION;
/* /*
* An active timer has reached its expire time. Reload the timer if it is an * An active timer has reached its expire time. Reload the timer if it is an
* auto reload timer, then call its callback. * auto reload timer, then call its callback.
*/ */
static void prvProcessExpiredTimer( portTickType xNextExpireTime, portTickType xTimeNow ) PRIVILEGED_FUNCTION; static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) PRIVILEGED_FUNCTION;
/* /*
* The tick count has overflowed. Switch the timer lists after ensuring the * The tick count has overflowed. Switch the timer lists after ensuring the
* current timer list does not still reference some timers. * current timer list does not still reference some timers.
*/ */
static void prvSwitchTimerLists( portTickType xLastTime ) PRIVILEGED_FUNCTION; static void prvSwitchTimerLists( void ) PRIVILEGED_FUNCTION;
/* /*
* Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE * Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE
* if a tick count overflow occurred since prvSampleTimeNow() was last called. * if a tick count overflow occurred since prvSampleTimeNow() was last called.
*/ */
static portTickType prvSampleTimeNow( portBASE_TYPE *pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION; static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION;
/* /*
* If the timer list contains any active timers then return the expire time of * If the timer list contains any active timers then return the expire time of
@ -184,19 +223,19 @@ static portTickType prvSampleTimeNow( portBASE_TYPE *pxTimerListsWereSwitched )
* timer list does not contain any timers then return 0 and set *pxListWasEmpty * timer list does not contain any timers then return 0 and set *pxListWasEmpty
* to pdTRUE. * to pdTRUE.
*/ */
static portTickType prvGetNextExpireTime( portBASE_TYPE *pxListWasEmpty ) PRIVILEGED_FUNCTION; static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIVILEGED_FUNCTION;
/* /*
* If a timer has expired, process it. Otherwise, block the timer service task * If a timer has expired, process it. Otherwise, block the timer service task
* until either a timer does expire or a command is received. * until either a timer does expire or a command is received.
*/ */
static void prvProcessTimerOrBlockTask( portTickType xNextExpireTime, portBASE_TYPE xListWasEmpty ) PRIVILEGED_FUNCTION; static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, const BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
portBASE_TYPE xTimerCreateTimerTask( void ) BaseType_t xTimerCreateTimerTask( void )
{ {
portBASE_TYPE xReturn = pdFAIL; BaseType_t xReturn = pdFAIL;
/* This function is called when the scheduler is started if /* This function is called when the scheduler is started if
configUSE_TIMERS is set to 1. Check that the infrastructure used by the configUSE_TIMERS is set to 1. Check that the infrastructure used by the
@ -210,34 +249,37 @@ portBASE_TYPE xReturn = pdFAIL;
{ {
/* Create the timer task, storing its handle in xTimerTaskHandle so /* Create the timer task, storing its handle in xTimerTaskHandle so
it can be returned by the xTimerGetTimerDaemonTaskHandle() function. */ it can be returned by the xTimerGetTimerDaemonTaskHandle() function. */
xReturn = xTaskCreate( prvTimerTask, ( const signed char * ) "Tmr Svc", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( unsigned portBASE_TYPE ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, &xTimerTaskHandle ); xReturn = xTaskCreate( prvTimerTask, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, &xTimerTaskHandle );
} }
#else #else
{ {
/* Create the timer task without storing its handle. */ /* Create the timer task without storing its handle. */
xReturn = xTaskCreate( prvTimerTask, ( const signed char * ) "Tmr Svc", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( unsigned portBASE_TYPE ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, NULL); xReturn = xTaskCreate( prvTimerTask, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, NULL);
} }
#endif #endif
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
configASSERT( xReturn ); configASSERT( xReturn );
return xReturn; return xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
xTimerHandle xTimerCreate( const signed char * const pcTimerName, portTickType xTimerPeriodInTicks, unsigned portBASE_TYPE uxAutoReload, void *pvTimerID, tmrTIMER_CALLBACK pxCallbackFunction ) TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
{ {
xTIMER *pxNewTimer; Timer_t *pxNewTimer;
/* Allocate the timer structure. */ /* Allocate the timer structure. */
if( xTimerPeriodInTicks == ( portTickType ) 0U ) if( xTimerPeriodInTicks == ( TickType_t ) 0U )
{ {
pxNewTimer = NULL; pxNewTimer = NULL;
configASSERT( ( xTimerPeriodInTicks > 0 ) );
} }
else else
{ {
pxNewTimer = ( xTIMER * ) pvPortMalloc( sizeof( xTIMER ) ); pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) );
if( pxNewTimer != NULL ) if( pxNewTimer != NULL )
{ {
/* Ensure the infrastructure used by the timer service task has been /* Ensure the infrastructure used by the timer service task has been
@ -260,14 +302,17 @@ xTIMER *pxNewTimer;
} }
} }
return ( xTimerHandle ) pxNewTimer; /* 0 is not a valid value for xTimerPeriodInTicks. */
configASSERT( ( xTimerPeriodInTicks > 0 ) );
return ( TimerHandle_t ) pxNewTimer;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
portBASE_TYPE xTimerGenericCommand( xTimerHandle xTimer, portBASE_TYPE xCommandID, portTickType xOptionalValue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portTickType xBlockTime ) BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait )
{ {
portBASE_TYPE xReturn = pdFAIL; BaseType_t xReturn = pdFAIL;
xTIMER_MESSAGE xMessage; DaemonTaskMessage_t xMessage;
/* Send a message to the timer service task to perform a particular action /* Send a message to the timer service task to perform a particular action
on a particular timer definition. */ on a particular timer definition. */
@ -275,14 +320,14 @@ xTIMER_MESSAGE xMessage;
{ {
/* Send a command to the timer service task to start the xTimer timer. */ /* Send a command to the timer service task to start the xTimer timer. */
xMessage.xMessageID = xCommandID; xMessage.xMessageID = xCommandID;
xMessage.xMessageValue = xOptionalValue; xMessage.u.xTimerParameters.xMessageValue = xOptionalValue;
xMessage.pxTimer = ( xTIMER * ) xTimer; xMessage.u.xTimerParameters.pxTimer = ( Timer_t * ) xTimer;
if( pxHigherPriorityTaskWoken == NULL ) if( xCommandID < tmrFIRST_FROM_ISR_COMMAND )
{ {
if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING ) if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING )
{ {
xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xBlockTime ); xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait );
} }
else else
{ {
@ -296,6 +341,10 @@ xTIMER_MESSAGE xMessage;
traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn ); traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn );
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
return xReturn; return xReturn;
} }
@ -303,7 +352,7 @@ xTIMER_MESSAGE xMessage;
#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )
xTaskHandle xTimerGetTimerDaemonTaskHandle( void ) TaskHandle_t xTimerGetTimerDaemonTaskHandle( void )
{ {
/* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been
started, then xTimerTaskHandle will be NULL. */ started, then xTimerTaskHandle will be NULL. */
@ -314,46 +363,50 @@ xTIMER_MESSAGE xMessage;
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvProcessExpiredTimer( portTickType xNextExpireTime, portTickType xTimeNow ) static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow )
{ {
xTIMER *pxTimer; BaseType_t xResult;
portBASE_TYPE xResult; Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );
/* Remove the timer from the list of active timers. A check has already /* Remove the timer from the list of active timers. A check has already
been performed to ensure the list is not empty. */ been performed to ensure the list is not empty. */
pxTimer = ( xTIMER * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );
( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
traceTIMER_EXPIRED( pxTimer ); traceTIMER_EXPIRED( pxTimer );
/* If the timer is an auto reload timer then calculate the next /* If the timer is an auto reload timer then calculate the next
expiry time and re-insert the timer in the list of active timers. */ expiry time and re-insert the timer in the list of active timers. */
if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE ) if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )
{ {
/* This is the only time a timer is inserted into a list using /* The timer is inserted into a list using a time relative to anything
a time relative to anything other than the current time. It other than the current time. It will therefore be inserted into the
will therefore be inserted into the correct list relative to correct list relative to the time this task thinks it is now. */
the time this task thinks it is now, even if a command to
switch lists due to a tick count overflow is already waiting in
the timer queue. */
if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) == pdTRUE ) if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) == pdTRUE )
{ {
/* The timer expired before it was added to the active timer /* The timer expired before it was added to the active timer
list. Reload it now. */ list. Reload it now. */
xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xNextExpireTime, NULL, tmrNO_DELAY ); xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY );
configASSERT( xResult ); configASSERT( xResult );
( void ) xResult; ( void ) xResult;
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
/* Call the timer callback. */ /* Call the timer callback. */
pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer ); pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvTimerTask( void *pvParameters ) static void prvTimerTask( void *pvParameters )
{ {
portTickType xNextExpireTime; TickType_t xNextExpireTime;
portBASE_TYPE xListWasEmpty; BaseType_t xListWasEmpty;
/* Just to avoid compiler warnings. */ /* Just to avoid compiler warnings. */
( void ) pvParameters; ( void ) pvParameters;
@ -374,10 +427,10 @@ portBASE_TYPE xListWasEmpty;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvProcessTimerOrBlockTask( portTickType xNextExpireTime, portBASE_TYPE xListWasEmpty ) static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, const BaseType_t xListWasEmpty )
{ {
portTickType xTimeNow; TickType_t xTimeNow;
portBASE_TYPE xTimerListsWereSwitched; BaseType_t xTimerListsWereSwitched;
vTaskSuspendAll(); vTaskSuspendAll();
{ {
@ -385,7 +438,7 @@ portBASE_TYPE xTimerListsWereSwitched;
has expired or not. If obtaining the time causes the lists to switch has expired or not. If obtaining the time causes the lists to switch
then don't process this timer as any timers that remained in the list then don't process this timer as any timers that remained in the list
when the lists were switched will have been processed within the when the lists were switched will have been processed within the
prvSampelTimeNow() function. */ prvSampleTimeNow() function. */
xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );
if( xTimerListsWereSwitched == pdFALSE ) if( xTimerListsWereSwitched == pdFALSE )
{ {
@ -413,6 +466,10 @@ portBASE_TYPE xTimerListsWereSwitched;
to block. */ to block. */
portYIELD_WITHIN_API(); portYIELD_WITHIN_API();
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
} }
else else
@ -423,9 +480,9 @@ portBASE_TYPE xTimerListsWereSwitched;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static portTickType prvGetNextExpireTime( portBASE_TYPE *pxListWasEmpty ) static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty )
{ {
portTickType xNextExpireTime; TickType_t xNextExpireTime;
/* Timers are listed in expiry time order, with the head of the list /* Timers are listed in expiry time order, with the head of the list
referencing the task that will expire first. Obtain the time at which referencing the task that will expire first. Obtain the time at which
@ -442,23 +499,23 @@ portTickType xNextExpireTime;
else else
{ {
/* Ensure the task unblocks when the tick count rolls over. */ /* Ensure the task unblocks when the tick count rolls over. */
xNextExpireTime = ( portTickType ) 0U; xNextExpireTime = ( TickType_t ) 0U;
} }
return xNextExpireTime; return xNextExpireTime;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static portTickType prvSampleTimeNow( portBASE_TYPE *pxTimerListsWereSwitched ) static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched )
{ {
portTickType xTimeNow; TickType_t xTimeNow;
PRIVILEGED_DATA static portTickType xLastTime = ( portTickType ) 0U; /*lint !e956 Variable is only accessible to one task. */ PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U; /*lint !e956 Variable is only accessible to one task. */
xTimeNow = xTaskGetTickCount(); xTimeNow = xTaskGetTickCount();
if( xTimeNow < xLastTime ) if( xTimeNow < xLastTime )
{ {
prvSwitchTimerLists( xLastTime ); prvSwitchTimerLists();
*pxTimerListsWereSwitched = pdTRUE; *pxTimerListsWereSwitched = pdTRUE;
} }
else else
@ -472,9 +529,9 @@ PRIVILEGED_DATA static portTickType xLastTime = ( portTickType ) 0U; /*lint !e95
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static portBASE_TYPE prvInsertTimerInActiveList( xTIMER *pxTimer, portTickType xNextExpiryTime, portTickType xTimeNow, portTickType xCommandTime ) static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime )
{ {
portBASE_TYPE xProcessTimerNow = pdFALSE; BaseType_t xProcessTimerNow = pdFALSE;
listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime ); listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime );
listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer );
@ -515,84 +572,136 @@ portBASE_TYPE xProcessTimerNow = pdFALSE;
static void prvProcessReceivedCommands( void ) static void prvProcessReceivedCommands( void )
{ {
xTIMER_MESSAGE xMessage; DaemonTaskMessage_t xMessage;
xTIMER *pxTimer; Timer_t *pxTimer;
portBASE_TYPE xTimerListsWereSwitched, xResult; BaseType_t xTimerListsWereSwitched, xResult;
portTickType xTimeNow; TickType_t xTimeNow;
while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) /*lint !e603 xMessage does not have to be initialised as it is passed out, not in, and it is not used unless xQueueReceive() returns pdTRUE. */ while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) /*lint !e603 xMessage does not have to be initialised as it is passed out, not in, and it is not used unless xQueueReceive() returns pdTRUE. */
{ {
pxTimer = xMessage.pxTimer; #if ( INCLUDE_xTimerPendFunctionCall == 1 )
if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE )
{ {
/* The timer is in a list, remove it. */ /* Negative commands are pended function calls rather than timer
( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); commands. */
if( xMessage.xMessageID < 0 )
{
const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters );
/* The timer uses the xCallbackParameters member to request a
callback be executed. Check the callback is not NULL. */
configASSERT( pxCallback );
/* Call the function. */
pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
#endif /* INCLUDE_xTimerPendFunctionCall */
traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.xMessageValue ); /* Commands that are positive are timer commands rather than pended
function calls. */
/* In this case the xTimerListsWereSwitched parameter is not used, but if( xMessage.xMessageID >= ( BaseType_t ) 0 )
it must be present in the function call. prvSampleTimeNow() must be
called after the message is received from xTimerQueue so there is no
possibility of a higher priority task adding a message to the message
queue with a time that is ahead of the timer daemon task (because it
pre-empted the timer daemon task after the xTimeNow value was set). */
xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );
switch( xMessage.xMessageID )
{ {
case tmrCOMMAND_START : /* The messages uses the xTimerParameters member to work on a
/* Start or restart a timer. */ software timer. */
if( prvInsertTimerInActiveList( pxTimer, xMessage.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.xMessageValue ) == pdTRUE ) pxTimer = xMessage.u.xTimerParameters.pxTimer;
{
/* The timer expired before it was added to the active timer
list. Process it now. */
pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer );
if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE ) if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE )
{
/* The timer is in a list, remove it. */
( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.u.xTimerParameters.xMessageValue );
/* In this case the xTimerListsWereSwitched parameter is not used, but
it must be present in the function call. prvSampleTimeNow() must be
called after the message is received from xTimerQueue so there is no
possibility of a higher priority task adding a message to the message
queue with a time that is ahead of the timer daemon task (because it
pre-empted the timer daemon task after the xTimeNow value was set). */
xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );
switch( xMessage.xMessageID )
{
case tmrCOMMAND_START :
case tmrCOMMAND_START_FROM_ISR :
case tmrCOMMAND_RESET :
case tmrCOMMAND_RESET_FROM_ISR :
case tmrCOMMAND_START_DONT_TRACE :
/* Start or restart a timer. */
if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) == pdTRUE )
{ {
xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xMessage.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY ); /* The timer expired before it was added to the active
configASSERT( xResult ); timer list. Process it now. */
( void ) xResult; pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
traceTIMER_EXPIRED( pxTimer );
if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )
{
xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY );
configASSERT( xResult );
( void ) xResult;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
} else
break; {
mtCOVERAGE_TEST_MARKER();
}
break;
case tmrCOMMAND_STOP : case tmrCOMMAND_STOP :
/* The timer has already been removed from the active list. case tmrCOMMAND_STOP_FROM_ISR :
There is nothing to do here. */ /* The timer has already been removed from the active list.
break; There is nothing to do here. */
break;
case tmrCOMMAND_CHANGE_PERIOD : case tmrCOMMAND_CHANGE_PERIOD :
pxTimer->xTimerPeriodInTicks = xMessage.xMessageValue; case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR :
configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) ); pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue;
( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow ); configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) );
break;
case tmrCOMMAND_DELETE : /* The new period does not really have a reference, and can be
/* The timer has already been removed from the active list, longer or shorter than the old one. The command time is
just free up the memory. */ therefore set to the current time, and as the period cannot be
vPortFree( pxTimer ); zero the next expiry time can only be in the future, meaning
break; (unlike for the xTimerStart() case above) there is no fail case
that needs to be handled here. */
( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow );
break;
default : case tmrCOMMAND_DELETE :
/* Don't expect to get here. */ /* The timer has already been removed from the active list,
break; just free up the memory. */
vPortFree( pxTimer );
break;
default :
/* Don't expect to get here. */
break;
}
} }
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSwitchTimerLists( portTickType xLastTime ) static void prvSwitchTimerLists( void )
{ {
portTickType xNextExpireTime, xReloadTime; TickType_t xNextExpireTime, xReloadTime;
xList *pxTemp; List_t *pxTemp;
xTIMER *pxTimer; Timer_t *pxTimer;
portBASE_TYPE xResult; BaseType_t xResult;
/* Remove compiler warnings if configASSERT() is not defined. */
( void ) xLastTime;
/* The tick count has overflowed. The timer lists must be switched. /* The tick count has overflowed. The timer lists must be switched.
If there are any timers still referenced from the current timer list If there are any timers still referenced from the current timer list
@ -603,15 +712,16 @@ portBASE_TYPE xResult;
xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );
/* Remove the timer from the list. */ /* Remove the timer from the list. */
pxTimer = ( xTIMER * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );
( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
traceTIMER_EXPIRED( pxTimer );
/* Execute its callback, then send a command to restart the timer if /* Execute its callback, then send a command to restart the timer if
it is an auto-reload timer. It cannot be restarted here as the lists it is an auto-reload timer. It cannot be restarted here as the lists
have not yet been switched. */ have not yet been switched. */
pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer ); pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE ) if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )
{ {
/* Calculate the reload value, and if the reload value results in /* Calculate the reload value, and if the reload value results in
the timer going into the same timer list then it has already expired the timer going into the same timer list then it has already expired
@ -628,11 +738,15 @@ portBASE_TYPE xResult;
} }
else else
{ {
xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xNextExpireTime, NULL, tmrNO_DELAY ); xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY );
configASSERT( xResult ); configASSERT( xResult );
( void ) xResult; ( void ) xResult;
} }
} }
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
pxTemp = pxCurrentTimerList; pxTemp = pxCurrentTimerList;
@ -654,17 +768,35 @@ static void prvCheckForValidListAndQueue( void )
vListInitialise( &xActiveTimerList2 ); vListInitialise( &xActiveTimerList2 );
pxCurrentTimerList = &xActiveTimerList1; pxCurrentTimerList = &xActiveTimerList1;
pxOverflowTimerList = &xActiveTimerList2; pxOverflowTimerList = &xActiveTimerList2;
xTimerQueue = xQueueCreate( ( unsigned portBASE_TYPE ) configTIMER_QUEUE_LENGTH, sizeof( xTIMER_MESSAGE ) ); xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) );
configASSERT( xTimerQueue );
#if ( configQUEUE_REGISTRY_SIZE > 0 )
{
if( xTimerQueue != NULL )
{
vQueueAddToRegistry( xTimerQueue, "TmrQ" );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* configQUEUE_REGISTRY_SIZE */
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer ) BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer )
{ {
portBASE_TYPE xTimerIsInActiveList; BaseType_t xTimerIsInActiveList;
xTIMER *pxTimer = ( xTIMER * ) xTimer; Timer_t *pxTimer = ( Timer_t * ) xTimer;
/* Is the timer in the list of active timers? */ /* Is the timer in the list of active timers? */
taskENTER_CRITICAL(); taskENTER_CRITICAL();
@ -677,17 +809,65 @@ xTIMER *pxTimer = ( xTIMER * ) xTimer;
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
return xTimerIsInActiveList; return xTimerIsInActiveList;
} } /*lint !e818 Can't be pointer to const due to the typedef. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void *pvTimerGetTimerID( xTimerHandle xTimer ) void *pvTimerGetTimerID( const TimerHandle_t xTimer )
{ {
xTIMER *pxTimer = ( xTIMER * ) xTimer; Timer_t * const pxTimer = ( Timer_t * ) xTimer;
return pxTimer->pvTimerID; return pxTimer->pvTimerID;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( INCLUDE_xTimerPendFunctionCall == 1 )
BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken )
{
DaemonTaskMessage_t xMessage;
BaseType_t xReturn;
/* Complete the message with the function parameters and post it to the
daemon task. */
xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR;
xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;
xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;
xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;
xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken );
tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, xReturn );
return xReturn;
}
#endif /* INCLUDE_xTimerPendFunctionCall */
/*-----------------------------------------------------------*/
#if( INCLUDE_xTimerPendFunctionCall == 1 )
BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait )
{
DaemonTaskMessage_t xMessage;
BaseType_t xReturn;
/* Complete the message with the function parameters and post it to the
daemon task. */
xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK;
xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;
xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;
xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;
xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait );
tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, xReturn );
return xReturn;
}
#endif /* INCLUDE_xTimerPendFunctionCall */
/*-----------------------------------------------------------*/
/* This entire source file will be skipped if the application is not configured /* This entire source file will be skipped if the application is not configured
to include software timer functionality. If you want to include software timer to include software timer functionality. If you want to include software timer
functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */

View File

@ -295,7 +295,7 @@ restart:
/* update free space counter */ /* update free space counter */
heap_free -= size; heap_free -= size;
traceMALLOC( (void *)(best + 1), size );
/* and return a pointer to the allocated region */ /* and return a pointer to the allocated region */
return (void *)(best + 1); return (void *)(best + 1);
} }
@ -314,6 +314,8 @@ msheap_free(void *ptr)
marker->next.free = 1; marker->next.free = 1;
(marker + marker->next.size)->prev.free = 1; (marker + marker->next.size)->prev.free = 1;
traceFREE( ptr, marker->next.size );
/* account for space we are freeing */ /* account for space we are freeing */
heap_free += marker->next.size; heap_free += marker->next.size;

View File

@ -1,19 +0,0 @@
Each real time kernel port consists of three files that contain the core kernel
components and are common to every port, and one or more files that are
specific to a particular microcontroller and/or compiler.
+ The FreeRTOS/Source/Portable/MemMang directory contains the three sample
memory allocators as described on the http://www.FreeRTOS.org WEB site.
+ The other directories each contain files specific to a particular
microcontroller or compiler.
For example, if you are interested in the GCC port for the ATMega323
microcontroller then the port specific files are contained in
FreeRTOS/Source/Portable/GCC/ATMega323 directory. If this is the only
port you are interested in then all the other directories can be
ignored.

View File

@ -1,17 +0,0 @@
Each real time kernel port consists of three files that contain the core kernel
components and are common to every port, and one or more files that are
specific to a particular microcontroller and or compiler.
+ The FreeRTOS/Source directory contains the three files that are common to
every port - list.c, queue.c and tasks.c. The kernel is contained within these
three files. croutine.c implements the optional co-routine functionality - which
is normally only used on very memory limited systems.
+ The FreeRTOS/Source/Portable directory contains the files that are specific to
a particular microcontroller and or compiler.
+ The FreeRTOS/Source/include directory contains the real time kernel header
files.
See the readme file in the FreeRTOS/Source/Portable directory for more
information.

View File

@ -44,7 +44,7 @@ EXTRAINCDIRS += $(USBDEVLIB)/inc
# the device-specific pieces of the code. # the device-specific pieces of the code.
# #
ifneq ($(FREERTOS_DIR),) ifneq ($(FREERTOS_DIR),)
FREERTOS_PORTDIR := $(PIOS_DEVLIB)libraries/FreeRTOS/Source FREERTOS_PORTDIR := $(FREERTOS_DIR)
SRC += $(sort $(wildcard $(FREERTOS_PORTDIR)/portable/GCC/ARM_CM3/*.c)) SRC += $(sort $(wildcard $(FREERTOS_PORTDIR)/portable/GCC/ARM_CM3/*.c))
SRC += $(sort $(wildcard $(FREERTOS_DIR)/portable/MemMang/heap_1.c)) SRC += $(sort $(wildcard $(FREERTOS_DIR)/portable/MemMang/heap_1.c))
EXTRAINCDIRS += $(FREERTOS_PORTDIR)/portable/GCC/ARM_CM3 EXTRAINCDIRS += $(FREERTOS_PORTDIR)/portable/GCC/ARM_CM3

View File

@ -55,8 +55,8 @@ EXTRAINCDIRS += $(USBDEVLIB)/Core/inc
# the device-specific pieces of the code. # the device-specific pieces of the code.
# #
ifneq ($(FREERTOS_DIR),) ifneq ($(FREERTOS_DIR),)
FREERTOS_PORTDIR := $(PIOS_DEVLIB)libraries/FreeRTOS/Source FREERTOS_PORTDIR := $(FREERTOS_DIR)
SRC += $(sort $(wildcard $(FREERTOS_PORTDIR)/portable/GCC/ARM_CM4F/*.c)) SRC += $(sort $(wildcard $(FREERTOS_PORTDIR)/portable/GCC/ARM_CM4F/*.c))
EXTRAINCDIRS += $(FREERTOS_PORTDIR)/portable/GCC/ARM_CM4F EXTRAINCDIRS += $(FREERTOS_PORTDIR)/portable/GCC/ARM_CM4F
include $(PIOSCOMMON)/libraries/msheap/library.mk include $(PIOSCOMMON)/libraries/msheap/library.mk
endif endif