FreeRTOS v_8.2.1 for LPC1768

Dependents:   frtos_v_8_bluetooth frtos_v_8_pololu frtos_v_8_Final

Committer:
dflet
Date:
Sat Jun 06 13:27:43 2015 +0000
Revision:
0:91ad48ad5687
Setup for LPC CM3 but may work with LPC CM4

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dflet 0:91ad48ad5687 1 /*
dflet 0:91ad48ad5687 2 FreeRTOS V8.2.1 - Copyright (C) 2015 Real Time Engineers Ltd.
dflet 0:91ad48ad5687 3 All rights reserved
dflet 0:91ad48ad5687 4
dflet 0:91ad48ad5687 5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
dflet 0:91ad48ad5687 6
dflet 0:91ad48ad5687 7 This file is part of the FreeRTOS distribution.
dflet 0:91ad48ad5687 8
dflet 0:91ad48ad5687 9 FreeRTOS is free software; you can redistribute it and/or modify it under
dflet 0:91ad48ad5687 10 the terms of the GNU General Public License (version 2) as published by the
dflet 0:91ad48ad5687 11 Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
dflet 0:91ad48ad5687 12
dflet 0:91ad48ad5687 13 ***************************************************************************
dflet 0:91ad48ad5687 14 >>! NOTE: The modification to the GPL is included to allow you to !<<
dflet 0:91ad48ad5687 15 >>! distribute a combined work that includes FreeRTOS without being !<<
dflet 0:91ad48ad5687 16 >>! obliged to provide the source code for proprietary components !<<
dflet 0:91ad48ad5687 17 >>! outside of the FreeRTOS kernel. !<<
dflet 0:91ad48ad5687 18 ***************************************************************************
dflet 0:91ad48ad5687 19
dflet 0:91ad48ad5687 20 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
dflet 0:91ad48ad5687 21 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dflet 0:91ad48ad5687 22 FOR A PARTICULAR PURPOSE. Full license text is available on the following
dflet 0:91ad48ad5687 23 link: http://www.freertos.org/a00114.html
dflet 0:91ad48ad5687 24
dflet 0:91ad48ad5687 25 ***************************************************************************
dflet 0:91ad48ad5687 26 * *
dflet 0:91ad48ad5687 27 * FreeRTOS provides completely free yet professionally developed, *
dflet 0:91ad48ad5687 28 * robust, strictly quality controlled, supported, and cross *
dflet 0:91ad48ad5687 29 * platform software that is more than just the market leader, it *
dflet 0:91ad48ad5687 30 * is the industry's de facto standard. *
dflet 0:91ad48ad5687 31 * *
dflet 0:91ad48ad5687 32 * Help yourself get started quickly while simultaneously helping *
dflet 0:91ad48ad5687 33 * to support the FreeRTOS project by purchasing a FreeRTOS *
dflet 0:91ad48ad5687 34 * tutorial book, reference manual, or both: *
dflet 0:91ad48ad5687 35 * http://www.FreeRTOS.org/Documentation *
dflet 0:91ad48ad5687 36 * *
dflet 0:91ad48ad5687 37 ***************************************************************************
dflet 0:91ad48ad5687 38
dflet 0:91ad48ad5687 39 http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
dflet 0:91ad48ad5687 40 the FAQ page "My application does not run, what could be wrong?". Have you
dflet 0:91ad48ad5687 41 defined configASSERT()?
dflet 0:91ad48ad5687 42
dflet 0:91ad48ad5687 43 http://www.FreeRTOS.org/support - In return for receiving this top quality
dflet 0:91ad48ad5687 44 embedded software for free we request you assist our global community by
dflet 0:91ad48ad5687 45 participating in the support forum.
dflet 0:91ad48ad5687 46
dflet 0:91ad48ad5687 47 http://www.FreeRTOS.org/training - Investing in training allows your team to
dflet 0:91ad48ad5687 48 be as productive as possible as early as possible. Now you can receive
dflet 0:91ad48ad5687 49 FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
dflet 0:91ad48ad5687 50 Ltd, and the world's leading authority on the world's leading RTOS.
dflet 0:91ad48ad5687 51
dflet 0:91ad48ad5687 52 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
dflet 0:91ad48ad5687 53 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
dflet 0:91ad48ad5687 54 compatible FAT file system, and our tiny thread aware UDP/IP stack.
dflet 0:91ad48ad5687 55
dflet 0:91ad48ad5687 56 http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
dflet 0:91ad48ad5687 57 Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
dflet 0:91ad48ad5687 58
dflet 0:91ad48ad5687 59 http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
dflet 0:91ad48ad5687 60 Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
dflet 0:91ad48ad5687 61 licenses offer ticketed support, indemnification and commercial middleware.
dflet 0:91ad48ad5687 62
dflet 0:91ad48ad5687 63 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
dflet 0:91ad48ad5687 64 engineered and independently SIL3 certified version for use in safety and
dflet 0:91ad48ad5687 65 mission critical applications that require provable dependability.
dflet 0:91ad48ad5687 66
dflet 0:91ad48ad5687 67 1 tab == 4 spaces!
dflet 0:91ad48ad5687 68 */
dflet 0:91ad48ad5687 69
dflet 0:91ad48ad5687 70 /* Standard includes. */
dflet 0:91ad48ad5687 71 #include <stdlib.h>
dflet 0:91ad48ad5687 72
dflet 0:91ad48ad5687 73 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
dflet 0:91ad48ad5687 74 all the API functions to use the MPU wrappers. That should only be done when
dflet 0:91ad48ad5687 75 task.h is included from an application file. */
dflet 0:91ad48ad5687 76 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
dflet 0:91ad48ad5687 77
dflet 0:91ad48ad5687 78 #include "FreeRTOS.h"
dflet 0:91ad48ad5687 79 #include "task.h"
dflet 0:91ad48ad5687 80 #include "queue.h"
dflet 0:91ad48ad5687 81 #include "timers.h"
dflet 0:91ad48ad5687 82
dflet 0:91ad48ad5687 83 #if ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 0 )
dflet 0:91ad48ad5687 84 #error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available.
dflet 0:91ad48ad5687 85 #endif
dflet 0:91ad48ad5687 86
dflet 0:91ad48ad5687 87 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the
dflet 0:91ad48ad5687 88 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
dflet 0:91ad48ad5687 89 header files above, but not in this file, in order to generate the correct
dflet 0:91ad48ad5687 90 privileged Vs unprivileged linkage and placement. */
dflet 0:91ad48ad5687 91 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
dflet 0:91ad48ad5687 92
dflet 0:91ad48ad5687 93
dflet 0:91ad48ad5687 94 /* This entire source file will be skipped if the application is not configured
dflet 0:91ad48ad5687 95 to include software timer functionality. This #if is closed at the very bottom
dflet 0:91ad48ad5687 96 of this file. If you want to include software timer functionality then ensure
dflet 0:91ad48ad5687 97 configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
dflet 0:91ad48ad5687 98 #if ( configUSE_TIMERS == 1 )
dflet 0:91ad48ad5687 99
dflet 0:91ad48ad5687 100 /* Misc definitions. */
dflet 0:91ad48ad5687 101 #define tmrNO_DELAY ( TickType_t ) 0U
dflet 0:91ad48ad5687 102
dflet 0:91ad48ad5687 103 /* The definition of the timers themselves. */
dflet 0:91ad48ad5687 104 typedef struct tmrTimerControl
dflet 0:91ad48ad5687 105 {
dflet 0:91ad48ad5687 106 const char *pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
dflet 0:91ad48ad5687 107 ListItem_t xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */
dflet 0:91ad48ad5687 108 TickType_t xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */
dflet 0:91ad48ad5687 109 UBaseType_t uxAutoReload; /*<< Set to pdTRUE if the timer should be automatically restarted once expired. Set to pdFALSE if the timer is, in effect, a one-shot timer. */
dflet 0:91ad48ad5687 110 void *pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */
dflet 0:91ad48ad5687 111 TimerCallbackFunction_t pxCallbackFunction; /*<< The function that will be called when the timer expires. */
dflet 0:91ad48ad5687 112 #if( configUSE_TRACE_FACILITY == 1 )
dflet 0:91ad48ad5687 113 UBaseType_t uxTimerNumber; /*<< An ID assigned by trace tools such as FreeRTOS+Trace */
dflet 0:91ad48ad5687 114 #endif
dflet 0:91ad48ad5687 115 } xTIMER;
dflet 0:91ad48ad5687 116
dflet 0:91ad48ad5687 117 /* The old xTIMER name is maintained above then typedefed to the new Timer_t
dflet 0:91ad48ad5687 118 name below to enable the use of older kernel aware debuggers. */
dflet 0:91ad48ad5687 119 typedef xTIMER Timer_t;
dflet 0:91ad48ad5687 120
dflet 0:91ad48ad5687 121 /* The definition of messages that can be sent and received on the timer queue.
dflet 0:91ad48ad5687 122 Two types of message can be queued - messages that manipulate a software timer,
dflet 0:91ad48ad5687 123 and messages that request the execution of a non-timer related callback. The
dflet 0:91ad48ad5687 124 two message types are defined in two separate structures, xTimerParametersType
dflet 0:91ad48ad5687 125 and xCallbackParametersType respectively. */
dflet 0:91ad48ad5687 126 typedef struct tmrTimerParameters
dflet 0:91ad48ad5687 127 {
dflet 0:91ad48ad5687 128 TickType_t xMessageValue; /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */
dflet 0:91ad48ad5687 129 Timer_t * pxTimer; /*<< The timer to which the command will be applied. */
dflet 0:91ad48ad5687 130 } TimerParameter_t;
dflet 0:91ad48ad5687 131
dflet 0:91ad48ad5687 132
dflet 0:91ad48ad5687 133 typedef struct tmrCallbackParameters
dflet 0:91ad48ad5687 134 {
dflet 0:91ad48ad5687 135 PendedFunction_t pxCallbackFunction; /* << The callback function to execute. */
dflet 0:91ad48ad5687 136 void *pvParameter1; /* << The value that will be used as the callback functions first parameter. */
dflet 0:91ad48ad5687 137 uint32_t ulParameter2; /* << The value that will be used as the callback functions second parameter. */
dflet 0:91ad48ad5687 138 } CallbackParameters_t;
dflet 0:91ad48ad5687 139
dflet 0:91ad48ad5687 140 /* The structure that contains the two message types, along with an identifier
dflet 0:91ad48ad5687 141 that is used to determine which message type is valid. */
dflet 0:91ad48ad5687 142 typedef struct tmrTimerQueueMessage
dflet 0:91ad48ad5687 143 {
dflet 0:91ad48ad5687 144 BaseType_t xMessageID; /*<< The command being sent to the timer service task. */
dflet 0:91ad48ad5687 145 union
dflet 0:91ad48ad5687 146 {
dflet 0:91ad48ad5687 147 TimerParameter_t xTimerParameters;
dflet 0:91ad48ad5687 148
dflet 0:91ad48ad5687 149 /* Don't include xCallbackParameters if it is not going to be used as
dflet 0:91ad48ad5687 150 it makes the structure (and therefore the timer queue) larger. */
dflet 0:91ad48ad5687 151 #if ( INCLUDE_xTimerPendFunctionCall == 1 )
dflet 0:91ad48ad5687 152 CallbackParameters_t xCallbackParameters;
dflet 0:91ad48ad5687 153 #endif /* INCLUDE_xTimerPendFunctionCall */
dflet 0:91ad48ad5687 154 } u;
dflet 0:91ad48ad5687 155 } DaemonTaskMessage_t;
dflet 0:91ad48ad5687 156
dflet 0:91ad48ad5687 157 /*lint -e956 A manual analysis and inspection has been used to determine which
dflet 0:91ad48ad5687 158 static variables must be declared volatile. */
dflet 0:91ad48ad5687 159
dflet 0:91ad48ad5687 160 /* The list in which active timers are stored. Timers are referenced in expire
dflet 0:91ad48ad5687 161 time order, with the nearest expiry time at the front of the list. Only the
dflet 0:91ad48ad5687 162 timer service task is allowed to access these lists. */
dflet 0:91ad48ad5687 163 PRIVILEGED_DATA static List_t xActiveTimerList1;
dflet 0:91ad48ad5687 164 PRIVILEGED_DATA static List_t xActiveTimerList2;
dflet 0:91ad48ad5687 165 PRIVILEGED_DATA static List_t *pxCurrentTimerList;
dflet 0:91ad48ad5687 166 PRIVILEGED_DATA static List_t *pxOverflowTimerList;
dflet 0:91ad48ad5687 167
dflet 0:91ad48ad5687 168 /* A queue that is used to send commands to the timer service task. */
dflet 0:91ad48ad5687 169 PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;
dflet 0:91ad48ad5687 170
dflet 0:91ad48ad5687 171 #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )
dflet 0:91ad48ad5687 172
dflet 0:91ad48ad5687 173 PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;
dflet 0:91ad48ad5687 174
dflet 0:91ad48ad5687 175 #endif
dflet 0:91ad48ad5687 176
dflet 0:91ad48ad5687 177 /*lint +e956 */
dflet 0:91ad48ad5687 178
dflet 0:91ad48ad5687 179 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 180
dflet 0:91ad48ad5687 181 /*
dflet 0:91ad48ad5687 182 * Initialise the infrastructure used by the timer service task if it has not
dflet 0:91ad48ad5687 183 * been initialised already.
dflet 0:91ad48ad5687 184 */
dflet 0:91ad48ad5687 185 static void prvCheckForValidListAndQueue( void ) PRIVILEGED_FUNCTION;
dflet 0:91ad48ad5687 186
dflet 0:91ad48ad5687 187 /*
dflet 0:91ad48ad5687 188 * The timer service task (daemon). Timer functionality is controlled by this
dflet 0:91ad48ad5687 189 * task. Other tasks communicate with the timer service task using the
dflet 0:91ad48ad5687 190 * xTimerQueue queue.
dflet 0:91ad48ad5687 191 */
dflet 0:91ad48ad5687 192 static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION;
dflet 0:91ad48ad5687 193
dflet 0:91ad48ad5687 194 /*
dflet 0:91ad48ad5687 195 * Called by the timer service task to interpret and process a command it
dflet 0:91ad48ad5687 196 * received on the timer queue.
dflet 0:91ad48ad5687 197 */
dflet 0:91ad48ad5687 198 static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION;
dflet 0:91ad48ad5687 199
dflet 0:91ad48ad5687 200 /*
dflet 0:91ad48ad5687 201 * Insert the timer into either xActiveTimerList1, or xActiveTimerList2,
dflet 0:91ad48ad5687 202 * depending on if the expire time causes a timer counter overflow.
dflet 0:91ad48ad5687 203 */
dflet 0:91ad48ad5687 204 static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) PRIVILEGED_FUNCTION;
dflet 0:91ad48ad5687 205
dflet 0:91ad48ad5687 206 /*
dflet 0:91ad48ad5687 207 * An active timer has reached its expire time. Reload the timer if it is an
dflet 0:91ad48ad5687 208 * auto reload timer, then call its callback.
dflet 0:91ad48ad5687 209 */
dflet 0:91ad48ad5687 210 static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) PRIVILEGED_FUNCTION;
dflet 0:91ad48ad5687 211
dflet 0:91ad48ad5687 212 /*
dflet 0:91ad48ad5687 213 * The tick count has overflowed. Switch the timer lists after ensuring the
dflet 0:91ad48ad5687 214 * current timer list does not still reference some timers.
dflet 0:91ad48ad5687 215 */
dflet 0:91ad48ad5687 216 static void prvSwitchTimerLists( void ) PRIVILEGED_FUNCTION;
dflet 0:91ad48ad5687 217
dflet 0:91ad48ad5687 218 /*
dflet 0:91ad48ad5687 219 * Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE
dflet 0:91ad48ad5687 220 * if a tick count overflow occurred since prvSampleTimeNow() was last called.
dflet 0:91ad48ad5687 221 */
dflet 0:91ad48ad5687 222 static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION;
dflet 0:91ad48ad5687 223
dflet 0:91ad48ad5687 224 /*
dflet 0:91ad48ad5687 225 * If the timer list contains any active timers then return the expire time of
dflet 0:91ad48ad5687 226 * the timer that will expire first and set *pxListWasEmpty to false. If the
dflet 0:91ad48ad5687 227 * timer list does not contain any timers then return 0 and set *pxListWasEmpty
dflet 0:91ad48ad5687 228 * to pdTRUE.
dflet 0:91ad48ad5687 229 */
dflet 0:91ad48ad5687 230 static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIVILEGED_FUNCTION;
dflet 0:91ad48ad5687 231
dflet 0:91ad48ad5687 232 /*
dflet 0:91ad48ad5687 233 * If a timer has expired, process it. Otherwise, block the timer service task
dflet 0:91ad48ad5687 234 * until either a timer does expire or a command is received.
dflet 0:91ad48ad5687 235 */
dflet 0:91ad48ad5687 236 static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, const BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION;
dflet 0:91ad48ad5687 237
dflet 0:91ad48ad5687 238 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 239
dflet 0:91ad48ad5687 240 BaseType_t xTimerCreateTimerTask( void )
dflet 0:91ad48ad5687 241 {
dflet 0:91ad48ad5687 242 BaseType_t xReturn = pdFAIL;
dflet 0:91ad48ad5687 243
dflet 0:91ad48ad5687 244 /* This function is called when the scheduler is started if
dflet 0:91ad48ad5687 245 configUSE_TIMERS is set to 1. Check that the infrastructure used by the
dflet 0:91ad48ad5687 246 timer service task has been created/initialised. If timers have already
dflet 0:91ad48ad5687 247 been created then the initialisation will already have been performed. */
dflet 0:91ad48ad5687 248 prvCheckForValidListAndQueue();
dflet 0:91ad48ad5687 249
dflet 0:91ad48ad5687 250 if( xTimerQueue != NULL )
dflet 0:91ad48ad5687 251 {
dflet 0:91ad48ad5687 252 #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )
dflet 0:91ad48ad5687 253 {
dflet 0:91ad48ad5687 254 /* Create the timer task, storing its handle in xTimerTaskHandle so
dflet 0:91ad48ad5687 255 it can be returned by the xTimerGetTimerDaemonTaskHandle() function. */
dflet 0:91ad48ad5687 256 xReturn = xTaskCreate( prvTimerTask, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, &xTimerTaskHandle );
dflet 0:91ad48ad5687 257 }
dflet 0:91ad48ad5687 258 #else
dflet 0:91ad48ad5687 259 {
dflet 0:91ad48ad5687 260 /* Create the timer task without storing its handle. */
dflet 0:91ad48ad5687 261 xReturn = xTaskCreate( prvTimerTask, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, NULL);
dflet 0:91ad48ad5687 262 }
dflet 0:91ad48ad5687 263 #endif
dflet 0:91ad48ad5687 264 }
dflet 0:91ad48ad5687 265 else
dflet 0:91ad48ad5687 266 {
dflet 0:91ad48ad5687 267 mtCOVERAGE_TEST_MARKER();
dflet 0:91ad48ad5687 268 }
dflet 0:91ad48ad5687 269
dflet 0:91ad48ad5687 270 configASSERT( xReturn );
dflet 0:91ad48ad5687 271 return xReturn;
dflet 0:91ad48ad5687 272 }
dflet 0:91ad48ad5687 273 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 274
dflet 0:91ad48ad5687 275 TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
dflet 0:91ad48ad5687 276 {
dflet 0:91ad48ad5687 277 Timer_t *pxNewTimer;
dflet 0:91ad48ad5687 278
dflet 0:91ad48ad5687 279 /* Allocate the timer structure. */
dflet 0:91ad48ad5687 280 if( xTimerPeriodInTicks == ( TickType_t ) 0U )
dflet 0:91ad48ad5687 281 {
dflet 0:91ad48ad5687 282 pxNewTimer = NULL;
dflet 0:91ad48ad5687 283 }
dflet 0:91ad48ad5687 284 else
dflet 0:91ad48ad5687 285 {
dflet 0:91ad48ad5687 286 pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) );
dflet 0:91ad48ad5687 287 if( pxNewTimer != NULL )
dflet 0:91ad48ad5687 288 {
dflet 0:91ad48ad5687 289 /* Ensure the infrastructure used by the timer service task has been
dflet 0:91ad48ad5687 290 created/initialised. */
dflet 0:91ad48ad5687 291 prvCheckForValidListAndQueue();
dflet 0:91ad48ad5687 292
dflet 0:91ad48ad5687 293 /* Initialise the timer structure members using the function parameters. */
dflet 0:91ad48ad5687 294 pxNewTimer->pcTimerName = pcTimerName;
dflet 0:91ad48ad5687 295 pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;
dflet 0:91ad48ad5687 296 pxNewTimer->uxAutoReload = uxAutoReload;
dflet 0:91ad48ad5687 297 pxNewTimer->pvTimerID = pvTimerID;
dflet 0:91ad48ad5687 298 pxNewTimer->pxCallbackFunction = pxCallbackFunction;
dflet 0:91ad48ad5687 299 vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );
dflet 0:91ad48ad5687 300
dflet 0:91ad48ad5687 301 traceTIMER_CREATE( pxNewTimer );
dflet 0:91ad48ad5687 302 }
dflet 0:91ad48ad5687 303 else
dflet 0:91ad48ad5687 304 {
dflet 0:91ad48ad5687 305 traceTIMER_CREATE_FAILED();
dflet 0:91ad48ad5687 306 }
dflet 0:91ad48ad5687 307 }
dflet 0:91ad48ad5687 308
dflet 0:91ad48ad5687 309 /* 0 is not a valid value for xTimerPeriodInTicks. */
dflet 0:91ad48ad5687 310 configASSERT( ( xTimerPeriodInTicks > 0 ) );
dflet 0:91ad48ad5687 311
dflet 0:91ad48ad5687 312 return ( TimerHandle_t ) pxNewTimer;
dflet 0:91ad48ad5687 313 }
dflet 0:91ad48ad5687 314 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 315
dflet 0:91ad48ad5687 316 BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait )
dflet 0:91ad48ad5687 317 {
dflet 0:91ad48ad5687 318 BaseType_t xReturn = pdFAIL;
dflet 0:91ad48ad5687 319 DaemonTaskMessage_t xMessage;
dflet 0:91ad48ad5687 320
dflet 0:91ad48ad5687 321 /* Send a message to the timer service task to perform a particular action
dflet 0:91ad48ad5687 322 on a particular timer definition. */
dflet 0:91ad48ad5687 323 if( xTimerQueue != NULL )
dflet 0:91ad48ad5687 324 {
dflet 0:91ad48ad5687 325 /* Send a command to the timer service task to start the xTimer timer. */
dflet 0:91ad48ad5687 326 xMessage.xMessageID = xCommandID;
dflet 0:91ad48ad5687 327 xMessage.u.xTimerParameters.xMessageValue = xOptionalValue;
dflet 0:91ad48ad5687 328 xMessage.u.xTimerParameters.pxTimer = ( Timer_t * ) xTimer;
dflet 0:91ad48ad5687 329
dflet 0:91ad48ad5687 330 if( xCommandID < tmrFIRST_FROM_ISR_COMMAND )
dflet 0:91ad48ad5687 331 {
dflet 0:91ad48ad5687 332 if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING )
dflet 0:91ad48ad5687 333 {
dflet 0:91ad48ad5687 334 xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait );
dflet 0:91ad48ad5687 335 }
dflet 0:91ad48ad5687 336 else
dflet 0:91ad48ad5687 337 {
dflet 0:91ad48ad5687 338 xReturn = xQueueSendToBack( xTimerQueue, &xMessage, tmrNO_DELAY );
dflet 0:91ad48ad5687 339 }
dflet 0:91ad48ad5687 340 }
dflet 0:91ad48ad5687 341 else
dflet 0:91ad48ad5687 342 {
dflet 0:91ad48ad5687 343 xReturn = xQueueSendToBackFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken );
dflet 0:91ad48ad5687 344 }
dflet 0:91ad48ad5687 345
dflet 0:91ad48ad5687 346 traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn );
dflet 0:91ad48ad5687 347 }
dflet 0:91ad48ad5687 348 else
dflet 0:91ad48ad5687 349 {
dflet 0:91ad48ad5687 350 mtCOVERAGE_TEST_MARKER();
dflet 0:91ad48ad5687 351 }
dflet 0:91ad48ad5687 352
dflet 0:91ad48ad5687 353 return xReturn;
dflet 0:91ad48ad5687 354 }
dflet 0:91ad48ad5687 355 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 356
dflet 0:91ad48ad5687 357 #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )
dflet 0:91ad48ad5687 358
dflet 0:91ad48ad5687 359 TaskHandle_t xTimerGetTimerDaemonTaskHandle( void )
dflet 0:91ad48ad5687 360 {
dflet 0:91ad48ad5687 361 /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been
dflet 0:91ad48ad5687 362 started, then xTimerTaskHandle will be NULL. */
dflet 0:91ad48ad5687 363 configASSERT( ( xTimerTaskHandle != NULL ) );
dflet 0:91ad48ad5687 364 return xTimerTaskHandle;
dflet 0:91ad48ad5687 365 }
dflet 0:91ad48ad5687 366
dflet 0:91ad48ad5687 367 #endif
dflet 0:91ad48ad5687 368 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 369
dflet 0:91ad48ad5687 370 const char * pcTimerGetTimerName( TimerHandle_t xTimer )
dflet 0:91ad48ad5687 371 {
dflet 0:91ad48ad5687 372 Timer_t *pxTimer = ( Timer_t * ) xTimer;
dflet 0:91ad48ad5687 373
dflet 0:91ad48ad5687 374 return pxTimer->pcTimerName;
dflet 0:91ad48ad5687 375 }
dflet 0:91ad48ad5687 376 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 377
dflet 0:91ad48ad5687 378 static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow )
dflet 0:91ad48ad5687 379 {
dflet 0:91ad48ad5687 380 BaseType_t xResult;
dflet 0:91ad48ad5687 381 Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );
dflet 0:91ad48ad5687 382
dflet 0:91ad48ad5687 383 /* Remove the timer from the list of active timers. A check has already
dflet 0:91ad48ad5687 384 been performed to ensure the list is not empty. */
dflet 0:91ad48ad5687 385 ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
dflet 0:91ad48ad5687 386 traceTIMER_EXPIRED( pxTimer );
dflet 0:91ad48ad5687 387
dflet 0:91ad48ad5687 388 /* If the timer is an auto reload timer then calculate the next
dflet 0:91ad48ad5687 389 expiry time and re-insert the timer in the list of active timers. */
dflet 0:91ad48ad5687 390 if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )
dflet 0:91ad48ad5687 391 {
dflet 0:91ad48ad5687 392 /* The timer is inserted into a list using a time relative to anything
dflet 0:91ad48ad5687 393 other than the current time. It will therefore be inserted into the
dflet 0:91ad48ad5687 394 correct list relative to the time this task thinks it is now. */
dflet 0:91ad48ad5687 395 if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) == pdTRUE )
dflet 0:91ad48ad5687 396 {
dflet 0:91ad48ad5687 397 /* The timer expired before it was added to the active timer
dflet 0:91ad48ad5687 398 list. Reload it now. */
dflet 0:91ad48ad5687 399 xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY );
dflet 0:91ad48ad5687 400 configASSERT( xResult );
dflet 0:91ad48ad5687 401 ( void ) xResult;
dflet 0:91ad48ad5687 402 }
dflet 0:91ad48ad5687 403 else
dflet 0:91ad48ad5687 404 {
dflet 0:91ad48ad5687 405 mtCOVERAGE_TEST_MARKER();
dflet 0:91ad48ad5687 406 }
dflet 0:91ad48ad5687 407 }
dflet 0:91ad48ad5687 408 else
dflet 0:91ad48ad5687 409 {
dflet 0:91ad48ad5687 410 mtCOVERAGE_TEST_MARKER();
dflet 0:91ad48ad5687 411 }
dflet 0:91ad48ad5687 412
dflet 0:91ad48ad5687 413 /* Call the timer callback. */
dflet 0:91ad48ad5687 414 pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
dflet 0:91ad48ad5687 415 }
dflet 0:91ad48ad5687 416 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 417
dflet 0:91ad48ad5687 418 static void prvTimerTask( void *pvParameters )
dflet 0:91ad48ad5687 419 {
dflet 0:91ad48ad5687 420 TickType_t xNextExpireTime;
dflet 0:91ad48ad5687 421 BaseType_t xListWasEmpty;
dflet 0:91ad48ad5687 422
dflet 0:91ad48ad5687 423 /* Just to avoid compiler warnings. */
dflet 0:91ad48ad5687 424 ( void ) pvParameters;
dflet 0:91ad48ad5687 425
dflet 0:91ad48ad5687 426 for( ;; )
dflet 0:91ad48ad5687 427 {
dflet 0:91ad48ad5687 428 /* Query the timers list to see if it contains any timers, and if so,
dflet 0:91ad48ad5687 429 obtain the time at which the next timer will expire. */
dflet 0:91ad48ad5687 430 xNextExpireTime = prvGetNextExpireTime( &xListWasEmpty );
dflet 0:91ad48ad5687 431
dflet 0:91ad48ad5687 432 /* If a timer has expired, process it. Otherwise, block this task
dflet 0:91ad48ad5687 433 until either a timer does expire, or a command is received. */
dflet 0:91ad48ad5687 434 prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty );
dflet 0:91ad48ad5687 435
dflet 0:91ad48ad5687 436 /* Empty the command queue. */
dflet 0:91ad48ad5687 437 prvProcessReceivedCommands();
dflet 0:91ad48ad5687 438 }
dflet 0:91ad48ad5687 439 }
dflet 0:91ad48ad5687 440 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 441
dflet 0:91ad48ad5687 442 static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, const BaseType_t xListWasEmpty )
dflet 0:91ad48ad5687 443 {
dflet 0:91ad48ad5687 444 TickType_t xTimeNow;
dflet 0:91ad48ad5687 445 BaseType_t xTimerListsWereSwitched;
dflet 0:91ad48ad5687 446
dflet 0:91ad48ad5687 447 vTaskSuspendAll();
dflet 0:91ad48ad5687 448 {
dflet 0:91ad48ad5687 449 /* Obtain the time now to make an assessment as to whether the timer
dflet 0:91ad48ad5687 450 has expired or not. If obtaining the time causes the lists to switch
dflet 0:91ad48ad5687 451 then don't process this timer as any timers that remained in the list
dflet 0:91ad48ad5687 452 when the lists were switched will have been processed within the
dflet 0:91ad48ad5687 453 prvSampleTimeNow() function. */
dflet 0:91ad48ad5687 454 xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );
dflet 0:91ad48ad5687 455 if( xTimerListsWereSwitched == pdFALSE )
dflet 0:91ad48ad5687 456 {
dflet 0:91ad48ad5687 457 /* The tick count has not overflowed, has the timer expired? */
dflet 0:91ad48ad5687 458 if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) )
dflet 0:91ad48ad5687 459 {
dflet 0:91ad48ad5687 460 ( void ) xTaskResumeAll();
dflet 0:91ad48ad5687 461 prvProcessExpiredTimer( xNextExpireTime, xTimeNow );
dflet 0:91ad48ad5687 462 }
dflet 0:91ad48ad5687 463 else
dflet 0:91ad48ad5687 464 {
dflet 0:91ad48ad5687 465 /* The tick count has not overflowed, and the next expire
dflet 0:91ad48ad5687 466 time has not been reached yet. This task should therefore
dflet 0:91ad48ad5687 467 block to wait for the next expire time or a command to be
dflet 0:91ad48ad5687 468 received - whichever comes first. The following line cannot
dflet 0:91ad48ad5687 469 be reached unless xNextExpireTime > xTimeNow, except in the
dflet 0:91ad48ad5687 470 case when the current timer list is empty. */
dflet 0:91ad48ad5687 471 vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ) );
dflet 0:91ad48ad5687 472
dflet 0:91ad48ad5687 473 if( xTaskResumeAll() == pdFALSE )
dflet 0:91ad48ad5687 474 {
dflet 0:91ad48ad5687 475 /* Yield to wait for either a command to arrive, or the
dflet 0:91ad48ad5687 476 block time to expire. If a command arrived between the
dflet 0:91ad48ad5687 477 critical section being exited and this yield then the yield
dflet 0:91ad48ad5687 478 will not cause the task to block. */
dflet 0:91ad48ad5687 479 portYIELD_WITHIN_API();
dflet 0:91ad48ad5687 480 }
dflet 0:91ad48ad5687 481 else
dflet 0:91ad48ad5687 482 {
dflet 0:91ad48ad5687 483 mtCOVERAGE_TEST_MARKER();
dflet 0:91ad48ad5687 484 }
dflet 0:91ad48ad5687 485 }
dflet 0:91ad48ad5687 486 }
dflet 0:91ad48ad5687 487 else
dflet 0:91ad48ad5687 488 {
dflet 0:91ad48ad5687 489 ( void ) xTaskResumeAll();
dflet 0:91ad48ad5687 490 }
dflet 0:91ad48ad5687 491 }
dflet 0:91ad48ad5687 492 }
dflet 0:91ad48ad5687 493 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 494
dflet 0:91ad48ad5687 495 static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty )
dflet 0:91ad48ad5687 496 {
dflet 0:91ad48ad5687 497 TickType_t xNextExpireTime;
dflet 0:91ad48ad5687 498
dflet 0:91ad48ad5687 499 /* Timers are listed in expiry time order, with the head of the list
dflet 0:91ad48ad5687 500 referencing the task that will expire first. Obtain the time at which
dflet 0:91ad48ad5687 501 the timer with the nearest expiry time will expire. If there are no
dflet 0:91ad48ad5687 502 active timers then just set the next expire time to 0. That will cause
dflet 0:91ad48ad5687 503 this task to unblock when the tick count overflows, at which point the
dflet 0:91ad48ad5687 504 timer lists will be switched and the next expiry time can be
dflet 0:91ad48ad5687 505 re-assessed. */
dflet 0:91ad48ad5687 506 *pxListWasEmpty = listLIST_IS_EMPTY( pxCurrentTimerList );
dflet 0:91ad48ad5687 507 if( *pxListWasEmpty == pdFALSE )
dflet 0:91ad48ad5687 508 {
dflet 0:91ad48ad5687 509 xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );
dflet 0:91ad48ad5687 510 }
dflet 0:91ad48ad5687 511 else
dflet 0:91ad48ad5687 512 {
dflet 0:91ad48ad5687 513 /* Ensure the task unblocks when the tick count rolls over. */
dflet 0:91ad48ad5687 514 xNextExpireTime = ( TickType_t ) 0U;
dflet 0:91ad48ad5687 515 }
dflet 0:91ad48ad5687 516
dflet 0:91ad48ad5687 517 return xNextExpireTime;
dflet 0:91ad48ad5687 518 }
dflet 0:91ad48ad5687 519 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 520
dflet 0:91ad48ad5687 521 static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched )
dflet 0:91ad48ad5687 522 {
dflet 0:91ad48ad5687 523 TickType_t xTimeNow;
dflet 0:91ad48ad5687 524 PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U; /*lint !e956 Variable is only accessible to one task. */
dflet 0:91ad48ad5687 525
dflet 0:91ad48ad5687 526 xTimeNow = xTaskGetTickCount();
dflet 0:91ad48ad5687 527
dflet 0:91ad48ad5687 528 if( xTimeNow < xLastTime )
dflet 0:91ad48ad5687 529 {
dflet 0:91ad48ad5687 530 prvSwitchTimerLists();
dflet 0:91ad48ad5687 531 *pxTimerListsWereSwitched = pdTRUE;
dflet 0:91ad48ad5687 532 }
dflet 0:91ad48ad5687 533 else
dflet 0:91ad48ad5687 534 {
dflet 0:91ad48ad5687 535 *pxTimerListsWereSwitched = pdFALSE;
dflet 0:91ad48ad5687 536 }
dflet 0:91ad48ad5687 537
dflet 0:91ad48ad5687 538 xLastTime = xTimeNow;
dflet 0:91ad48ad5687 539
dflet 0:91ad48ad5687 540 return xTimeNow;
dflet 0:91ad48ad5687 541 }
dflet 0:91ad48ad5687 542 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 543
dflet 0:91ad48ad5687 544 static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime )
dflet 0:91ad48ad5687 545 {
dflet 0:91ad48ad5687 546 BaseType_t xProcessTimerNow = pdFALSE;
dflet 0:91ad48ad5687 547
dflet 0:91ad48ad5687 548 listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime );
dflet 0:91ad48ad5687 549 listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer );
dflet 0:91ad48ad5687 550
dflet 0:91ad48ad5687 551 if( xNextExpiryTime <= xTimeNow )
dflet 0:91ad48ad5687 552 {
dflet 0:91ad48ad5687 553 /* Has the expiry time elapsed between the command to start/reset a
dflet 0:91ad48ad5687 554 timer was issued, and the time the command was processed? */
dflet 0:91ad48ad5687 555 if( ( xTimeNow - xCommandTime ) >= pxTimer->xTimerPeriodInTicks )
dflet 0:91ad48ad5687 556 {
dflet 0:91ad48ad5687 557 /* The time between a command being issued and the command being
dflet 0:91ad48ad5687 558 processed actually exceeds the timers period. */
dflet 0:91ad48ad5687 559 xProcessTimerNow = pdTRUE;
dflet 0:91ad48ad5687 560 }
dflet 0:91ad48ad5687 561 else
dflet 0:91ad48ad5687 562 {
dflet 0:91ad48ad5687 563 vListInsert( pxOverflowTimerList, &( pxTimer->xTimerListItem ) );
dflet 0:91ad48ad5687 564 }
dflet 0:91ad48ad5687 565 }
dflet 0:91ad48ad5687 566 else
dflet 0:91ad48ad5687 567 {
dflet 0:91ad48ad5687 568 if( ( xTimeNow < xCommandTime ) && ( xNextExpiryTime >= xCommandTime ) )
dflet 0:91ad48ad5687 569 {
dflet 0:91ad48ad5687 570 /* If, since the command was issued, the tick count has overflowed
dflet 0:91ad48ad5687 571 but the expiry time has not, then the timer must have already passed
dflet 0:91ad48ad5687 572 its expiry time and should be processed immediately. */
dflet 0:91ad48ad5687 573 xProcessTimerNow = pdTRUE;
dflet 0:91ad48ad5687 574 }
dflet 0:91ad48ad5687 575 else
dflet 0:91ad48ad5687 576 {
dflet 0:91ad48ad5687 577 vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) );
dflet 0:91ad48ad5687 578 }
dflet 0:91ad48ad5687 579 }
dflet 0:91ad48ad5687 580
dflet 0:91ad48ad5687 581 return xProcessTimerNow;
dflet 0:91ad48ad5687 582 }
dflet 0:91ad48ad5687 583 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 584
dflet 0:91ad48ad5687 585 static void prvProcessReceivedCommands( void )
dflet 0:91ad48ad5687 586 {
dflet 0:91ad48ad5687 587 DaemonTaskMessage_t xMessage;
dflet 0:91ad48ad5687 588 Timer_t *pxTimer;
dflet 0:91ad48ad5687 589 BaseType_t xTimerListsWereSwitched, xResult;
dflet 0:91ad48ad5687 590 TickType_t xTimeNow;
dflet 0:91ad48ad5687 591
dflet 0:91ad48ad5687 592 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. */
dflet 0:91ad48ad5687 593 {
dflet 0:91ad48ad5687 594 #if ( INCLUDE_xTimerPendFunctionCall == 1 )
dflet 0:91ad48ad5687 595 {
dflet 0:91ad48ad5687 596 /* Negative commands are pended function calls rather than timer
dflet 0:91ad48ad5687 597 commands. */
dflet 0:91ad48ad5687 598 if( xMessage.xMessageID < ( BaseType_t ) 0 )
dflet 0:91ad48ad5687 599 {
dflet 0:91ad48ad5687 600 const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters );
dflet 0:91ad48ad5687 601
dflet 0:91ad48ad5687 602 /* The timer uses the xCallbackParameters member to request a
dflet 0:91ad48ad5687 603 callback be executed. Check the callback is not NULL. */
dflet 0:91ad48ad5687 604 configASSERT( pxCallback );
dflet 0:91ad48ad5687 605
dflet 0:91ad48ad5687 606 /* Call the function. */
dflet 0:91ad48ad5687 607 pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 );
dflet 0:91ad48ad5687 608 }
dflet 0:91ad48ad5687 609 else
dflet 0:91ad48ad5687 610 {
dflet 0:91ad48ad5687 611 mtCOVERAGE_TEST_MARKER();
dflet 0:91ad48ad5687 612 }
dflet 0:91ad48ad5687 613 }
dflet 0:91ad48ad5687 614 #endif /* INCLUDE_xTimerPendFunctionCall */
dflet 0:91ad48ad5687 615
dflet 0:91ad48ad5687 616 /* Commands that are positive are timer commands rather than pended
dflet 0:91ad48ad5687 617 function calls. */
dflet 0:91ad48ad5687 618 if( xMessage.xMessageID >= ( BaseType_t ) 0 )
dflet 0:91ad48ad5687 619 {
dflet 0:91ad48ad5687 620 /* The messages uses the xTimerParameters member to work on a
dflet 0:91ad48ad5687 621 software timer. */
dflet 0:91ad48ad5687 622 pxTimer = xMessage.u.xTimerParameters.pxTimer;
dflet 0:91ad48ad5687 623
dflet 0:91ad48ad5687 624 if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE )
dflet 0:91ad48ad5687 625 {
dflet 0:91ad48ad5687 626 /* The timer is in a list, remove it. */
dflet 0:91ad48ad5687 627 ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
dflet 0:91ad48ad5687 628 }
dflet 0:91ad48ad5687 629 else
dflet 0:91ad48ad5687 630 {
dflet 0:91ad48ad5687 631 mtCOVERAGE_TEST_MARKER();
dflet 0:91ad48ad5687 632 }
dflet 0:91ad48ad5687 633
dflet 0:91ad48ad5687 634 traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.u.xTimerParameters.xMessageValue );
dflet 0:91ad48ad5687 635
dflet 0:91ad48ad5687 636 /* In this case the xTimerListsWereSwitched parameter is not used, but
dflet 0:91ad48ad5687 637 it must be present in the function call. prvSampleTimeNow() must be
dflet 0:91ad48ad5687 638 called after the message is received from xTimerQueue so there is no
dflet 0:91ad48ad5687 639 possibility of a higher priority task adding a message to the message
dflet 0:91ad48ad5687 640 queue with a time that is ahead of the timer daemon task (because it
dflet 0:91ad48ad5687 641 pre-empted the timer daemon task after the xTimeNow value was set). */
dflet 0:91ad48ad5687 642 xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );
dflet 0:91ad48ad5687 643
dflet 0:91ad48ad5687 644 switch( xMessage.xMessageID )
dflet 0:91ad48ad5687 645 {
dflet 0:91ad48ad5687 646 case tmrCOMMAND_START :
dflet 0:91ad48ad5687 647 case tmrCOMMAND_START_FROM_ISR :
dflet 0:91ad48ad5687 648 case tmrCOMMAND_RESET :
dflet 0:91ad48ad5687 649 case tmrCOMMAND_RESET_FROM_ISR :
dflet 0:91ad48ad5687 650 case tmrCOMMAND_START_DONT_TRACE :
dflet 0:91ad48ad5687 651 /* Start or restart a timer. */
dflet 0:91ad48ad5687 652 if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) == pdTRUE )
dflet 0:91ad48ad5687 653 {
dflet 0:91ad48ad5687 654 /* The timer expired before it was added to the active
dflet 0:91ad48ad5687 655 timer list. Process it now. */
dflet 0:91ad48ad5687 656 pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
dflet 0:91ad48ad5687 657 traceTIMER_EXPIRED( pxTimer );
dflet 0:91ad48ad5687 658
dflet 0:91ad48ad5687 659 if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )
dflet 0:91ad48ad5687 660 {
dflet 0:91ad48ad5687 661 xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY );
dflet 0:91ad48ad5687 662 configASSERT( xResult );
dflet 0:91ad48ad5687 663 ( void ) xResult;
dflet 0:91ad48ad5687 664 }
dflet 0:91ad48ad5687 665 else
dflet 0:91ad48ad5687 666 {
dflet 0:91ad48ad5687 667 mtCOVERAGE_TEST_MARKER();
dflet 0:91ad48ad5687 668 }
dflet 0:91ad48ad5687 669 }
dflet 0:91ad48ad5687 670 else
dflet 0:91ad48ad5687 671 {
dflet 0:91ad48ad5687 672 mtCOVERAGE_TEST_MARKER();
dflet 0:91ad48ad5687 673 }
dflet 0:91ad48ad5687 674 break;
dflet 0:91ad48ad5687 675
dflet 0:91ad48ad5687 676 case tmrCOMMAND_STOP :
dflet 0:91ad48ad5687 677 case tmrCOMMAND_STOP_FROM_ISR :
dflet 0:91ad48ad5687 678 /* The timer has already been removed from the active list.
dflet 0:91ad48ad5687 679 There is nothing to do here. */
dflet 0:91ad48ad5687 680 break;
dflet 0:91ad48ad5687 681
dflet 0:91ad48ad5687 682 case tmrCOMMAND_CHANGE_PERIOD :
dflet 0:91ad48ad5687 683 case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR :
dflet 0:91ad48ad5687 684 pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue;
dflet 0:91ad48ad5687 685 configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) );
dflet 0:91ad48ad5687 686
dflet 0:91ad48ad5687 687 /* The new period does not really have a reference, and can be
dflet 0:91ad48ad5687 688 longer or shorter than the old one. The command time is
dflet 0:91ad48ad5687 689 therefore set to the current time, and as the period cannot be
dflet 0:91ad48ad5687 690 zero the next expiry time can only be in the future, meaning
dflet 0:91ad48ad5687 691 (unlike for the xTimerStart() case above) there is no fail case
dflet 0:91ad48ad5687 692 that needs to be handled here. */
dflet 0:91ad48ad5687 693 ( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow );
dflet 0:91ad48ad5687 694 break;
dflet 0:91ad48ad5687 695
dflet 0:91ad48ad5687 696 case tmrCOMMAND_DELETE :
dflet 0:91ad48ad5687 697 /* The timer has already been removed from the active list,
dflet 0:91ad48ad5687 698 just free up the memory. */
dflet 0:91ad48ad5687 699 vPortFree( pxTimer );
dflet 0:91ad48ad5687 700 break;
dflet 0:91ad48ad5687 701
dflet 0:91ad48ad5687 702 default :
dflet 0:91ad48ad5687 703 /* Don't expect to get here. */
dflet 0:91ad48ad5687 704 break;
dflet 0:91ad48ad5687 705 }
dflet 0:91ad48ad5687 706 }
dflet 0:91ad48ad5687 707 }
dflet 0:91ad48ad5687 708 }
dflet 0:91ad48ad5687 709 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 710
dflet 0:91ad48ad5687 711 static void prvSwitchTimerLists( void )
dflet 0:91ad48ad5687 712 {
dflet 0:91ad48ad5687 713 TickType_t xNextExpireTime, xReloadTime;
dflet 0:91ad48ad5687 714 List_t *pxTemp;
dflet 0:91ad48ad5687 715 Timer_t *pxTimer;
dflet 0:91ad48ad5687 716 BaseType_t xResult;
dflet 0:91ad48ad5687 717
dflet 0:91ad48ad5687 718 /* The tick count has overflowed. The timer lists must be switched.
dflet 0:91ad48ad5687 719 If there are any timers still referenced from the current timer list
dflet 0:91ad48ad5687 720 then they must have expired and should be processed before the lists
dflet 0:91ad48ad5687 721 are switched. */
dflet 0:91ad48ad5687 722 while( listLIST_IS_EMPTY( pxCurrentTimerList ) == pdFALSE )
dflet 0:91ad48ad5687 723 {
dflet 0:91ad48ad5687 724 xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );
dflet 0:91ad48ad5687 725
dflet 0:91ad48ad5687 726 /* Remove the timer from the list. */
dflet 0:91ad48ad5687 727 pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );
dflet 0:91ad48ad5687 728 ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
dflet 0:91ad48ad5687 729 traceTIMER_EXPIRED( pxTimer );
dflet 0:91ad48ad5687 730
dflet 0:91ad48ad5687 731 /* Execute its callback, then send a command to restart the timer if
dflet 0:91ad48ad5687 732 it is an auto-reload timer. It cannot be restarted here as the lists
dflet 0:91ad48ad5687 733 have not yet been switched. */
dflet 0:91ad48ad5687 734 pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
dflet 0:91ad48ad5687 735
dflet 0:91ad48ad5687 736 if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )
dflet 0:91ad48ad5687 737 {
dflet 0:91ad48ad5687 738 /* Calculate the reload value, and if the reload value results in
dflet 0:91ad48ad5687 739 the timer going into the same timer list then it has already expired
dflet 0:91ad48ad5687 740 and the timer should be re-inserted into the current list so it is
dflet 0:91ad48ad5687 741 processed again within this loop. Otherwise a command should be sent
dflet 0:91ad48ad5687 742 to restart the timer to ensure it is only inserted into a list after
dflet 0:91ad48ad5687 743 the lists have been swapped. */
dflet 0:91ad48ad5687 744 xReloadTime = ( xNextExpireTime + pxTimer->xTimerPeriodInTicks );
dflet 0:91ad48ad5687 745 if( xReloadTime > xNextExpireTime )
dflet 0:91ad48ad5687 746 {
dflet 0:91ad48ad5687 747 listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xReloadTime );
dflet 0:91ad48ad5687 748 listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer );
dflet 0:91ad48ad5687 749 vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) );
dflet 0:91ad48ad5687 750 }
dflet 0:91ad48ad5687 751 else
dflet 0:91ad48ad5687 752 {
dflet 0:91ad48ad5687 753 xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY );
dflet 0:91ad48ad5687 754 configASSERT( xResult );
dflet 0:91ad48ad5687 755 ( void ) xResult;
dflet 0:91ad48ad5687 756 }
dflet 0:91ad48ad5687 757 }
dflet 0:91ad48ad5687 758 else
dflet 0:91ad48ad5687 759 {
dflet 0:91ad48ad5687 760 mtCOVERAGE_TEST_MARKER();
dflet 0:91ad48ad5687 761 }
dflet 0:91ad48ad5687 762 }
dflet 0:91ad48ad5687 763
dflet 0:91ad48ad5687 764 pxTemp = pxCurrentTimerList;
dflet 0:91ad48ad5687 765 pxCurrentTimerList = pxOverflowTimerList;
dflet 0:91ad48ad5687 766 pxOverflowTimerList = pxTemp;
dflet 0:91ad48ad5687 767 }
dflet 0:91ad48ad5687 768 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 769
dflet 0:91ad48ad5687 770 static void prvCheckForValidListAndQueue( void )
dflet 0:91ad48ad5687 771 {
dflet 0:91ad48ad5687 772 /* Check that the list from which active timers are referenced, and the
dflet 0:91ad48ad5687 773 queue used to communicate with the timer service, have been
dflet 0:91ad48ad5687 774 initialised. */
dflet 0:91ad48ad5687 775 taskENTER_CRITICAL();
dflet 0:91ad48ad5687 776 {
dflet 0:91ad48ad5687 777 if( xTimerQueue == NULL )
dflet 0:91ad48ad5687 778 {
dflet 0:91ad48ad5687 779 vListInitialise( &xActiveTimerList1 );
dflet 0:91ad48ad5687 780 vListInitialise( &xActiveTimerList2 );
dflet 0:91ad48ad5687 781 pxCurrentTimerList = &xActiveTimerList1;
dflet 0:91ad48ad5687 782 pxOverflowTimerList = &xActiveTimerList2;
dflet 0:91ad48ad5687 783 xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) );
dflet 0:91ad48ad5687 784 configASSERT( xTimerQueue );
dflet 0:91ad48ad5687 785
dflet 0:91ad48ad5687 786 #if ( configQUEUE_REGISTRY_SIZE > 0 )
dflet 0:91ad48ad5687 787 {
dflet 0:91ad48ad5687 788 if( xTimerQueue != NULL )
dflet 0:91ad48ad5687 789 {
dflet 0:91ad48ad5687 790 vQueueAddToRegistry( xTimerQueue, "TmrQ" );
dflet 0:91ad48ad5687 791 }
dflet 0:91ad48ad5687 792 else
dflet 0:91ad48ad5687 793 {
dflet 0:91ad48ad5687 794 mtCOVERAGE_TEST_MARKER();
dflet 0:91ad48ad5687 795 }
dflet 0:91ad48ad5687 796 }
dflet 0:91ad48ad5687 797 #endif /* configQUEUE_REGISTRY_SIZE */
dflet 0:91ad48ad5687 798 }
dflet 0:91ad48ad5687 799 else
dflet 0:91ad48ad5687 800 {
dflet 0:91ad48ad5687 801 mtCOVERAGE_TEST_MARKER();
dflet 0:91ad48ad5687 802 }
dflet 0:91ad48ad5687 803 }
dflet 0:91ad48ad5687 804 taskEXIT_CRITICAL();
dflet 0:91ad48ad5687 805 }
dflet 0:91ad48ad5687 806 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 807
dflet 0:91ad48ad5687 808 BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer )
dflet 0:91ad48ad5687 809 {
dflet 0:91ad48ad5687 810 BaseType_t xTimerIsInActiveList;
dflet 0:91ad48ad5687 811 Timer_t *pxTimer = ( Timer_t * ) xTimer;
dflet 0:91ad48ad5687 812
dflet 0:91ad48ad5687 813 /* Is the timer in the list of active timers? */
dflet 0:91ad48ad5687 814 taskENTER_CRITICAL();
dflet 0:91ad48ad5687 815 {
dflet 0:91ad48ad5687 816 /* Checking to see if it is in the NULL list in effect checks to see if
dflet 0:91ad48ad5687 817 it is referenced from either the current or the overflow timer lists in
dflet 0:91ad48ad5687 818 one go, but the logic has to be reversed, hence the '!'. */
dflet 0:91ad48ad5687 819 xTimerIsInActiveList = ( BaseType_t ) !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) );
dflet 0:91ad48ad5687 820 }
dflet 0:91ad48ad5687 821 taskEXIT_CRITICAL();
dflet 0:91ad48ad5687 822
dflet 0:91ad48ad5687 823 return xTimerIsInActiveList;
dflet 0:91ad48ad5687 824 } /*lint !e818 Can't be pointer to const due to the typedef. */
dflet 0:91ad48ad5687 825 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 826
dflet 0:91ad48ad5687 827 void *pvTimerGetTimerID( const TimerHandle_t xTimer )
dflet 0:91ad48ad5687 828 {
dflet 0:91ad48ad5687 829 Timer_t * const pxTimer = ( Timer_t * ) xTimer;
dflet 0:91ad48ad5687 830 void *pvReturn;
dflet 0:91ad48ad5687 831
dflet 0:91ad48ad5687 832 configASSERT( xTimer );
dflet 0:91ad48ad5687 833
dflet 0:91ad48ad5687 834 taskENTER_CRITICAL();
dflet 0:91ad48ad5687 835 {
dflet 0:91ad48ad5687 836 pvReturn = pxTimer->pvTimerID;
dflet 0:91ad48ad5687 837 }
dflet 0:91ad48ad5687 838 taskEXIT_CRITICAL();
dflet 0:91ad48ad5687 839
dflet 0:91ad48ad5687 840 return pvReturn;
dflet 0:91ad48ad5687 841 }
dflet 0:91ad48ad5687 842 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 843
dflet 0:91ad48ad5687 844 void vTimerSetTimerID( const TimerHandle_t xTimer, void *pvNewID )
dflet 0:91ad48ad5687 845 {
dflet 0:91ad48ad5687 846 Timer_t * const pxTimer = ( Timer_t * ) xTimer;
dflet 0:91ad48ad5687 847
dflet 0:91ad48ad5687 848 configASSERT( xTimer );
dflet 0:91ad48ad5687 849
dflet 0:91ad48ad5687 850 taskENTER_CRITICAL();
dflet 0:91ad48ad5687 851 {
dflet 0:91ad48ad5687 852 pxTimer->pvTimerID = pvNewID;
dflet 0:91ad48ad5687 853 }
dflet 0:91ad48ad5687 854 taskEXIT_CRITICAL();
dflet 0:91ad48ad5687 855 }
dflet 0:91ad48ad5687 856 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 857
dflet 0:91ad48ad5687 858 #if( INCLUDE_xTimerPendFunctionCall == 1 )
dflet 0:91ad48ad5687 859
dflet 0:91ad48ad5687 860 BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken )
dflet 0:91ad48ad5687 861 {
dflet 0:91ad48ad5687 862 DaemonTaskMessage_t xMessage;
dflet 0:91ad48ad5687 863 BaseType_t xReturn;
dflet 0:91ad48ad5687 864
dflet 0:91ad48ad5687 865 /* Complete the message with the function parameters and post it to the
dflet 0:91ad48ad5687 866 daemon task. */
dflet 0:91ad48ad5687 867 xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR;
dflet 0:91ad48ad5687 868 xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;
dflet 0:91ad48ad5687 869 xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;
dflet 0:91ad48ad5687 870 xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;
dflet 0:91ad48ad5687 871
dflet 0:91ad48ad5687 872 xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken );
dflet 0:91ad48ad5687 873
dflet 0:91ad48ad5687 874 tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, xReturn );
dflet 0:91ad48ad5687 875
dflet 0:91ad48ad5687 876 return xReturn;
dflet 0:91ad48ad5687 877 }
dflet 0:91ad48ad5687 878
dflet 0:91ad48ad5687 879 #endif /* INCLUDE_xTimerPendFunctionCall */
dflet 0:91ad48ad5687 880 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 881
dflet 0:91ad48ad5687 882 #if( INCLUDE_xTimerPendFunctionCall == 1 )
dflet 0:91ad48ad5687 883
dflet 0:91ad48ad5687 884 BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait )
dflet 0:91ad48ad5687 885 {
dflet 0:91ad48ad5687 886 DaemonTaskMessage_t xMessage;
dflet 0:91ad48ad5687 887 BaseType_t xReturn;
dflet 0:91ad48ad5687 888
dflet 0:91ad48ad5687 889 /* This function can only be called after a timer has been created or
dflet 0:91ad48ad5687 890 after the scheduler has been started because, until then, the timer
dflet 0:91ad48ad5687 891 queue does not exist. */
dflet 0:91ad48ad5687 892 configASSERT( xTimerQueue );
dflet 0:91ad48ad5687 893
dflet 0:91ad48ad5687 894 /* Complete the message with the function parameters and post it to the
dflet 0:91ad48ad5687 895 daemon task. */
dflet 0:91ad48ad5687 896 xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK;
dflet 0:91ad48ad5687 897 xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;
dflet 0:91ad48ad5687 898 xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;
dflet 0:91ad48ad5687 899 xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;
dflet 0:91ad48ad5687 900
dflet 0:91ad48ad5687 901 xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait );
dflet 0:91ad48ad5687 902
dflet 0:91ad48ad5687 903 tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, xReturn );
dflet 0:91ad48ad5687 904
dflet 0:91ad48ad5687 905 return xReturn;
dflet 0:91ad48ad5687 906 }
dflet 0:91ad48ad5687 907
dflet 0:91ad48ad5687 908 #endif /* INCLUDE_xTimerPendFunctionCall */
dflet 0:91ad48ad5687 909 /*-----------------------------------------------------------*/
dflet 0:91ad48ad5687 910
dflet 0:91ad48ad5687 911 /* This entire source file will be skipped if the application is not configured
dflet 0:91ad48ad5687 912 to include software timer functionality. If you want to include software timer
dflet 0:91ad48ad5687 913 functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
dflet 0:91ad48ad5687 914 #endif /* configUSE_TIMERS == 1 */
dflet 0:91ad48ad5687 915
dflet 0:91ad48ad5687 916
dflet 0:91ad48ad5687 917
dflet 0:91ad48ad5687 918