Port of TI's CC3100 Websock camera demo. Using FreeRTOS, mbedTLS, also parts of Arducam for cams ov5642 and 0v2640. Can also use MT9D111. Work in progress. Be warned some parts maybe a bit flacky. This is for Seeed Arch max only, for an M3, see the demo for CM3 using the 0v5642 aducam mini.

Dependencies:   mbed

Committer:
dflet
Date:
Tue Sep 15 16:45:04 2015 +0000
Revision:
22:f9b5e0b80bf2
Parent:
0:50cedd586816
Removed some debug.

Who changed what in which revision?

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