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.
This commit is contained in:
Richard Barry 2013-11-21 21:46:08 +00:00
parent faed443e82
commit f54f21b8f6
11 changed files with 1511 additions and 80 deletions

View file

@ -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

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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 )

View file

@ -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
}

View file

@ -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.