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:
442
FreeRTOS/Source/event_groups.c
Normal file
442
FreeRTOS/Source/event_groups.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -92,9 +92,10 @@ is included as it is used by the port layer. */
|
|||||||
conform. */
|
conform. */
|
||||||
typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
|
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.
|
* 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
|
#define configUSE_TIMERS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef configUSE_EVENT_GROUPS
|
||||||
|
#define configUSE_EVENT_GROUPS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef configUSE_COUNTING_SEMAPHORES
|
#ifndef configUSE_COUNTING_SEMAPHORES
|
||||||
#define configUSE_COUNTING_SEMAPHORES 0
|
#define configUSE_COUNTING_SEMAPHORES 0
|
||||||
#endif
|
#endif
|
||||||
@ -218,6 +223,14 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
|
|||||||
#define INCLUDE_xTaskResumeFromISR 1
|
#define INCLUDE_xTaskResumeFromISR 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef INCLUDE_xEventGroupSetBitFromISR
|
||||||
|
#define INCLUDE_xEventGroupSetBitFromISR 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef INCLUDE_xTimerPendCallbackFromISR
|
||||||
|
#define INCLUDE_xTimerPendCallbackFromISR 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef configASSERT
|
#ifndef configASSERT
|
||||||
#define configASSERT( x )
|
#define configASSERT( x )
|
||||||
#define configASSERT_DEFINED 0
|
#define configASSERT_DEFINED 0
|
||||||
|
625
FreeRTOS/Source/include/event_groups.h
Normal file
625
FreeRTOS/Source/include/event_groups.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -205,7 +205,31 @@ typedef struct xLIST
|
|||||||
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
|
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
|
||||||
* \ingroup LinkedList
|
* \ingroup LinkedList
|
||||||
*/
|
*/
|
||||||
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->xItemValue )
|
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the list item at the head of the list.
|
||||||
|
*
|
||||||
|
* \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
|
* 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 vPortFree( void *pv ) PRIVILEGED_FUNCTION;
|
||||||
void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION;
|
void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION;
|
||||||
size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION;
|
size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION;
|
||||||
|
size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup the hardware ready for the scheduler to take control. This generally
|
* Setup the hardware ready for the scheduler to take control. This generally
|
||||||
|
@ -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
|
All rights reserved
|
||||||
|
|
||||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
@ -69,6 +69,10 @@
|
|||||||
/* Defines the prototype to which task functions must conform. */
|
/* Defines the prototype to which task functions must conform. */
|
||||||
typedef void (*pdTASK_CODE)( void * );
|
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 pdFALSE ( ( portBASE_TYPE ) 0 )
|
||||||
#define pdTRUE ( ( portBASE_TYPE ) 1 )
|
#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
|
* there be no higher priority tasks waiting on the same event) or
|
||||||
* the delay period expires.
|
* the delay period expires.
|
||||||
*
|
*
|
||||||
|
* The 'unordered' version replaces the event list item value with the
|
||||||
|
* xItemValue value, and inserts the list item at the end of the list.
|
||||||
|
*
|
||||||
|
* The 'ordered' version uses the existing event list item value (which is the
|
||||||
|
* owning tasks priority) to insert the list item into the event list is task
|
||||||
|
* priority order.
|
||||||
|
*
|
||||||
* @param pxEventList The list containing tasks that are blocked waiting
|
* @param pxEventList The list containing tasks that are blocked waiting
|
||||||
* for the event to occur.
|
* for the event to occur.
|
||||||
*
|
*
|
||||||
|
* @param xItemValue The item value to use for the event list item when the
|
||||||
|
* event list is not ordered by task priority.
|
||||||
|
*
|
||||||
* @param xTicksToWait The maximum amount of time that the task should wait
|
* @param xTicksToWait The maximum amount of time that the task should wait
|
||||||
* for the event to occur. This is specified in kernel ticks,the constant
|
* for the event to occur. This is specified in kernel ticks,the constant
|
||||||
* portTICK_RATE_MS can be used to convert kernel ticks into a real time
|
* portTICK_RATE_MS can be used to convert kernel ticks into a real time
|
||||||
* period.
|
* period.
|
||||||
*/
|
*/
|
||||||
void vTaskPlaceOnEventList( xList * const pxEventList, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
|
void vTaskPlaceOnEventList( 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
|
* 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
|
* Removes a task from both the specified event list and the list of blocked
|
||||||
* tasks, and places it on a ready queue.
|
* tasks, and places it on a ready queue.
|
||||||
*
|
*
|
||||||
* xTaskRemoveFromEventList () will be called if either an event occurs to
|
* xTaskRemoveFromEventList()/xTaskRemoveFromUnorderedEventList() will be called
|
||||||
* unblock a task, or the block timeout period expires.
|
* if either an event occurs to unblock a task, or the block timeout period
|
||||||
|
* expires.
|
||||||
|
*
|
||||||
|
* xTaskRemoveFromEventList() is used when the event list is in task priority
|
||||||
|
* order. It removes the list item from the head of the event list as that will
|
||||||
|
* have the highest priority owning task of all the tasks on the event list.
|
||||||
|
* xTaskRemoveFromUnorderedEventList() is used when the event list is not
|
||||||
|
* ordered and the event list items hold something other than the owning tasks
|
||||||
|
* priority. In this case the event list item value is updated to the value
|
||||||
|
* passed in the xItemValue parameter.
|
||||||
*
|
*
|
||||||
* @return pdTRUE if the task being removed has a higher priority than the task
|
* @return pdTRUE if the task being removed has a higher priority than the task
|
||||||
* making the call, otherwise pdFALSE.
|
* making the call, otherwise pdFALSE.
|
||||||
*/
|
*/
|
||||||
signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList ) PRIVILEGED_FUNCTION;
|
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
|
* 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;
|
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.
|
* 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.
|
* 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
|
* Set the uxTCBNumber of the task referenced by the xTask parameter to
|
||||||
* ucHandle.
|
* 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
|
* 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
|
* to date with the actual execution time by being skipped forward by the by
|
||||||
* a time equal to the idle period.
|
* 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
|
* 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
|
* critical section between the timer being stopped and the sleep mode being
|
||||||
* entered to ensure it is ok to proceed into the sleep mode.
|
* entered to ensure it is ok to proceed into the sleep mode.
|
||||||
*/
|
*/
|
||||||
eSleepModeStatus eTaskConfirmSleepModeStatus( void );
|
eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#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
|
All rights reserved
|
||||||
|
|
||||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
@ -83,6 +83,7 @@ extern "C" {
|
|||||||
/* IDs for commands that can be sent/received on the timer queue. These are to
|
/* IDs for commands that can be sent/received on the timer queue. These are to
|
||||||
be used solely through the macros that make up the public software timer API,
|
be used solely through the macros that make up the public software timer API,
|
||||||
as defined below. */
|
as defined below. */
|
||||||
|
#define tmrCOMMAND_EXECUTE_CALLBACK ( ( portBASE_TYPE ) -1 )
|
||||||
#define tmrCOMMAND_START ( ( portBASE_TYPE ) 0 )
|
#define tmrCOMMAND_START ( ( portBASE_TYPE ) 0 )
|
||||||
#define tmrCOMMAND_STOP ( ( portBASE_TYPE ) 1 )
|
#define tmrCOMMAND_STOP ( ( portBASE_TYPE ) 1 )
|
||||||
#define tmrCOMMAND_CHANGE_PERIOD ( ( portBASE_TYPE ) 2 )
|
#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.
|
* // Optionally do something if the pxTimer parameter is NULL.
|
||||||
* configASSERT( pxTimer );
|
* configASSERT( pxTimer );
|
||||||
*
|
*
|
||||||
* // Which timer expired?
|
* // Which timer expired?
|
||||||
* lArrayIndex = ( long ) pvTimerGetTimerID( pxTimer );
|
* lArrayIndex = ( long ) pvTimerGetTimerID( pxTimer );
|
||||||
*
|
*
|
||||||
@ -293,7 +294,7 @@ void *pvTimerGetTimerID( xTimerHandle xTimer ) PRIVILEGED_FUNCTION;
|
|||||||
portBASE_TYPE xTimerIsTimerActive( 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.
|
* INCLUDE_xTimerGetTimerDaemonTaskHandle is set to 1 in FreeRTOSConfig.h.
|
||||||
*
|
*
|
||||||
* Simply returns the handle of the timer service/daemon task. It it not valid
|
* Simply returns the handle of the timer service/daemon task. It it not valid
|
||||||
@ -944,6 +945,95 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
|
|||||||
*/
|
*/
|
||||||
#define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U )
|
#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
|
* Functions beyond this part are not part of the public API and are intended
|
||||||
* for use by the kernel only.
|
* for use by the kernel only.
|
||||||
|
@ -134,6 +134,7 @@ static xBlockLink xStart, *pxEnd = NULL;
|
|||||||
/* Keeps track of the number of free bytes remaining, but says nothing about
|
/* Keeps track of the number of free bytes remaining, but says nothing about
|
||||||
fragmentation. */
|
fragmentation. */
|
||||||
static size_t xFreeBytesRemaining = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );
|
static size_t xFreeBytesRemaining = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );
|
||||||
|
static size_t xMinimumEverFreeBytesRemaining = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );
|
||||||
|
|
||||||
/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize
|
/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize
|
||||||
member of an xBlockLink structure is set then the block belongs to the
|
member of an xBlockLink structure is set then the block belongs to the
|
||||||
@ -223,6 +224,11 @@ void *pvReturn = NULL;
|
|||||||
|
|
||||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||||
|
|
||||||
|
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
||||||
|
{
|
||||||
|
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||||
|
}
|
||||||
|
|
||||||
/* The block is being returned - it is allocated and owned
|
/* The block is being returned - it is allocated and owned
|
||||||
by the application and has no "next" block. */
|
by the application and has no "next" block. */
|
||||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||||
@ -295,6 +301,12 @@ size_t xPortGetFreeHeapSize( void )
|
|||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
size_t xPortGetMinimumEverFreeHeapSize( void )
|
||||||
|
{
|
||||||
|
return xMinimumEverFreeBytesRemaining;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vPortInitialiseBlocks( void )
|
void vPortInitialiseBlocks( void )
|
||||||
{
|
{
|
||||||
/* This just exists to keep the linker quiet. */
|
/* This just exists to keep the linker quiet. */
|
||||||
|
@ -169,7 +169,6 @@ typedef struct tskTaskControlBlock
|
|||||||
|
|
||||||
} tskTCB;
|
} tskTCB;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some kernel aware debuggers require the data the debugger needs access to to
|
* Some kernel aware debuggers require the data the debugger needs access to to
|
||||||
* be global, rather than file scope.
|
* be global, rather than file scope.
|
||||||
@ -1327,7 +1326,9 @@ void vTaskEndScheduler( void )
|
|||||||
void vTaskSuspendAll( void )
|
void vTaskSuspendAll( void )
|
||||||
{
|
{
|
||||||
/* A critical section is not required as the variable is of type
|
/* A critical section is not required as the variable is of type
|
||||||
portBASE_TYPE. */
|
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;
|
++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
|
#if configUSE_TIMERS == 1
|
||||||
|
|
||||||
void vTaskPlaceOnEventListRestricted( xList * const pxEventList, portTickType xTicksToWait )
|
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 )
|
void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut )
|
||||||
{
|
{
|
||||||
configASSERT( pxTimeOut );
|
configASSERT( pxTimeOut );
|
||||||
@ -2973,6 +3078,20 @@ tskTCB *pxNewTCB;
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* configGENERATE_RUN_TIME_STATS */
|
#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
|
All rights reserved
|
||||||
|
|
||||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
@ -76,6 +76,10 @@ task.h is included from an application file. */
|
|||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
|
|
||||||
|
#if ( INCLUDE_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
|
/* Lint e961 and e750 are suppressed as a MISRA exception justified because the
|
||||||
MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
|
MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
|
||||||
header files above, but not in this file, in order to generate the correct
|
header files above, but not in this file, in order to generate the correct
|
||||||
@ -103,14 +107,41 @@ typedef struct tmrTimerControl
|
|||||||
tmrTIMER_CALLBACK pxCallbackFunction; /*<< The function that will be called when the timer expires. */
|
tmrTIMER_CALLBACK pxCallbackFunction; /*<< The function that will be called when the timer expires. */
|
||||||
} xTIMER;
|
} xTIMER;
|
||||||
|
|
||||||
/* The definition of messages that can be sent and received on the timer
|
/* The definition of messages that can be sent and received on the timer queue.
|
||||||
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
|
||||||
|
{
|
||||||
|
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. */
|
||||||
|
} 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
|
typedef struct tmrTimerQueueMessage
|
||||||
{
|
{
|
||||||
portBASE_TYPE xMessageID; /*<< The command being sent to the timer service task. */
|
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. */
|
union
|
||||||
xTIMER * pxTimer; /*<< The timer to which the command will be applied. */
|
{
|
||||||
} xTIMER_MESSAGE;
|
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
|
/*lint -e956 A manual analysis and inspection has been used to determine which
|
||||||
static variables must be declared volatile. */
|
static variables must be declared volatile. */
|
||||||
@ -270,7 +301,7 @@ xTIMER *pxNewTimer;
|
|||||||
portBASE_TYPE xTimerGenericCommand( xTimerHandle xTimer, portBASE_TYPE xCommandID, portTickType xOptionalValue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portTickType xBlockTime )
|
portBASE_TYPE xTimerGenericCommand( xTimerHandle xTimer, portBASE_TYPE xCommandID, portTickType xOptionalValue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portTickType xBlockTime )
|
||||||
{
|
{
|
||||||
portBASE_TYPE xReturn = pdFAIL;
|
portBASE_TYPE xReturn = pdFAIL;
|
||||||
xTIMER_MESSAGE xMessage;
|
xDAEMON_TASK_MESSAGE xMessage;
|
||||||
|
|
||||||
/* Send a message to the timer service task to perform a particular action
|
/* Send a message to the timer service task to perform a particular action
|
||||||
on a particular timer definition. */
|
on a particular timer definition. */
|
||||||
@ -278,8 +309,8 @@ xTIMER_MESSAGE xMessage;
|
|||||||
{
|
{
|
||||||
/* Send a command to the timer service task to start the xTimer timer. */
|
/* Send a command to the timer service task to start the xTimer timer. */
|
||||||
xMessage.xMessageID = xCommandID;
|
xMessage.xMessageID = xCommandID;
|
||||||
xMessage.xMessageValue = xOptionalValue;
|
xMessage.u.xTimerParameters.xMessageValue = xOptionalValue;
|
||||||
xMessage.pxTimer = ( xTIMER * ) xTimer;
|
xMessage.u.xTimerParameters.pxTimer = ( xTIMER * ) xTimer;
|
||||||
|
|
||||||
if( pxHigherPriorityTaskWoken == NULL )
|
if( pxHigherPriorityTaskWoken == NULL )
|
||||||
{
|
{
|
||||||
@ -518,77 +549,98 @@ portBASE_TYPE xProcessTimerNow = pdFALSE;
|
|||||||
|
|
||||||
static void prvProcessReceivedCommands( void )
|
static void prvProcessReceivedCommands( void )
|
||||||
{
|
{
|
||||||
xTIMER_MESSAGE xMessage;
|
xDAEMON_TASK_MESSAGE xMessage;
|
||||||
xTIMER *pxTimer;
|
xTIMER *pxTimer;
|
||||||
portBASE_TYPE xTimerListsWereSwitched, xResult;
|
portBASE_TYPE xTimerListsWereSwitched, xResult;
|
||||||
portTickType xTimeNow;
|
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. */
|
while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) /*lint !e603 xMessage does not have to be initialised as it is passed out, not in, and it is not used unless xQueueReceive() returns pdTRUE. */
|
||||||
{
|
{
|
||||||
pxTimer = xMessage.pxTimer;
|
#if ( INCLUDE_xTimerPendCallbackFromISR == 1 )
|
||||||
|
|
||||||
if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE )
|
|
||||||
{
|
{
|
||||||
/* The timer is in a list, remove it. */
|
if( xMessage.xMessageID == tmrCOMMAND_EXECUTE_CALLBACK )
|
||||||
( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
|
{
|
||||||
|
const xCallbackParametersType * const pxCallback = &( xMessage.u.xCallbackParameters );
|
||||||
|
|
||||||
|
/* The timer uses the xCallbackParameters member to request a
|
||||||
|
callback be executed. Check the callback is not NULL. */
|
||||||
|
configASSERT( pxCallback );
|
||||||
|
|
||||||
|
/* Call the function. */
|
||||||
|
pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* INCLUDE_xTimerPendCallbackFromISR */
|
||||||
|
|
||||||
traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.xMessageValue );
|
if( xMessage.xMessageID != tmrCOMMAND_EXECUTE_CALLBACK )
|
||||||
|
|
||||||
/* 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 :
|
/* The messages uses the xTimerParameters member to work on a
|
||||||
/* Start or restart a timer. */
|
software timer. */
|
||||||
if( prvInsertTimerInActiveList( pxTimer, xMessage.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.xMessageValue ) == pdTRUE )
|
pxTimer = xMessage.u.xTimerParameters.pxTimer;
|
||||||
{
|
|
||||||
/* The timer expired before it was added to the active timer
|
|
||||||
list. Process it now. */
|
|
||||||
pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer );
|
|
||||||
|
|
||||||
if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE )
|
if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE )
|
||||||
|
{
|
||||||
|
/* The timer is in a list, remove it. */
|
||||||
|
( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.u.xTimerParameters.xMessageValue );
|
||||||
|
|
||||||
|
/* In this case the xTimerListsWereSwitched parameter is not used, but
|
||||||
|
it must be present in the function call. prvSampleTimeNow() must be
|
||||||
|
called after the message is received from xTimerQueue so there is no
|
||||||
|
possibility of a higher priority task adding a message to the message
|
||||||
|
queue with a time that is ahead of the timer daemon task (because it
|
||||||
|
pre-empted the timer daemon task after the xTimeNow value was set). */
|
||||||
|
xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );
|
||||||
|
|
||||||
|
switch( xMessage.xMessageID )
|
||||||
|
{
|
||||||
|
case tmrCOMMAND_START :
|
||||||
|
/* Start or restart a timer. */
|
||||||
|
if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) == pdTRUE )
|
||||||
{
|
{
|
||||||
xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xMessage.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY );
|
/* The timer expired before it was added to the active timer
|
||||||
configASSERT( xResult );
|
list. Process it now. */
|
||||||
( void ) xResult;
|
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;
|
||||||
break;
|
|
||||||
|
|
||||||
case tmrCOMMAND_STOP :
|
case tmrCOMMAND_STOP :
|
||||||
/* The timer has already been removed from the active list.
|
/* The timer has already been removed from the active list.
|
||||||
There is nothing to do here. */
|
There is nothing to do here. */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tmrCOMMAND_CHANGE_PERIOD :
|
case tmrCOMMAND_CHANGE_PERIOD :
|
||||||
pxTimer->xTimerPeriodInTicks = xMessage.xMessageValue;
|
pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue;
|
||||||
configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) );
|
configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) );
|
||||||
|
|
||||||
/* The new period does not really have a reference, and can be
|
/* The new period does not really have a reference, and can be
|
||||||
longer or shorter than the old one. The command time is
|
longer or shorter than the old one. The command time is
|
||||||
therefore set to the current time, and as the period cannot be
|
therefore set to the current time, and as the period cannot be
|
||||||
zero the next expiry time can only be in the future, meaning
|
zero the next expiry time can only be in the future, meaning
|
||||||
(unlike for the xTimerStart() case above) there is no fail case
|
(unlike for the xTimerStart() case above) there is no fail case
|
||||||
that needs to be handled here. */
|
that needs to be handled here. */
|
||||||
( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow );
|
( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tmrCOMMAND_DELETE :
|
case tmrCOMMAND_DELETE :
|
||||||
/* The timer has already been removed from the active list,
|
/* The timer has already been removed from the active list,
|
||||||
just free up the memory. */
|
just free up the memory. */
|
||||||
vPortFree( pxTimer );
|
vPortFree( pxTimer );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default :
|
default :
|
||||||
/* Don't expect to get here. */
|
/* Don't expect to get here. */
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -664,7 +716,7 @@ static void prvCheckForValidListAndQueue( void )
|
|||||||
vListInitialise( &xActiveTimerList2 );
|
vListInitialise( &xActiveTimerList2 );
|
||||||
pxCurrentTimerList = &xActiveTimerList1;
|
pxCurrentTimerList = &xActiveTimerList1;
|
||||||
pxOverflowTimerList = &xActiveTimerList2;
|
pxOverflowTimerList = &xActiveTimerList2;
|
||||||
xTimerQueue = xQueueCreate( ( unsigned portBASE_TYPE ) configTIMER_QUEUE_LENGTH, sizeof( xTIMER_MESSAGE ) );
|
xTimerQueue = xQueueCreate( ( unsigned portBASE_TYPE ) configTIMER_QUEUE_LENGTH, sizeof( xDAEMON_TASK_MESSAGE ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
taskEXIT_CRITICAL();
|
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
|
/* This entire source file will be skipped if the application is not configured
|
||||||
to include software timer functionality. If you want to include software timer
|
to include software timer functionality. If you want to include software timer
|
||||||
functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
|
functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
|
||||||
|
Reference in New Issue
Block a user