]> git.sur5r.net Git - freertos/commitdiff
Start an optional timers module implementation.
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Tue, 8 Feb 2011 15:20:29 +0000 (15:20 +0000)
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Tue, 8 Feb 2011 15:20:29 +0000 (15:20 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1276 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

Source/timers.c [new file with mode: 0644]

diff --git a/Source/timers.c b/Source/timers.c
new file mode 100644 (file)
index 0000000..e28b78f
--- /dev/null
@@ -0,0 +1,325 @@
+/* Need a method of switching to an overflow list. _RB_*/\r
+\r
+/*\r
+    FreeRTOS V6.1.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+\r
+    ***************************************************************************\r
+    *                                                                         *\r
+    * If you are:                                                             *\r
+    *                                                                         *\r
+    *    + New to FreeRTOS,                                                   *\r
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *\r
+    *    + Looking for basic training,                                        *\r
+    *    + Wanting to improve your FreeRTOS skills and productivity           *\r
+    *                                                                         *\r
+    * then take a look at the FreeRTOS books - available as PDF or paperback  *\r
+    *                                                                         *\r
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *\r
+    *                  http://www.FreeRTOS.org/Documentation                  *\r
+    *                                                                         *\r
+    * A pdf reference manual is also available.  Both are usually delivered   *\r
+    * to your inbox within 20 minutes to two hours when purchased between 8am *\r
+    * and 8pm GMT (although please allow up to 24 hours in case of            *\r
+    * exceptional circumstances).  Thank you for your support!                *\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
+    ***NOTE*** The exception to the GPL is included to allow you to distribute\r
+    a combined work that includes FreeRTOS without being obliged to provide the\r
+    source code for proprietary components outside of the FreeRTOS kernel.\r
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT\r
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
+    more details. You should have received a copy of the GNU General Public\r
+    License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+    by writing to Richard Barry, contact details for whom are available on the\r
+    FreeRTOS WEB site.\r
+\r
+    1 tab == 4 spaces!\r
+\r
+    http://www.FreeRTOS.org - Documentation, latest information, license and\r
+    contact details.\r
+\r
+    http://www.SafeRTOS.com - A version that is certified for use in safety\r
+    critical systems.\r
+\r
+    http://www.OpenRTOS.com - Commercial support, development, porting,\r
+    licensing and training services.\r
+*/\r
+\r
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining\r
+all the API functions to use the MPU wrappers.  That should only be done when\r
+task.h is included from an application file. */\r
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
+\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "timers.h"\r
+\r
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
+\r
+/* IDs for commands that can be sent/received on the timer queue. */\r
+#define tmrSTART               0\r
+\r
+/* Misc definitions. */\r
+#define timerNO_DELAY  ( portTickType ) 0U\r
+\r
+/* The definition of the timers themselves. */\r
+typedef struct tmrTimerControl\r
+{\r
+       const signed char               *pcTimerName;           /*<< Text name.  This is not used by the kernel, it is included simply to make debugging easier. */\r
+       xListItem                               xTimerListItem;         /*<< Standard linked list item as used by all kernel features for event management. */\r
+       portTickType                    xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */\r
+       unsigned portBASE_TYPE  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
+       tmrTIMER_CALLBACK               pxCallbackFunction;     /*<< The function that will be called when the timer expires. */\r
+} xTIMER;\r
+\r
+/* The definition of messages that can be sent and received on the timer \r
+queue. */\r
+typedef struct tmrTimerQueueMessage\r
+{\r
+       portBASE_TYPE                   xMessageID;\r
+       portTickType                    xMessageValue;\r
+       xTIMER *                                pxTimer;\r
+} xTIMER_MESSAGE;\r
+\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 xActiveTimerList. */\r
+PRIVILEGED_DATA static xList xActiveTimerList;\r
+\r
+/* A queue that is used to send commands to the timer service task. */\r
+PRIVILEGED_DATA static xQueueHandle xTimerQueue = NULL;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Called when a timer is about to be modified.  If the timer is already in the\r
+ * list of active timers then it is removed prior to the modification.\r
+ */\r
+static void prvRemoveTimerFromActiveList( xTIMER *pxTimer ) PRIVILEGED_FUNCTION;\r
+\r
+static void prvCheckForValidListAndQueue( void ) PRIVILEGED_FUNCTION;\r
+\r
+/*\r
+ * The timer service task (daemon).\r
+ */\r
+static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION;\r
+\r
+\r
+/* Handlers for commands received on the timer queue. */\r
+static void prvTimerStart( xTIMER *pxTimer );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+portBASE_TYPE xTimerCreateTimerTask( void )\r
+{\r
+portBASE_TYPE xReturn = pdFAIL;\r
+\r
+       /* This function is called when the scheduler is started if \r
+       configUSE_TIMERS is set to 1. */\r
+       prvCheckForValidListAndQueue();\r
+\r
+       if( xTimerQueue != NULL )\r
+       {\r
+               xReturn = xTaskCreate( prvTimerTask, ( const signed char * ) "Timers", configMINIMAL_STACK_SIZE, NULL, configTIMER_TASK_PRIORITY, NULL );\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+xTimerHandle xTimerCreate( const signed char *pcTimerName, portTickType xTimerPeriodInTicks, unsigned portBASE_TYPE uxAutoReload, void *pvTimerID, tmrTIMER_CALLBACK pxCallbackFunction )\r
+{\r
+xTIMER *pxNewTimer;\r
+\r
+       /* Allocate the timer structure. */\r
+       pxNewTimer = ( xTIMER * ) pvPortMalloc( sizeof( xTIMER ) );\r
+       if( pxNewTimer != NULL )\r
+       {\r
+               prvCheckForValidListAndQueue();\r
+\r
+               /* Initialise the timer structure members. */\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
+\r
+       return ( xTimerHandle ) pxNewTimer;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+portBASE_TYPE xTimerStart( xTimerHandle xTimer, portTickType xBlockTime )\r
+{\r
+portBASE_TYPE xReturn = pdFAIL;\r
+xTIMER_MESSAGE xMessage;\r
+\r
+       if( xTimerQueue != NULL )\r
+       {\r
+               xMessage.xMessageID = tmrSTART;\r
+               xMessage.pxTimer = ( xTIMER * ) xTimer;\r
+\r
+               xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xBlockTime );\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void *pvTimerGetTimerID( xTimerHandle xTimer )\r
+{\r
+xTIMER *pxTimer = ( xTIMER * ) xTimer;\r
+\r
+       return pxTimer->pvTimerID;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvRemoveTimerFromActiveList( xTIMER *pxTimer )\r
+{\r
+       /* Is the timer already in the list of active timers? */\r
+       if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE )\r
+       {\r
+               /* The timer is in the list, remove it. */\r
+               vListRemove( &( pxTimer->xTimerListItem ) );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvTimerTask( void *pvParameters )\r
+{\r
+portTickType xNextWakeTime, xTimeNow;\r
+xTIMER *pxTimer;\r
+xTIMER_MESSAGE xMessage;\r
+\r
+       /* Just to avoid compiler warnings. */\r
+       ( void ) pvParameters;\r
+\r
+       for( ;; )\r
+       {\r
+               if( listLIST_IS_EMPTY( &xActiveTimerList ) == pdFALSE )\r
+               {\r
+                       xNextWakeTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( &xActiveTimerList );\r
+               }\r
+               else\r
+               {\r
+                       xNextWakeTime = portMAX_DELAY;\r
+               }\r
+\r
+               if( xNextWakeTime <= xTaskGetTickCount() )\r
+               {\r
+                       /* Remove the timer from the list.  This functionality relies on\r
+                       the list of active timers not being accessed from outside of this\r
+                       task. */\r
+                       pxTimer = listGET_OWNER_OF_HEAD_ENTRY( &xActiveTimerList );\r
+                       vListRemove( &( pxTimer->xTimerListItem ) );\r
+\r
+                       if( pxTimer->uxAutoReload == pdTRUE )\r
+                       {\r
+                               listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), ( xNextWakeTime + pxTimer->xTimerPeriodInTicks ) );\r
+                               vListInsert( &xActiveTimerList, &( pxTimer->xTimerListItem ) );\r
+                       }\r
+\r
+                       /* Call the timer callback. */\r
+                       pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer );\r
+               }\r
+               else\r
+               {\r
+                       /* Calculate the block time. */\r
+                       taskENTER_CRITICAL();\r
+                       {\r
+                               xTimeNow = xTaskGetTickCount();\r
+                               if( xTimeNow < xNextWakeTime )\r
+                               {\r
+                                       vQueueWaitForMessageRestricted( xTimerQueue, ( xNextWakeTime - xTimeNow ) );\r
+                               }\r
+                       }\r
+                       taskEXIT_CRITICAL();\r
+                       portYIELD_WITHIN_API();\r
+\r
+                       while( xQueueReceive( xTimerQueue, &xMessage, timerNO_DELAY ) != pdFAIL )\r
+                       {\r
+                               switch( xMessage.xMessageID )\r
+                               {\r
+                                       case tmrSTART   :       prvTimerStart( xMessage.pxTimer );\r
+                                                                               break;\r
+                                       default                 :       /* Don't expect to get here. */\r
+                                                                               break;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvCheckForValidListAndQueue( void )\r
+{\r
+       /* Check that the list from which active timers are referenced, and the\r
+       queue used to communicate with the timer service, have been \r
+       initialised. */\r
+       taskENTER_CRITICAL();\r
+       {\r
+               if( xTimerQueue == NULL )\r
+               {\r
+                       vListInitialise( &xActiveTimerList );\r
+                       xTimerQueue = xQueueCreate( configTIMER_QUEUE_LENGTH, sizeof( xTIMER_MESSAGE ) );\r
+               }\r
+       }\r
+       taskEXIT_CRITICAL();\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvTimerStart( xTIMER *pxTimer )\r
+{\r
+portTickType xTimeToWake;\r
+\r
+       if( pxTimer != NULL )\r
+       {\r
+               /* Is the timer already in the list of active timers? */\r
+               prvRemoveTimerFromActiveList( pxTimer );\r
+\r
+               xTimeToWake = xTaskGetTickCount() + pxTimer->xTimerPeriodInTicks;\r
+               listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xTimeToWake );\r
+               listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer );\r
+               vListInsert( &xActiveTimerList, &( pxTimer->xTimerListItem ) );\r
+       }\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer )\r
+{\r
+       return pdFALSE;\r
+}\r
+\r
+void vTimerStop( xTimerHandle xTimer )\r
+{\r
+}\r
+\r
+\r
+void vTimerChangePeriod( xTimerHandle xTimer )\r
+{\r
+}\r
+\r
+void vTimerDelete( xTimerHandle xTimer )\r
+{\r
+}\r
+/*-----------------------------------------------------------*/\r