/*\r
- FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.\r
- All rights reserved\r
-\r
- VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
-\r
- ***************************************************************************\r
- * *\r
- * FreeRTOS provides completely free yet professionally developed, *\r
- * robust, strictly quality controlled, supported, and cross *\r
- * platform software that has become a de facto standard. *\r
- * *\r
- * Help yourself get started quickly and support the FreeRTOS *\r
- * project by purchasing a FreeRTOS tutorial book, reference *\r
- * manual, or both from: http://www.FreeRTOS.org/Documentation *\r
- * *\r
- * Thank you! *\r
- * *\r
- ***************************************************************************\r
-\r
- This file is part of the FreeRTOS distribution.\r
-\r
- FreeRTOS is free software; you can redistribute it and/or modify it under\r
- the terms of the GNU General Public License (version 2) as published by the\r
- Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
-\r
- >>! NOTE: The modification to the GPL is included to allow you to distribute\r
- >>! a combined work that includes FreeRTOS without being obliged to provide\r
- >>! the source code for proprietary components outside of the FreeRTOS\r
- >>! kernel.\r
-\r
- FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
- FOR A PARTICULAR PURPOSE. Full license text is available from the following\r
- link: http://www.freertos.org/a00114.html\r
-\r
- 1 tab == 4 spaces!\r
-\r
- ***************************************************************************\r
- * *\r
- * Having a problem? Start by reading the FAQ "My application does *\r
- * not run, what could be wrong?" *\r
- * *\r
- * http://www.FreeRTOS.org/FAQHelp.html *\r
- * *\r
- ***************************************************************************\r
-\r
- http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
- license and Real Time Engineers Ltd. contact details.\r
-\r
- http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
- including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
- compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
-\r
- http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
- Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS\r
- licenses offer ticketed support, indemnification and middleware.\r
-\r
- http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
- engineered and independently SIL3 certified version for use in safety and\r
- mission critical applications that require provable dependability.\r
-\r
- 1 tab == 4 spaces!\r
-*/\r
+ * FreeRTOS Kernel V10.2.1\r
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://aws.amazon.com/freertos\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ */\r
\r
/* Standard includes. */\r
#include <stdlib.h>\r
#error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available.\r
#endif\r
\r
-/* Lint e961 and e750 are suppressed as a MISRA exception justified because the\r
-MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the\r
-header files above, but not in this file, in order to generate the correct\r
-privileged Vs unprivileged linkage and placement. */\r
-#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */\r
+/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified\r
+because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined\r
+for the header files above, but not in this file, in order to generate the\r
+correct privileged Vs unprivileged linkage and placement. */\r
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e9021 !e961 !e750. */\r
\r
\r
/* This entire source file will be skipped if the application is not configured\r
/* Misc definitions. */\r
#define tmrNO_DELAY ( TickType_t ) 0U\r
\r
+/* The name assigned to the timer service task. This can be overridden by\r
+defining trmTIMER_SERVICE_TASK_NAME in FreeRTOSConfig.h. */\r
+#ifndef configTIMER_SERVICE_TASK_NAME\r
+ #define configTIMER_SERVICE_TASK_NAME "Tmr Svc"\r
+#endif\r
+\r
+/* Bit definitions used in the ucStatus member of a timer structure. */\r
+#define tmrSTATUS_IS_ACTIVE ( ( uint8_t ) 0x01 )\r
+#define tmrSTATUS_IS_STATICALLY_ALLOCATED ( ( uint8_t ) 0x02 )\r
+#define tmrSTATUS_IS_AUTORELOAD ( ( uint8_t ) 0x04 )\r
+\r
/* The definition of the timers themselves. */\r
-typedef struct tmrTimerControl\r
+typedef struct tmrTimerControl /* The old naming convention is used to prevent breaking kernel aware debuggers. */\r
{\r
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. */\r
ListItem_t xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */\r
TickType_t xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */\r
- 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. */\r
void *pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */\r
TimerCallbackFunction_t pxCallbackFunction; /*<< The function that will be called when the timer expires. */\r
#if( configUSE_TRACE_FACILITY == 1 )\r
UBaseType_t uxTimerNumber; /*<< An ID assigned by trace tools such as FreeRTOS+Trace */\r
#endif\r
-} Timer_t;\r
+ uint8_t ucStatus; /*<< Holds bits to say if the timer was statically allocated or not, and if it is active or not. */\r
+} xTIMER;\r
+\r
+/* The old xTIMER name is maintained above then typedefed to the new Timer_t\r
+name below to enable the use of older kernel aware debuggers. */\r
+typedef xTIMER Timer_t;\r
\r
/* The definition of messages that can be sent and received on the timer queue.\r
Two types of message can be queued - messages that manipulate a software timer,\r
} u;\r
} DaemonTaskMessage_t;\r
\r
-/*lint -e956 A manual analysis and inspection has been used to determine which\r
-static variables must be declared volatile. */\r
+/*lint -save -e956 A manual analysis and inspection has been used to determine\r
+which static variables must be declared volatile. */\r
\r
/* The list in which active timers are stored. Timers are referenced in expire\r
time order, with the nearest expiry time at the front of the list. Only the\r
-timer service task is allowed to access these lists. */\r
+timer service task is allowed to access these lists.\r
+xActiveTimerList1 and xActiveTimerList2 could be at function scope but that\r
+breaks some kernel aware debuggers, and debuggers that reply on removing the\r
+static qualifier. */\r
PRIVILEGED_DATA static List_t xActiveTimerList1;\r
PRIVILEGED_DATA static List_t xActiveTimerList2;\r
PRIVILEGED_DATA static List_t *pxCurrentTimerList;\r
\r
/* A queue that is used to send commands to the timer service task. */\r
PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;\r
+PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;\r
\r
-#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )\r
+/*lint -restore */\r
\r
- PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;\r
+/*-----------------------------------------------------------*/\r
\r
-#endif\r
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
\r
-/*lint +e956 */\r
+ /* If static allocation is supported then the application must provide the\r
+ following callback function - which enables the application to optionally\r
+ provide the memory that will be used by the timer task as the task's stack\r
+ and TCB. */\r
+ extern void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize );\r
\r
-/*-----------------------------------------------------------*/\r
+#endif\r
\r
/*\r
* Initialise the infrastructure used by the timer service task if it has not\r
* task. Other tasks communicate with the timer service task using the\r
* xTimerQueue queue.\r
*/\r
-static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION;\r
+static portTASK_FUNCTION_PROTO( prvTimerTask, pvParameters ) PRIVILEGED_FUNCTION;\r
\r
/*\r
* Called by the timer service task to interpret and process a command it\r
* received on the timer queue.\r
*/\r
-static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION;\r
+static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION;\r
\r
/*\r
* Insert the timer into either xActiveTimerList1, or xActiveTimerList2,\r
\r
/*\r
* An active timer has reached its expire time. Reload the timer if it is an\r
- * auto reload timer, then call its callback.\r
+ * auto-reload timer, then call its callback.\r
*/\r
static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) PRIVILEGED_FUNCTION;\r
\r
* If a timer has expired, process it. Otherwise, block the timer service task\r
* until either a timer does expire or a command is received.\r
*/\r
-static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, const BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION;\r
+static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION;\r
\r
+/*\r
+ * Called after a Timer_t structure has been allocated either statically or\r
+ * dynamically to fill in the structure's members.\r
+ */\r
+static void prvInitialiseNewTimer( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+ const TickType_t xTimerPeriodInTicks,\r
+ const UBaseType_t uxAutoReload,\r
+ void * const pvTimerID,\r
+ TimerCallbackFunction_t pxCallbackFunction,\r
+ Timer_t *pxNewTimer ) PRIVILEGED_FUNCTION;\r
/*-----------------------------------------------------------*/\r
\r
BaseType_t xTimerCreateTimerTask( void )\r
\r
if( xTimerQueue != NULL )\r
{\r
- #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )\r
+ #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
{\r
- /* Create the timer task, storing its handle in xTimerTaskHandle so\r
- it can be returned by the xTimerGetTimerDaemonTaskHandle() function. */\r
- xReturn = xTaskCreate( prvTimerTask, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, &xTimerTaskHandle );\r
+ StaticTask_t *pxTimerTaskTCBBuffer = NULL;\r
+ StackType_t *pxTimerTaskStackBuffer = NULL;\r
+ uint32_t ulTimerTaskStackSize;\r
+\r
+ vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer, &pxTimerTaskStackBuffer, &ulTimerTaskStackSize );\r
+ xTimerTaskHandle = xTaskCreateStatic( prvTimerTask,\r
+ configTIMER_SERVICE_TASK_NAME,\r
+ ulTimerTaskStackSize,\r
+ NULL,\r
+ ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,\r
+ pxTimerTaskStackBuffer,\r
+ pxTimerTaskTCBBuffer );\r
+\r
+ if( xTimerTaskHandle != NULL )\r
+ {\r
+ xReturn = pdPASS;\r
+ }\r
}\r
#else\r
{\r
- /* Create the timer task without storing its handle. */\r
- xReturn = xTaskCreate( prvTimerTask, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, NULL);\r
+ xReturn = xTaskCreate( prvTimerTask,\r
+ configTIMER_SERVICE_TASK_NAME,\r
+ configTIMER_TASK_STACK_DEPTH,\r
+ NULL,\r
+ ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,\r
+ &xTimerTaskHandle );\r
}\r
- #endif\r
+ #endif /* configSUPPORT_STATIC_ALLOCATION */\r
}\r
else\r
{\r
}\r
/*-----------------------------------------------------------*/\r
\r
-TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
-{\r
-Timer_t *pxNewTimer;\r
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
\r
- /* Allocate the timer structure. */\r
- if( xTimerPeriodInTicks == ( TickType_t ) 0U )\r
+ TimerHandle_t xTimerCreate( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+ const TickType_t xTimerPeriodInTicks,\r
+ const UBaseType_t uxAutoReload,\r
+ void * const pvTimerID,\r
+ TimerCallbackFunction_t pxCallbackFunction )\r
{\r
- pxNewTimer = NULL;\r
+ Timer_t *pxNewTimer;\r
+\r
+ pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of Timer_t is always a pointer to the timer's mame. */\r
+\r
+ if( pxNewTimer != NULL )\r
+ {\r
+ /* Status is thus far zero as the timer is not created statically\r
+ and has not been started. The auto-reload bit may get set in\r
+ prvInitialiseNewTimer. */\r
+ pxNewTimer->ucStatus = 0x00;\r
+ prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );\r
+ }\r
+\r
+ return pxNewTimer;\r
}\r
- else\r
+\r
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
+\r
+ TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+ const TickType_t xTimerPeriodInTicks,\r
+ const UBaseType_t uxAutoReload,\r
+ void * const pvTimerID,\r
+ TimerCallbackFunction_t pxCallbackFunction,\r
+ StaticTimer_t *pxTimerBuffer )\r
{\r
- pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) );\r
- if( pxNewTimer != NULL )\r
+ Timer_t *pxNewTimer;\r
+\r
+ #if( configASSERT_DEFINED == 1 )\r
{\r
- /* Ensure the infrastructure used by the timer service task has been\r
- created/initialised. */\r
- prvCheckForValidListAndQueue();\r
-\r
- /* Initialise the timer structure members using the function parameters. */\r
- pxNewTimer->pcTimerName = pcTimerName;\r
- pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;\r
- pxNewTimer->uxAutoReload = uxAutoReload;\r
- pxNewTimer->pvTimerID = pvTimerID;\r
- pxNewTimer->pxCallbackFunction = pxCallbackFunction;\r
- vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );\r
-\r
- traceTIMER_CREATE( pxNewTimer );\r
+ /* Sanity check that the size of the structure used to declare a\r
+ variable of type StaticTimer_t equals the size of the real timer\r
+ structure. */\r
+ volatile size_t xSize = sizeof( StaticTimer_t );\r
+ configASSERT( xSize == sizeof( Timer_t ) );\r
+ ( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */\r
}\r
- else\r
+ #endif /* configASSERT_DEFINED */\r
+\r
+ /* A pointer to a StaticTimer_t structure MUST be provided, use it. */\r
+ configASSERT( pxTimerBuffer );\r
+ pxNewTimer = ( Timer_t * ) pxTimerBuffer; /*lint !e740 !e9087 StaticTimer_t is a pointer to a Timer_t, so guaranteed to be aligned and sized correctly (checked by an assert()), so this is safe. */\r
+\r
+ if( pxNewTimer != NULL )\r
{\r
- traceTIMER_CREATE_FAILED();\r
+ /* Timers can be created statically or dynamically so note this\r
+ timer was created statically in case it is later deleted. The\r
+ auto-reload bit may get set in prvInitialiseNewTimer(). */\r
+ pxNewTimer->ucStatus = tmrSTATUS_IS_STATICALLY_ALLOCATED;\r
+\r
+ prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );\r
}\r
+\r
+ return pxNewTimer;\r
}\r
\r
+#endif /* configSUPPORT_STATIC_ALLOCATION */\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvInitialiseNewTimer( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+ const TickType_t xTimerPeriodInTicks,\r
+ const UBaseType_t uxAutoReload,\r
+ void * const pvTimerID,\r
+ TimerCallbackFunction_t pxCallbackFunction,\r
+ Timer_t *pxNewTimer )\r
+{\r
/* 0 is not a valid value for xTimerPeriodInTicks. */\r
configASSERT( ( xTimerPeriodInTicks > 0 ) );\r
\r
- return ( TimerHandle_t ) pxNewTimer;\r
+ if( pxNewTimer != NULL )\r
+ {\r
+ /* Ensure the infrastructure used by the timer service task has been\r
+ created/initialised. */\r
+ prvCheckForValidListAndQueue();\r
+\r
+ /* Initialise the timer structure members using the function\r
+ parameters. */\r
+ pxNewTimer->pcTimerName = pcTimerName;\r
+ pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;\r
+ pxNewTimer->pvTimerID = pvTimerID;\r
+ pxNewTimer->pxCallbackFunction = pxCallbackFunction;\r
+ vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );\r
+ if( uxAutoReload != pdFALSE )\r
+ {\r
+ pxNewTimer->ucStatus |= tmrSTATUS_IS_AUTORELOAD;\r
+ }\r
+ traceTIMER_CREATE( pxNewTimer );\r
+ }\r
}\r
/*-----------------------------------------------------------*/\r
\r
BaseType_t xReturn = pdFAIL;\r
DaemonTaskMessage_t xMessage;\r
\r
+ configASSERT( xTimer );\r
+\r
/* Send a message to the timer service task to perform a particular action\r
on a particular timer definition. */\r
if( xTimerQueue != NULL )\r
/* Send a command to the timer service task to start the xTimer timer. */\r
xMessage.xMessageID = xCommandID;\r
xMessage.u.xTimerParameters.xMessageValue = xOptionalValue;\r
- xMessage.u.xTimerParameters.pxTimer = ( Timer_t * ) xTimer;\r
+ xMessage.u.xTimerParameters.pxTimer = xTimer;\r
\r
if( xCommandID < tmrFIRST_FROM_ISR_COMMAND )\r
{\r
}\r
/*-----------------------------------------------------------*/\r
\r
-#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )\r
+TaskHandle_t xTimerGetTimerDaemonTaskHandle( void )\r
+{\r
+ /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been\r
+ started, then xTimerTaskHandle will be NULL. */\r
+ configASSERT( ( xTimerTaskHandle != NULL ) );\r
+ return xTimerTaskHandle;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+TickType_t xTimerGetPeriod( TimerHandle_t xTimer )\r
+{\r
+Timer_t *pxTimer = xTimer;\r
+\r
+ configASSERT( xTimer );\r
+ return pxTimer->xTimerPeriodInTicks;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload )\r
+{\r
+Timer_t * pxTimer = xTimer;\r
+\r
+ configASSERT( xTimer );\r
+ taskENTER_CRITICAL();\r
+ {\r
+ if( uxAutoReload != pdFALSE )\r
+ {\r
+ pxTimer->ucStatus |= tmrSTATUS_IS_AUTORELOAD;\r
+ }\r
+ else\r
+ {\r
+ pxTimer->ucStatus &= ~tmrSTATUS_IS_AUTORELOAD;\r
+ }\r
+ }\r
+ taskEXIT_CRITICAL();\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer )\r
+{\r
+Timer_t * pxTimer = xTimer;\r
+UBaseType_t uxReturn;\r
\r
- TaskHandle_t xTimerGetTimerDaemonTaskHandle( void )\r
+ configASSERT( xTimer );\r
+ taskENTER_CRITICAL();\r
{\r
- /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been\r
- started, then xTimerTaskHandle will be NULL. */\r
- configASSERT( ( xTimerTaskHandle != NULL ) );\r
- return xTimerTaskHandle;\r
+ if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) == 0 )\r
+ {\r
+ /* Not an auto-reload timer. */\r
+ uxReturn = ( UBaseType_t ) pdFALSE;\r
+ }\r
+ else\r
+ {\r
+ /* Is an auto-reload timer. */\r
+ uxReturn = ( UBaseType_t ) pdTRUE;\r
+ }\r
}\r
+ taskEXIT_CRITICAL();\r
\r
-#endif\r
+ return uxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer )\r
+{\r
+Timer_t * pxTimer = xTimer;\r
+TickType_t xReturn;\r
+\r
+ configASSERT( xTimer );\r
+ xReturn = listGET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ) );\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+const char * pcTimerGetName( TimerHandle_t xTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+{\r
+Timer_t *pxTimer = xTimer;\r
+\r
+ configASSERT( xTimer );\r
+ return pxTimer->pcTimerName;\r
+}\r
/*-----------------------------------------------------------*/\r
\r
static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow )\r
{\r
BaseType_t xResult;\r
-Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );\r
+Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); /*lint !e9087 !e9079 void * is used as this macro is used with tasks and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */\r
\r
/* Remove the timer from the list of active timers. A check has already\r
been performed to ensure the list is not empty. */\r
( void ) uxListRemove( &( pxTimer->xTimerListItem ) );\r
traceTIMER_EXPIRED( pxTimer );\r
\r
- /* If the timer is an auto reload timer then calculate the next\r
+ /* If the timer is an auto-reload timer then calculate the next\r
expiry time and re-insert the timer in the list of active timers. */\r
- if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )\r
+ if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 )\r
{\r
/* The timer is inserted into a list using a time relative to anything\r
other than the current time. It will therefore be inserted into the\r
correct list relative to the time this task thinks it is now. */\r
- if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) == pdTRUE )\r
+ if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) != pdFALSE )\r
{\r
/* The timer expired before it was added to the active timer\r
list. Reload it now. */\r
}\r
else\r
{\r
+ pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;\r
mtCOVERAGE_TEST_MARKER();\r
}\r
\r
}\r
/*-----------------------------------------------------------*/\r
\r
-static void prvTimerTask( void *pvParameters )\r
+static portTASK_FUNCTION( prvTimerTask, pvParameters )\r
{\r
TickType_t xNextExpireTime;\r
BaseType_t xListWasEmpty;\r
/* Just to avoid compiler warnings. */\r
( void ) pvParameters;\r
\r
+ #if( configUSE_DAEMON_TASK_STARTUP_HOOK == 1 )\r
+ {\r
+ extern void vApplicationDaemonTaskStartupHook( void );\r
+\r
+ /* Allow the application writer to execute some code in the context of\r
+ this task at the point the task starts executing. This is useful if the\r
+ application includes initialisation code that would benefit from\r
+ executing after the scheduler has been started. */\r
+ vApplicationDaemonTaskStartupHook();\r
+ }\r
+ #endif /* configUSE_DAEMON_TASK_STARTUP_HOOK */\r
+\r
for( ;; )\r
{\r
/* Query the timers list to see if it contains any timers, and if so,\r
}\r
/*-----------------------------------------------------------*/\r
\r
-static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, const BaseType_t xListWasEmpty )\r
+static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty )\r
{\r
TickType_t xTimeNow;\r
BaseType_t xTimerListsWereSwitched;\r
received - whichever comes first. The following line cannot\r
be reached unless xNextExpireTime > xTimeNow, except in the\r
case when the current timer list is empty. */\r
- vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ) );\r
+ if( xListWasEmpty != pdFALSE )\r
+ {\r
+ /* The current timer list is empty - is the overflow list\r
+ also empty? */\r
+ xListWasEmpty = listLIST_IS_EMPTY( pxOverflowTimerList );\r
+ }\r
+\r
+ vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ), xListWasEmpty );\r
\r
if( xTaskResumeAll() == pdFALSE )\r
{\r
- /* Yield to wait for either a command to arrive, or the block time\r
- to expire. If a command arrived between the critical section being\r
- exited and this yield then the yield will not cause the task\r
- to block. */\r
+ /* Yield to wait for either a command to arrive, or the\r
+ block time to expire. If a command arrived between the\r
+ critical section being exited and this yield then the yield\r
+ will not cause the task to block. */\r
portYIELD_WITHIN_API();\r
}\r
else\r
{\r
/* Has the expiry time elapsed between the command to start/reset a\r
timer was issued, and the time the command was processed? */\r
- if( ( xTimeNow - xCommandTime ) >= pxTimer->xTimerPeriodInTicks )\r
+ if( ( ( TickType_t ) ( xTimeNow - xCommandTime ) ) >= pxTimer->xTimerPeriodInTicks ) /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
{\r
/* The time between a command being issued and the command being\r
processed actually exceeds the timers period. */\r
{\r
/* Negative commands are pended function calls rather than timer\r
commands. */\r
- if( xMessage.xMessageID < 0 )\r
+ if( xMessage.xMessageID < ( BaseType_t ) 0 )\r
{\r
const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters );\r
\r
software timer. */\r
pxTimer = xMessage.u.xTimerParameters.pxTimer;\r
\r
- if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE )\r
+ if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) /*lint !e961. The cast is only redundant when NULL is passed into the macro. */\r
{\r
/* The timer is in a list, remove it. */\r
( void ) uxListRemove( &( pxTimer->xTimerListItem ) );\r
switch( xMessage.xMessageID )\r
{\r
case tmrCOMMAND_START :\r
- case tmrCOMMAND_START_FROM_ISR :\r
- case tmrCOMMAND_RESET :\r
- case tmrCOMMAND_RESET_FROM_ISR :\r
+ case tmrCOMMAND_START_FROM_ISR :\r
+ case tmrCOMMAND_RESET :\r
+ case tmrCOMMAND_RESET_FROM_ISR :\r
case tmrCOMMAND_START_DONT_TRACE :\r
/* Start or restart a timer. */\r
- if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) == pdTRUE )\r
+ pxTimer->ucStatus |= tmrSTATUS_IS_ACTIVE;\r
+ if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) != pdFALSE )\r
{\r
/* The timer expired before it was added to the active\r
timer list. Process it now. */\r
pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );\r
traceTIMER_EXPIRED( pxTimer );\r
\r
- if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )\r
+ if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 )\r
{\r
xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY );\r
configASSERT( xResult );\r
\r
case tmrCOMMAND_STOP :\r
case tmrCOMMAND_STOP_FROM_ISR :\r
- /* The timer has already been removed from the active list.\r
- There is nothing to do here. */\r
+ /* The timer has already been removed from the active list. */\r
+ pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;\r
break;\r
\r
case tmrCOMMAND_CHANGE_PERIOD :\r
case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR :\r
+ pxTimer->ucStatus |= tmrSTATUS_IS_ACTIVE;\r
pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue;\r
configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) );\r
\r
- /* The new period does not really have a reference, and can be\r
- longer or shorter than the old one. The command time is\r
- therefore set to the current time, and as the period cannot be\r
- zero the next expiry time can only be in the future, meaning\r
- (unlike for the xTimerStart() case above) there is no fail case\r
- that needs to be handled here. */\r
+ /* The new period does not really have a reference, and can\r
+ be longer or shorter than the old one. The command time is\r
+ therefore set to the current time, and as the period cannot\r
+ be zero the next expiry time can only be in the future,\r
+ meaning (unlike for the xTimerStart() case above) there is\r
+ no fail case that needs to be handled here. */\r
( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow );\r
break;\r
\r
case tmrCOMMAND_DELETE :\r
- /* The timer has already been removed from the active list,\r
- just free up the memory. */\r
- vPortFree( pxTimer );\r
+ #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
+ {\r
+ /* The timer has already been removed from the active list,\r
+ just free up the memory if the memory was dynamically\r
+ allocated. */\r
+ if( ( pxTimer->ucStatus & tmrSTATUS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) 0 )\r
+ {\r
+ vPortFree( pxTimer );\r
+ }\r
+ else\r
+ {\r
+ pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;\r
+ }\r
+ }\r
+ #else\r
+ {\r
+ /* If dynamic allocation is not enabled, the memory\r
+ could not have been dynamically allocated. So there is\r
+ no need to free the memory - just mark the timer as\r
+ "not active". */\r
+ pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;\r
+ }\r
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
break;\r
\r
default :\r
xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );\r
\r
/* Remove the timer from the list. */\r
- pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );\r
+ pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); /*lint !e9087 !e9079 void * is used as this macro is used with tasks and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */\r
( void ) uxListRemove( &( pxTimer->xTimerListItem ) );\r
traceTIMER_EXPIRED( pxTimer );\r
\r
have not yet been switched. */\r
pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );\r
\r
- if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )\r
+ if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 )\r
{\r
/* Calculate the reload value, and if the reload value results in\r
the timer going into the same timer list then it has already expired\r
vListInitialise( &xActiveTimerList2 );\r
pxCurrentTimerList = &xActiveTimerList1;\r
pxOverflowTimerList = &xActiveTimerList2;\r
- xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) );\r
- configASSERT( xTimerQueue );\r
+\r
+ #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
+ {\r
+ /* The timer queue is allocated statically in case\r
+ configSUPPORT_DYNAMIC_ALLOCATION is 0. */\r
+ static StaticQueue_t xStaticTimerQueue; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */\r
+ static uint8_t ucStaticTimerQueueStorage[ ( size_t ) configTIMER_QUEUE_LENGTH * sizeof( DaemonTaskMessage_t ) ]; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */\r
+\r
+ xTimerQueue = xQueueCreateStatic( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, ( UBaseType_t ) sizeof( DaemonTaskMessage_t ), &( ucStaticTimerQueueStorage[ 0 ] ), &xStaticTimerQueue );\r
+ }\r
+ #else\r
+ {\r
+ xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) );\r
+ }\r
+ #endif\r
\r
#if ( configQUEUE_REGISTRY_SIZE > 0 )\r
{\r
\r
BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer )\r
{\r
-BaseType_t xTimerIsInActiveList;\r
-Timer_t *pxTimer = ( Timer_t * ) xTimer;\r
+BaseType_t xReturn;\r
+Timer_t *pxTimer = xTimer;\r
+\r
+ configASSERT( xTimer );\r
\r
/* Is the timer in the list of active timers? */\r
taskENTER_CRITICAL();\r
{\r
- /* Checking to see if it is in the NULL list in effect checks to see if\r
- it is referenced from either the current or the overflow timer lists in\r
- one go, but the logic has to be reversed, hence the '!'. */\r
- xTimerIsInActiveList = !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) );\r
+ if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0 )\r
+ {\r
+ xReturn = pdFALSE;\r
+ }\r
+ else\r
+ {\r
+ xReturn = pdTRUE;\r
+ }\r
}\r
taskEXIT_CRITICAL();\r
\r
- return xTimerIsInActiveList;\r
+ return xReturn;\r
} /*lint !e818 Can't be pointer to const due to the typedef. */\r
/*-----------------------------------------------------------*/\r
\r
void *pvTimerGetTimerID( const TimerHandle_t xTimer )\r
{\r
-Timer_t * const pxTimer = ( Timer_t * ) xTimer;\r
+Timer_t * const pxTimer = xTimer;\r
+void *pvReturn;\r
+\r
+ configASSERT( xTimer );\r
+\r
+ taskENTER_CRITICAL();\r
+ {\r
+ pvReturn = pxTimer->pvTimerID;\r
+ }\r
+ taskEXIT_CRITICAL();\r
+\r
+ return pvReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID )\r
+{\r
+Timer_t * const pxTimer = xTimer;\r
\r
- return pxTimer->pvTimerID;\r
+ configASSERT( xTimer );\r
+\r
+ taskENTER_CRITICAL();\r
+ {\r
+ pxTimer->pvTimerID = pvNewID;\r
+ }\r
+ taskEXIT_CRITICAL();\r
}\r
/*-----------------------------------------------------------*/\r
\r
xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;\r
\r
xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken );\r
- \r
+\r
tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, xReturn );\r
\r
return xReturn;\r
DaemonTaskMessage_t xMessage;\r
BaseType_t xReturn;\r
\r
+ /* This function can only be called after a timer has been created or\r
+ after the scheduler has been started because, until then, the timer\r
+ queue does not exist. */\r
+ configASSERT( xTimerQueue );\r
+\r
/* Complete the message with the function parameters and post it to the\r
daemon task. */\r
xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK;\r
xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait );\r
\r
tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, xReturn );\r
- \r
+\r
return xReturn;\r
}\r
\r
#endif /* INCLUDE_xTimerPendFunctionCall */\r
/*-----------------------------------------------------------*/\r
\r
+#if ( configUSE_TRACE_FACILITY == 1 )\r
+\r
+ UBaseType_t uxTimerGetTimerNumber( TimerHandle_t xTimer )\r
+ {\r
+ return ( ( Timer_t * ) xTimer )->uxTimerNumber;\r
+ }\r
+\r
+#endif /* configUSE_TRACE_FACILITY */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( configUSE_TRACE_FACILITY == 1 )\r
+\r
+ void vTimerSetTimerNumber( TimerHandle_t xTimer, UBaseType_t uxTimerNumber )\r
+ {\r
+ ( ( Timer_t * ) xTimer )->uxTimerNumber = uxTimerNumber;\r
+ }\r
+\r
+#endif /* configUSE_TRACE_FACILITY */\r
+/*-----------------------------------------------------------*/\r
+\r
/* This entire source file will be skipped if the application is not configured\r
to include software timer functionality. If you want to include software timer\r
functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */\r