Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: frdm_k64f_freertos_lib
src/timers.c@0:62cd296ba2a7, 2017-05-31 (annotated)
- 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?
| User | Revision | Line number | New 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 |