* Insert the timer into either xActiveTimerList1, or xActiveTimerList2,\r
* depending on if the expire time causes a timer counter overflow.\r
*/\r
-static void prvInsertTimerInActiveList( xTIMER *pxTimer, portTickType xNextExpiryTime, portTickType xTimeNow ) PRIVILEGED_FUNCTION;\r
+static portBASE_TYPE prvInsertTimerInActiveList( xTIMER *pxTimer, portTickType xNextExpiryTime, portTickType xTimeNow, portTickType xCommandTime ) PRIVILEGED_FUNCTION;\r
\r
/*\r
* An active timer has reached its expire time. Reload the timer if it is an\r
xTIMER *pxNewTimer;\r
\r
/* Allocate the timer structure. */\r
- pxNewTimer = ( xTIMER * ) pvPortMalloc( sizeof( xTIMER ) );\r
- if( pxNewTimer != NULL )\r
+ if( xTimerPeriodInTicks == ( portTickType ) 0U )\r
{\r
- /* Ensure the infrastructure used by the timer service task has been\r
- created/initialised. */\r
- prvCheckForValidListAndQueue();\r
-\r
- /* Initialise the timer structure members using the function parameters. */\r
- pxNewTimer->pcTimerName = pcTimerName;\r
- pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;\r
- pxNewTimer->uxAutoReload = uxAutoReload;\r
- pxNewTimer->pvTimerID = pvTimerID;\r
- pxNewTimer->pxCallbackFunction = pxCallbackFunction;\r
- vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );\r
+ pxNewTimer = NULL;\r
+ configASSERT( ( xTimerPeriodInTicks > 0 ) );\r
}\r
-\r
+ else\r
+ {\r
+ pxNewTimer = ( xTIMER * ) pvPortMalloc( sizeof( xTIMER ) );\r
+ if( pxNewTimer != NULL )\r
+ {\r
+ /* Ensure the infrastructure used by the timer service task has been\r
+ created/initialised. */\r
+ prvCheckForValidListAndQueue();\r
+ \r
+ configASSERT( ( xTimerPeriodInTicks > 0 ) );\r
+ \r
+ /* Initialise the timer structure members using the function parameters. */\r
+ pxNewTimer->pcTimerName = pcTimerName;\r
+ pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;\r
+ pxNewTimer->uxAutoReload = uxAutoReload;\r
+ pxNewTimer->pvTimerID = pvTimerID;\r
+ pxNewTimer->pxCallbackFunction = pxCallbackFunction;\r
+ vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );\r
+ }\r
+ }\r
+ \r
return ( xTimerHandle ) pxNewTimer;\r
}\r
/*-----------------------------------------------------------*/\r
}\r
}\r
\r
+ configASSERT( xReturn );\r
return xReturn;\r
}\r
/*-----------------------------------------------------------*/\r
}\r
else\r
{\r
- /* The tick count has not overflowed, and the next expire \r
- time has not been reached yet. This task should therefore \r
- block to wait for the next expire time or a command to be \r
+ /* The tick count has not overflowed, and the next expire\r
+ time has not been reached yet. This task should therefore\r
+ block to wait for the next expire time or a command to be\r
received - whichever comes first. The following line cannot\r
- be reached unless xNextExpireTime > xTimeNow, except in the \r
+ be reached unless xNextExpireTime > xTimeNow, except in the\r
case when the current timer list is empty. */\r
vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ) );\r
}\r
the timer with the nearest expiry time will expire. If there are no\r
active timers then just set the next expire time to 0. That will cause\r
this task to unblock when the tick count overflows, at which point the\r
- timer lists will be switched and the next expiry time can be \r
+ timer lists will be switched and the next expiry time can be\r
re-assessed. */\r
*pxListWasEmpty = listLIST_IS_EMPTY( pxCurrentTimerList );\r
if( *pxListWasEmpty == pdFALSE )\r
}\r
/*-----------------------------------------------------------*/\r
\r
-static void prvInsertTimerInActiveList( xTIMER *pxTimer, portTickType xNextExpiryTime, portTickType xTimeNow )\r
+static portBASE_TYPE prvInsertTimerInActiveList( xTIMER *pxTimer, portTickType xNextExpiryTime, portTickType xTimeNow, portTickType xCommandTime )\r
{\r
+portBASE_TYPE xProcessTimerNow = pdFALSE;\r
+\r
listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime );\r
listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer );\r
\r
- if( xNextExpiryTime < xTimeNow )\r
+ if( xNextExpiryTime <= xTimeNow )\r
{\r
- vListInsert( pxOverflowTimerList, &( pxTimer->xTimerListItem ) );\r
+ /* Has the expiry time elapsed between the command to start/reset a\r
+ timer was issued, and the time the command was processed? */\r
+ if( ( xTimeNow - xCommandTime ) >= pxTimer->xTimerPeriodInTicks )\r
+ {\r
+ /* The time between a command being issued and the command being\r
+ processed actually exceeds the timers period. */\r
+ xProcessTimerNow = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ vListInsert( pxOverflowTimerList, &( pxTimer->xTimerListItem ) );\r
+ }\r
}\r
else\r
{\r
- vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) );\r
+ if( ( xTimeNow < xCommandTime ) && ( xNextExpiryTime >= xCommandTime ) )\r
+ {\r
+ /* If, since the command was issued, the tick count has overflowed\r
+ but the expiry time has not, then the timer must have already passed\r
+ its expiry time and should be processed immediately. */\r
+ xProcessTimerNow = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) );\r
+ }\r
}\r
+\r
+ return xProcessTimerNow;\r
}\r
/*-----------------------------------------------------------*/\r
\r
{\r
case tmrCOMMAND_START : \r
/* Start or restart a timer. */\r
- prvInsertTimerInActiveList( pxTimer, xTimeNow + pxTimer->xTimerPeriodInTicks, xTimeNow );\r
+ if( prvInsertTimerInActiveList( pxTimer, xMessage.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.xMessageValue ) == pdTRUE )\r
+ {\r
+ /* The timer expired before it was added to the active timer\r
+ list. Process it now. */\r
+ /* Call the timer callback. */\r
+ pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer );\r
+\r
+ if( pxTimer->uxAutoReload == pdTRUE )\r
+ {\r
+ xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xMessage.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY );\r
+ }\r
+ }\r
break;\r
\r
case tmrCOMMAND_STOP : \r
\r
case tmrCOMMAND_CHANGE_PERIOD :\r
pxTimer->xTimerPeriodInTicks = xMessage.xMessageValue;\r
- prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow );\r
+ configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) );\r
+ prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow );\r
break;\r
\r
case tmrCOMMAND_DELETE :\r
/*-----------------------------------------------------------*/\r
\r
\r
-\r
-\r