Add event_groups.c and associated functions in other core files.

Added xTimerPendCallbackFromISR() to provide a centralised deferred interrupt handling mechanism.
Add xPortGetLowestEverFreeHeapSize() to heap_4.c.
pull/1/head
Richard Barry 11 years ago
parent faed443e82
commit f54f21b8f6

@ -0,0 +1,442 @@
/*
FreeRTOS V7.6.0 - Copyright (C) 2013 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_xTimerPendCallbackFromISR == 0 )
#error INCLUDE_xTimerPendCallbackFromISR must also be set to one to make the xEventGroupSetBitFromISR() function available.
#endif
#if configUSE_16_BIT_TICKS == 1
#define taskCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
#define taskUNBLOCKED_DUE_TO_BIT_SET_BIT 0x0200U
#define taskWAIT_FOR_ALL_BITS 0x0400U
#define taskEVENT_BITS_CONTROL_BYTES 0xff00U
#else
#define taskCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL
#define taskUNBLOCKED_DUE_TO_BIT_SET_BIT 0x02000000UL
#define taskWAIT_FOR_ALL_BITS 0x04000000UL
#define taskEVENT_BITS_CONTROL_BYTES 0xff000000UL
#endif
typedef struct EventBitsDefinition
{
xEventBitsType uxEventBits;
xList xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */
} xEVENT_BITS;
/* Used internally only. */
typedef struct EVENT_GROUP_CALLBACK_PARAMTERS
{
xEventGroupHandle xTargetEventGroup;
xEventBitsType xBitsToSet;
} xEventGroupCallbackParameters;
/*-----------------------------------------------------------*/
xEventGroupHandle xEventGroupCreate( void )
{
xEVENT_BITS *pxEventBits;
pxEventBits = pvPortMalloc( sizeof( xEVENT_BITS ) );
if( pxEventBits != NULL )
{
pxEventBits->uxEventBits = 0;
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
}
return ( xEventGroupHandle ) pxEventBits;
}
/*-----------------------------------------------------------*/
xEventBitsType xEventGroupSync( xEventGroupHandle xEventGroup, xEventBitsType uxBitsToSet, xEventBitsType uxBitsToWaitFor, portTickType xBlockTime )
{
xEventBitsType uxOriginalBitValue, uxReturn;
xEVENT_BITS *pxEventBits = ( xEVENT_BITS * ) xEventGroup;
portBASE_TYPE xYieldedAlready;
vTaskSuspendAll();
{
uxOriginalBitValue = pxEventBits->uxEventBits;
( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
{
/* All the rendezvous bits will have been set once this task set
its bits - 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;
xBlockTime = 0;
}
else
{
if( xBlockTime != ( portTickType ) 0 )
{
/* 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 | taskCLEAR_EVENTS_ON_EXIT_BIT | taskWAIT_FOR_ALL_BITS ), xBlockTime );
}
else
{
/* The rendezvous bits were not set, but no block time was
specified - just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits;
}
}
}
xYieldedAlready = xTaskResumeAll();
if( xBlockTime != ( portTickType ) 0 )
{
if( xYieldedAlready == pdFALSE )
{
portYIELD_WITHIN_API();
}
/* The task blocked to wait for its required bits to be set - at this
point either the required bits were set or the block time expired. If
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 & taskUNBLOCKED_DUE_TO_BIT_SET_BIT ) == ( xEventBitsType ) 0 )
{
/* The task timed out, just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits;
}
else
{
/* The task unblocked because the bits were set. Clear the control
bits before returning the value. */
uxReturn &= ~taskEVENT_BITS_CONTROL_BYTES;
}
}
return uxReturn;
}
/*-----------------------------------------------------------*/
xEventBitsType xEventGroupWaitBits( xEventGroupHandle xEventGroup, xEventBitsType uxBitsToWaitFor, portBASE_TYPE xClearOnExit, portBASE_TYPE xWaitForAllBits, portTickType xBlockTime )
{
xEVENT_BITS *pxEventBits = ( xEVENT_BITS * ) xEventGroup;
const xEventBitsType uxCurrentEventBits = pxEventBits->uxEventBits;
xEventBitsType uxReturn, uxControlBits = 0;
/* 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 & taskEVENT_BITS_CONTROL_BYTES ) == 0 );
configASSERT( uxBitsToWaitFor != 0 );
taskENTER_CRITICAL();
{
if( xWaitForAllBits == pdFALSE )
{
/* Task only has to wait for one bit within uxBitsToWaitFor to be set. Is
one already set? */
if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( xEventBitsType ) 0 )
{
/* At least one of the bits was set. No need to block. */
xBlockTime = 0;
}
}
else
{
/* Task has to wait for all the bits in uxBitsToWaitFor to be set. Are they
set already? */
if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
{
/* All the bits were set, no need to block. */
xBlockTime = 0;
}
}
/* The task can return now if either its wait condition is already met
or the requested block time is 0. */
if( xBlockTime == ( portTickType ) 0 )
{
/* No need to block, just set the return value. */
uxReturn = uxCurrentEventBits;
if( xClearOnExit != pdFALSE )
{
/* The user requested the bits be cleared again prior to exiting
this function. */
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
}
}
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 |= taskCLEAR_EVENTS_ON_EXIT_BIT;
}
if( xWaitForAllBits != pdFALSE )
{
uxControlBits |= taskWAIT_FOR_ALL_BITS;
}
/* 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 ), xBlockTime );
portYIELD_WITHIN_API();
}
}
taskEXIT_CRITICAL();
if( xBlockTime != ( portTickType ) 0 )
{
/* 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 & taskUNBLOCKED_DUE_TO_BIT_SET_BIT ) == ( xEventBitsType ) 0 )
{
/* The task timed out, just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits;
}
else
{
/* The task unblocked because the bits were set. Clear the control
bits before returning the value. */
uxReturn &= ~taskEVENT_BITS_CONTROL_BYTES;
}
}
return uxReturn;
}
/*-----------------------------------------------------------*/
xEventBitsType xEventGroupClearBits( xEventGroupHandle xEventGroup, xEventBitsType uxBitsToClear )
{
xEVENT_BITS *pxEventBits = ( xEVENT_BITS * ) xEventGroup;
xEventBitsType uxReturn;
/* Check the user is not attempting to clear the bits used by the kernel
itself. */
configASSERT( ( uxBitsToClear & taskEVENT_BITS_CONTROL_BYTES ) == 0 );
uxBitsToClear = ~uxBitsToClear;
taskENTER_CRITICAL();
{
/* 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;
}
/*-----------------------------------------------------------*/
xEventBitsType xEventGroupSetBits( xEventGroupHandle xEventGroup, xEventBitsType uxBitsToSet )
{
xListItem *pxListItem, *pxNext;
xListItem const *pxListEnd;
xList *pxList;
xEventBitsType uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
xEVENT_BITS *pxEventBits = ( xEVENT_BITS * ) xEventGroup;
portBASE_TYPE xMatchFound = pdFALSE;
/* Check the user is not attempting to set the bits used by the kernel
itself. */
configASSERT( ( uxBitsToSet & taskEVENT_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. */
pxListItem = listGET_HEAD_ENTRY( pxList );
vTaskSuspendAll();
{
/* 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 );
/* Split the bits waited for from the control bits. */
uxControlBits = uxBitsWaitedFor & taskEVENT_BITS_CONTROL_BYTES;
uxBitsWaitedFor &= ~taskEVENT_BITS_CONTROL_BYTES;
if( ( uxControlBits & taskWAIT_FOR_ALL_BITS ) == ( xEventBitsType ) 0 )
{
/* Just looking for single bit being set. */
if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( xEventBitsType ) 0 )
{
xMatchFound = pdTRUE;
}
}
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 & taskCLEAR_EVENTS_ON_EXIT_BIT ) != ( xEventBitsType ) 0 )
{
uxBitsToClear |= uxBitsWaitedFor;
}
/* Store the actual event flag value in the task's event list
item before removing the task from the event list. The
taskUNBLOCKED_DUE_TO_BIT_SET_BIT 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 | taskUNBLOCKED_DUE_TO_BIT_SET_BIT );
}
/* 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 taskCLEAR_EVENTS_ON_EXIT_BIT
bit was set in the control word. */
pxEventBits->uxEventBits &= ~uxBitsToClear;
}
( void ) xTaskResumeAll();
return pxEventBits->uxEventBits;
}
/*-----------------------------------------------------------*/
void vEventGroupDelete( xEventGroupHandle xEventGroup )
{
xEVENT_BITS *pxEventBits = ( xEVENT_BITS * ) xEventGroup;
const xList *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
vTaskSuspendAll();
{
while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( unsigned portBASE_TYPE ) 0 )
{
/* Unblock the task, returning 0 as the event list is being deleted
and cannot therefore have any bits set. */
configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( xListItem * ) &( pxTasksWaitingForBits->xListEnd ) );
( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, ( portTickType ) 0 );
}
vPortFree( pxEventBits );
}
( void ) xTaskResumeAll();
}
/*-----------------------------------------------------------*/
/* For internal use only - execute a 'set bits' command that was pended from
an interrupt. */
void vEventGroupSetBitsCallback( void *pvEventGroup, unsigned long ulBitsToSet )
{
( void ) xEventGroupSetBits( pvEventGroup, ( xEventBitsType ) ulBitsToSet );
}

