Francisco Paez / freertos

Dependents:   frdm_k64f_freertos_lib

Committer:
fep
Date:
Wed May 31 02:27:10 2017 +0000
Revision:
0:62cd296ba2a7
FreeRTOS v9.0.0 for Cortex-M4F (FRDM-K64F and others...)

Who changed what in which revision?

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