Francisco Paez / freertos-cm3

Dependents:   mbed_lpc1768_freertos_lib

Committer:
fep
Date:
Wed May 31 02:36:43 2017 +0000
Revision:
0:5ff20db10a96
FreeRTOS v9.0.0 for ARM Cortex-M3 based boards.

Who changed what in which revision?

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