@ -92,9 +92,10 @@ is included as it is used by the port layer. */
conform. */
typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
/* The type that holds event bits always matches portTickType - 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. */
typedef portTickType xEventBitsType;
/*
* Check all the required application specific macros have been defined.
@ -190,6 +191,10 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
#define configUSE_TIMERS 0
#endif
#ifndef configUSE_EVENT_GROUPS
#define configUSE_EVENT_GROUPS 0
#endif
#ifndef configUSE_COUNTING_SEMAPHORES
#define configUSE_COUNTING_SEMAPHORES 0
#endif
@ -218,6 +223,14 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
#define INCLUDE_xTaskResumeFromISR 1
#endif
#ifndef INCLUDE_xEventGroupSetBitFromISR
#define INCLUDE_xEventGroupSetBitFromISR 0
#endif
#ifndef INCLUDE_xTimerPendCallbackFromISR
#define INCLUDE_xTimerPendCallbackFromISR 0
#endif
#ifndef configASSERT
#define configASSERT( x )
#define configASSERT_DEFINED 0

@ -0,0 +1,625 @@
/*
FreeRTOS V7.6.0 - Copyright (C) 2013 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 xEventGroupHandle variable that can then
* be used as a parameter to other event group functions.
*
* \defgroup xEventGroupHandle xEventGroupHandle
* \ingroup EventGroup
*/
typedef void * xEventGroupHandle;
/**
* event_groups.h
*<pre>
xEventGroupHandle 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 xEventBitsType 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.
xEventGroupHandle 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
*/
xEventGroupHandle xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
*<pre>
xEventBitsType xEventGroupWaitBits( xEventGroupHandle xEventGroup,
xEventBitsType uxBitsToWaitFor,
portBASE_TYPE xClearOnExit,
portBASE_TYPE xWaitForAllBits,
portTickType xBlockTime );
</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 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.
*
* @param xBlockTime 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 because the xClearOnExit parameter was set to pdTRUE.
*
* Example usage:
<pre>
#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )
void aFunction( xEventGroupHandle xEventGroup )
{
xEventBitsType uxBits;
const portTickType xBlockTime = 100 / portTICK_RATE_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.
xBlockTime ); // 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 xBlockTime ticks passed
// without either BIT_0 or BIT_4 becoming set.
}
}
</pre>
* \defgroup xEventGroupWaitBits xEventGroupWaitBits
* \ingroup EventGroup
*/
xEventBitsType xEventGroupWaitBits( xEventGroupHandle xEventGroup, xEventBitsType uxBitsToWaitFor, portBASE_TYPE xClearOnExit, portBASE_TYPE xWaitForAllBits, portTickType xBlockTime ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
*<pre>
xEventBitsType xEventGroupClearBits( xEventGroupHandle xEventGroup, xEventBitsType 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( xEventGroupHandle xEventGroup )
{
xEventBitsType 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 the call to
// 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
*/
xEventBitsType xEventGroupClearBits( xEventGroupHandle xEventGroup, xEventBitsType uxBitsToClear ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
*<pre>
xEventBitsType xEventGroupSetBits( xEventGroupHandle xEventGroup, xEventBitsType 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( xEventGroupHandle xEventGroup )
{
xEventBitsType 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 either or 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
*/
xEventBitsType xEventGroupSetBits( xEventGroupHandle xEventGroup, xEventBitsType uxBitsToSet ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
*<pre>
xEventBitsType xEventGroupSetBitsFromISR( xEventGroupHandle xEventGroup, xEventBitsType uxBitsToSet, portBASE_TYPE *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.
*
* @ 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 callback request was registered 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 assume has already been created by a call to
// xEventGroupCreate().
xEventGroupHandle xEventGroup;
void anInterruptHandler( void )
{
portBASE_TYPE xHigherPriorityTaskWoken;
// xHigherPriorityTaskWoken must be initialised to pdFALSE;
xHigherPriorityTaskWoken = pdFALSE;
// Set bit 0 and bit 4 in xEventGroup.
uxBits = xEventGroupSetBitsFromISR(
xEventGroup, // The event group being updated.
BIT_0 | BIT_4 // The bits being set.
&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 );
}
</pre>
* \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR
* \ingroup EventGroup
*/
#define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) xTimerPendCallbackFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( unsigned long ) uxBitsToSet, pxHigherPriorityTaskWoken )
/**
* event_groups.h
*<pre>
xEventBitsType xEventGroupSync( xEventGroupHandle xEventGroup,
xEventBitsType uxBitsToSet,
xEventBitsType uxBitsToWaitFor,
portTickType xBlockTime );
</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 xBlockTime 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.
xEventGroupHandle xEventBits;
void vTask0( void *pvParameters )
{
xEventBitsType uxReturn;
portTickType xBlockTime = 100 / portTICK_RATE_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, xBlockTime );
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
*/
xEventBitsType xEventGroupSync( xEventGroupHandle xEventGroup, xEventBitsType uxBitsToSet, xEventBitsType uxBitsToWaitFor, portTickType xBlockTime ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
*<pre>
xEventBitsType xEventGroupGetBits( xEventGroupHandle 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>
void xEventGroupDelete( xEventGroupHandle 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( xEventGroupHandle xEventGroup );
/* For internal use only. */
void vEventGroupSetBitsCallback( void *pvEventGroup, unsigned long ulBitsToSet );
#ifdef __cplusplus
}
#endif
#endif /* EVENT_GROUPS_H */

@ -205,7 +205,31 @@ typedef struct xLIST
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
* \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_HEAD_ENTRY listGET_HEAD_ENTRY
* \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 ) ( ( xListItem const * ) ( &( ( pxList )->xListEnd ) ) )
/*
* Access macro to determine if a list contains any items. The macro will

@ -368,6 +368,7 @@ void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION;
void vPortFree( void *pv ) PRIVILEGED_FUNCTION;
void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION;
size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION;
size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION;
/*
* Setup the hardware ready for the scheduler to take control. This generally

@ -1,5 +1,5 @@
/*
FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.
FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -69,6 +69,10 @@
/* Defines the prototype to which task functions must conform. */
typedef void (*pdTASK_CODE)( void * );
/* Defines the prototype to which callback functions called from the RTOS/timer
daemon task must conform. */
typedef void (*pdAPPLICATION_CALLBACK_CODE)( void *, unsigned long );
#define pdFALSE ( ( portBASE_TYPE ) 0 )
#define pdTRUE ( ( portBASE_TYPE ) 1 )

@ -1378,15 +1378,26 @@ portBASE_TYPE xTaskIncrementTick( void ) PRIVILEGED_FUNCTION;
* there be no higher priority tasks waiting on the same event) or
* 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
* 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
* 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
* period.
*/
void vTaskPlaceOnEventList( xList * const pxEventList, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
void vTaskPlaceOnUnorderedEventList( xList * pxEventList, portTickType xItemValue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
/*
* THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN
@ -1412,13 +1423,23 @@ void vTaskPlaceOnEventListRestricted( xList * const pxEventList, portTickType xT
* Removes a task from both the specified event list and the list of blocked
* tasks, and places it on a ready queue.
*
* xTaskRemoveFromEventList () will be called if either an event occurs to
* unblock a task, or the block timeout period expires.
* xTaskRemoveFromEventList()/xTaskRemoveFromUnorderedEventList() will be called
* 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
* making the call, otherwise pdFALSE.
*/
signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList ) PRIVILEGED_FUNCTION;
signed portBASE_TYPE xTaskRemoveFromUnorderedEventList( xListItem * pxEventListItem, portTickType xItemValue ) PRIVILEGED_FUNCTION;
/*
* THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY
@ -1430,6 +1451,12 @@ signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList )
*/
void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION;
/*
* THESE FUNCTIONS MUST NOT BE USED FROM APPLICATION CODE. THEY ARE USED BY
* THE EVENT BITS MODULE.
*/
portTickType uxTaskResetEventItemValue( void ) PRIVILEGED_FUNCTION;
/*
* Return the handle of the calling task.
*/
@ -1479,13 +1506,13 @@ signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed ch
/*
* Get the uxTCBNumber assigned to the task referenced by the xTask parameter.
*/
unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask );
unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask ) PRIVILEGED_FUNCTION;
/*
* Set the uxTCBNumber of the task referenced by the xTask parameter to
* ucHandle.
*/
void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle );
void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle ) PRIVILEGED_FUNCTION;
/*
* If tickless mode is being used, or a low power mode is implemented, then
@ -1494,7 +1521,7 @@ void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle );
* to date with the actual execution time by being skipped forward by the by
* a time equal to the idle period.
*/
void vTaskStepTick( portTickType xTicksToJump );
void vTaskStepTick( portTickType xTicksToJump ) PRIVILEGED_FUNCTION;
/*
* Provided for use within portSUPPRESS_TICKS_AND_SLEEP() to allow the port
@ -1509,7 +1536,7 @@ void vTaskStepTick( portTickType xTicksToJump );
* critical section between the timer being stopped and the sleep mode being
* entered to ensure it is ok to proceed into the sleep mode.
*/
eSleepModeStatus eTaskConfirmSleepModeStatus( void );
eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION;
#ifdef __cplusplus
}

@ -1,5 +1,5 @@
/*
FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.
FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -83,6 +83,7 @@ extern "C" {
/* 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_EXECUTE_CALLBACK ( ( portBASE_TYPE ) -1 )
#define tmrCOMMAND_START ( ( portBASE_TYPE ) 0 )
#define tmrCOMMAND_STOP ( ( portBASE_TYPE ) 1 )
#define tmrCOMMAND_CHANGE_PERIOD ( ( portBASE_TYPE ) 2 )
@ -170,7 +171,7 @@ typedef void (*tmrTIMER_CALLBACK)( xTimerHandle xTimer );
*
* // Optionally do something if the pxTimer parameter is NULL.
* configASSERT( pxTimer );
*
*
* // Which timer expired?
* lArrayIndex = ( long ) pvTimerGetTimerID( pxTimer );
*
@ -293,7 +294,7 @@ void *pvTimerGetTimerID( xTimerHandle xTimer ) PRIVILEGED_FUNCTION;
portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer ) PRIVILEGED_FUNCTION;
/**
* xTimerGetTimerDaemonTaskHandle() is only available if
* xTimerGetTimerDaemonTaskHandle() is only available if
* INCLUDE_xTimerGetTimerDaemonTaskHandle is set to 1 in FreeRTOSConfig.h.
*
* Simply returns the handle of the timer service/daemon task. It it not valid
@ -944,6 +945,95 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
*/
#define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U )
/**
* portBASE_TYPE xTimerPendCallbackFromISR( pdAPPLICATION_CALLBACK_CODE pvCallbackFunction,
* void *pvParameter1,
* unsigned long ulParameter2,
* portBASE_TYPE *pxHigherPriorityTaskWoken );
*
*
* Can be used by interrupt service routines to request that a function (the
* callback function) is executed from a task context.
*
* 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 the processing can be
* deferred to be performed in a task - allowing the ISR to exit. The timer
* daemon service/daemon task is already responsible for executing software
* timer callback functions, so is also used to executed callback functions that
* are pended from interrupts.
*
* 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 pvCallbackFunction The function to execute from the timer service/
* daemon task. The function must conform to the pdAPPLICATION_CALLBACK_CODE
* 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
* xTimerPendCallbackFromISR(), 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.
*
* 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, unsigned long ulParameter2 )
* {
* portBASE_TYPE xInterfaceToService;
*
* // The interface that requires servicing is passed in the second
* // parameter. The first parameter is not used in this case.
* xInterfaceToService = ( portBASE_TYPE ) ulParameter2;
*
* // ...Perform the processing here...
* }
*
* // An ISR that receives data packets from multiple interfaces
* void vAnISR( void )
* {
* portBASE_TYPE 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;
* xTimerPendCallbackFromISR( vProcessInterface, NULL, ( unsigned long ) 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
*/
portBASE_TYPE xTimerPendCallbackFromISR( pdAPPLICATION_CALLBACK_CODE pvCallbackFunction, void *pvParameter1, unsigned long ulParameter2, portBASE_TYPE *pxHigherPriorityTaskWoken );
/*
* Functions beyond this part are not part of the public API and are intended
* for use by the kernel only.

@ -134,6 +134,7 @@ static xBlockLink xStart, *pxEnd = NULL;
/* Keeps track of the number of free bytes remaining, but says nothing about
fragmentation. */
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
member of an xBlockLink structure is set then the block belongs to the
@ -223,6 +224,11 @@ void *pvReturn = NULL;
xFreeBytesRemaining -= pxBlock->xBlockSize;
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
{
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
}
/* The block is being returned - it is allocated and owned
by the application and has no "next" block. */
pxBlock->xBlockSize |= xBlockAllocatedBit;
@ -295,6 +301,12 @@ size_t xPortGetFreeHeapSize( void )
}
/*-----------------------------------------------------------*/
size_t xPortGetMinimumEverFreeHeapSize( void )
{
return xMinimumEverFreeBytesRemaining;
}
/*-----------------------------------------------------------*/
void vPortInitialiseBlocks( void )
{
/* This just exists to keep the linker quiet. */

@ -169,7 +169,6 @@ typedef struct tskTaskControlBlock
} tskTCB;
/*
* Some kernel aware debuggers require the data the debugger needs access to to
* be global, rather than file scope.
@ -1327,7 +1326,9 @@ void vTaskEndScheduler( void )
void vTaskSuspendAll( void )
{
/* A critical section is not required as the variable is of type
portBASE_TYPE. */
portBASE_TYPE. 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;
}
/*----------------------------------------------------------*/
@ -1938,6 +1939,60 @@ portTickType xTimeToWake;
}
/*-----------------------------------------------------------*/
void vTaskPlaceOnUnorderedEventList( xList * pxEventList, portTickType xItemValue, portTickType xTicksToWait )
{
portTickType xTimeToWake;
configASSERT( pxEventList );
/* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
SCHEDULER SUSPENDED. */
/* Store the item value in the event list item. */
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue );
/* Place the event list item of the TCB at the end of the appropriate event
list. */
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 ) ) == ( unsigned portBASE_TYPE ) 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 );
}
#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. */
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. */
xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
#endif /* INCLUDE_vTaskSuspend */
}
/*-----------------------------------------------------------*/
#if configUSE_TIMERS == 1
void vTaskPlaceOnEventListRestricted( xList * const pxEventList, portTickType xTicksToWait )
@ -2034,6 +2089,56 @@ portBASE_TYPE xReturn;
}
/*-----------------------------------------------------------*/
signed portBASE_TYPE xTaskRemoveFromUnorderedEventList( xListItem * pxEventListItem, portTickType xItemValue )
{
tskTCB *pxUnblockedTCB;
portBASE_TYPE xReturn;
/* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
SCHEDULER SUSPENDED. It can also be called from within an ISR. */
/* Store the new item value in the event list. */
listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue );
/* Remove the TCB from the delayed list, and add it to the ready list. */
pxUnblockedTCB = ( tskTCB * ) listGET_LIST_ITEM_OWNER( pxEventListItem );
configASSERT( pxUnblockedTCB );
( void ) uxListRemove( pxEventListItem );
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
{
( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
prvAddTaskToReadyList( pxUnblockedTCB );
}
else
{
/* Cannot access the delayed or ready lists, so will hold this task
pending until the scheduler is resumed. */
vListInsertEnd( &( xPendingReadyList ), pxEventListItem );
}
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( xTimeOutType * const pxTimeOut )
{
configASSERT( pxTimeOut );
@ -2973,6 +3078,20 @@ tskTCB *pxNewTCB;
}
#endif /* configGENERATE_RUN_TIME_STATS */
/*-----------------------------------------------------------*/
portTickType uxTaskResetEventItemValue( void )
{
portTickType 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 ), ( ( portTickType ) configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
return uxReturn;
}
/*-----------------------------------------------------------*/

@ -1,5 +1,5 @@
/*
FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.
FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -76,6 +76,10 @@ task.h is included from an application file. */
#include "queue.h"
#include "timers.h"
#if ( INCLUDE_xTimerPendCallbackFromISR == 1 ) && ( configUSE_TIMERS == 0 )
#error configUSE_TIMERS must be set to 1 to make the INCLUDE_xTimerPendCallbackFromISR() function available.
#endif
/* Lint e961 and e750 are suppressed as a MISRA exception justified because the
MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
header files above, but not in this file, in order to generate the correct
@ -103,14 +107,41 @@ typedef struct tmrTimerControl
tmrTIMER_CALLBACK pxCallbackFunction; /*<< The function that will be called when the timer expires. */
} xTIMER;
/* The definition of messages that can be sent and received on the timer
queue. */
typedef struct tmrTimerQueueMessage
/* 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
{
portBASE_TYPE 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. */
xTIMER * pxTimer; /*<< The timer to which the command will be applied. */
} xTIMER_MESSAGE;
} xTimerParametersType;
typedef struct tmrCallbackParameters
{
pdAPPLICATION_CALLBACK_CODE pxCallbackFunction; /* << The callback function to execute. */
void *pvParameter1; /* << The value that will be used as the callback functions first parameter. */
unsigned long ulParameter2; /* << The value that will be used as the callback functions second parameter. */
} xCallbackParametersType;
/* 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
{
portBASE_TYPE xMessageID; /*<< The command being sent to the timer service task. */
union
{
xTimerParametersType 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_xTimerPendCallbackFromISR == 1 )
xCallbackParametersType xCallbackParameters;
#endif /* INCLUDE_xTimerPendCallbackFromISR */
} u;
} xDAEMON_TASK_MESSAGE;
/*lint -e956 A manual analysis and inspection has been used to determine which
static variables must be declared volatile. */
@ -270,7 +301,7 @@ xTIMER *pxNewTimer;
portBASE_TYPE xTimerGenericCommand( xTimerHandle xTimer, portBASE_TYPE xCommandID, portTickType xOptionalValue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portTickType xBlockTime )
{
portBASE_TYPE xReturn = pdFAIL;
xTIMER_MESSAGE xMessage;
xDAEMON_TASK_MESSAGE xMessage;
/* Send a message to the timer service task to perform a particular action
on a particular timer definition. */
@ -278,8 +309,8 @@ xTIMER_MESSAGE xMessage;
{
/* Send a command to the timer service task to start the xTimer timer. */
xMessage.xMessageID = xCommandID;
xMessage.xMessageValue = xOptionalValue;
xMessage.pxTimer = ( xTIMER * ) xTimer;
xMessage.u.xTimerParameters.xMessageValue = xOptionalValue;
xMessage.u.xTimerParameters.pxTimer = ( xTIMER * ) xTimer;
if( pxHigherPriorityTaskWoken == NULL )
{
@ -518,77 +549,98 @@ portBASE_TYPE xProcessTimerNow = pdFALSE;
static void prvProcessReceivedCommands( void )
{
xTIMER_MESSAGE xMessage;
xDAEMON_TASK_MESSAGE xMessage;
xTIMER *pxTimer;
portBASE_TYPE xTimerListsWereSwitched, xResult;
portTickType 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. */
{
pxTimer = xMessage.pxTimer;
if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE )
#if ( INCLUDE_xTimerPendCallbackFromISR == 1 )
{
/* The timer is in a list, remove it. */
( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
}
if( xMessage.xMessageID == tmrCOMMAND_EXECUTE_CALLBACK )
{
const xCallbackParametersType * const pxCallback = &( xMessage.u.xCallbackParameters );
traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.xMessageValue );
/* The timer uses the xCallbackParameters member to request a
callback be executed. Check the callback is not NULL. */
configASSERT( pxCallback );
/* 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 );
/* Call the function. */
pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 );
}
}
#endif /* INCLUDE_xTimerPendCallbackFromISR */
switch( xMessage.xMessageID )
if( xMessage.xMessageID != tmrCOMMAND_EXECUTE_CALLBACK )
{
case tmrCOMMAND_START :
/* Start or restart a timer. */
if( prvInsertTimerInActiveList( pxTimer, xMessage.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.xMessageValue ) == pdTRUE )
{
/* The timer expired before it was added to the active timer
list. Process it now. */
pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer );
/* The messages uses the xTimerParameters member to work on a
software timer. */
pxTimer = xMessage.u.xTimerParameters.pxTimer;
if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE )
{
/* The timer is in a list, remove it. */
( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
}
traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.u.xTimerParameters.xMessageValue );
if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE )
/* 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 :
/* 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 );
configASSERT( xResult );
( void ) xResult;
/* 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 )
{
xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY );
configASSERT( xResult );
( void ) xResult;
}
}
}
break;
case tmrCOMMAND_STOP :
/* The timer has already been removed from the active list.
There is nothing to do here. */
break;
case tmrCOMMAND_CHANGE_PERIOD :
pxTimer->xTimerPeriodInTicks = xMessage.xMessageValue;
configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) );
/* The new period does not really have a reference, and can be
longer or shorter than the old one. The command time is
therefore set to the current time, and as the period cannot be
zero the next expiry time can only be in the future, meaning
(unlike for the xTimerStart() case above) there is no fail case
that needs to be handled here. */
( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow );
break;
case tmrCOMMAND_DELETE :
/* The timer has already been removed from the active list,
just free up the memory. */
vPortFree( pxTimer );
break;
default :
/* Don't expect to get here. */
break;
break;
case tmrCOMMAND_STOP :
/* The timer has already been removed from the active list.
There is nothing to do here. */
break;
case tmrCOMMAND_CHANGE_PERIOD :
pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue;
configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) );
/* The new period does not really have a reference, and can be
longer or shorter than the old one. The command time is
therefore set to the current time, and as the period cannot be
zero the next expiry time can only be in the future, meaning
(unlike for the xTimerStart() case above) there is no fail case
that needs to be handled here. */
( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow );
break;
case tmrCOMMAND_DELETE :
/* The timer has already been removed from the active list,
just free up the memory. */
vPortFree( pxTimer );
break;
default :
/* Don't expect to get here. */
break;
}
}
}
}
@ -664,7 +716,7 @@ static void prvCheckForValidListAndQueue( void )
vListInitialise( &xActiveTimerList2 );
pxCurrentTimerList = &xActiveTimerList1;
pxOverflowTimerList = &xActiveTimerList2;
xTimerQueue = xQueueCreate( ( unsigned portBASE_TYPE ) configTIMER_QUEUE_LENGTH, sizeof( xTIMER_MESSAGE ) );
xTimerQueue = xQueueCreate( ( unsigned portBASE_TYPE ) configTIMER_QUEUE_LENGTH, sizeof( xDAEMON_TASK_MESSAGE ) );
}
}
taskEXIT_CRITICAL();
@ -698,6 +750,28 @@ xTIMER *pxTimer = ( xTIMER * ) xTimer;
}
/*-----------------------------------------------------------*/
#if( INCLUDE_xTimerPendCallbackFromISR == 1 )
portBASE_TYPE xTimerPendCallbackFromISR( pdAPPLICATION_CALLBACK_CODE pvCallbackFunction, void *pvParameter1, unsigned long ulParameter2, portBASE_TYPE *pxHigherPriorityTaskWoken )
{
xDAEMON_TASK_MESSAGE xMessage;
portBASE_TYPE xReturn;
/* Complete the message with the function parameters and post it to the
daemon task. */
xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK;
xMessage.u.xCallbackParameters.pxCallbackFunction = pvCallbackFunction;
xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;
xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;
xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken );
return xReturn;
}
#endif /* INCLUDE_xTimerPendCallbackFromISR */
/*-----------------------------------------------------------*/
/* This entire source file will be skipped if the application is not configured
to include software timer functionality. If you want to include software timer
functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */

Loading…
Cancel
Save