]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-IoT-Libraries/abstractions/platform/freertos/iot_clock_freertos.c
Correct an err in queue.c introduced when previously updating behaviour when queue...
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-IoT-Libraries / abstractions / platform / freertos / iot_clock_freertos.c
1 /*\r
2  * Amazon FreeRTOS Platform V1.0.0\r
3  * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://aws.amazon.com/freertos\r
23  * http://www.FreeRTOS.org\r
24  */\r
25 \r
26 /**\r
27  * @file iot_clock_freertos.c\r
28  * @brief Implementation of the functions in iot_clock.h for Amazon FreeRTOS systems.\r
29  */\r
30 \r
31 /* The config header is always included first. */\r
32 #include "iot_config.h"\r
33 \r
34 /* Standard includes. */\r
35 #include <stdio.h>\r
36 \r
37 /* Platform clock include. */\r
38 #include "platform/iot_platform_types_freertos.h"\r
39 #include "platform/iot_clock.h"\r
40 #include "task.h"\r
41 \r
42 /* Configure logs for the functions in this file. */\r
43 #ifdef IOT_LOG_LEVEL_PLATFORM\r
44     #define LIBRARY_LOG_LEVEL        IOT_LOG_LEVEL_PLATFORM\r
45 #else\r
46     #ifdef IOT_LOG_LEVEL_GLOBAL\r
47         #define LIBRARY_LOG_LEVEL    IOT_LOG_LEVEL_GLOBAL\r
48     #else\r
49         #define LIBRARY_LOG_LEVEL    IOT_LOG_NONE\r
50     #endif\r
51 #endif\r
52 \r
53 #define LIBRARY_LOG_NAME    ( "CLOCK" )\r
54 #include "iot_logging_setup.h"\r
55 \r
56 /*-----------------------------------------------------------*/\r
57 \r
58 /*\r
59  * Time conversion constants.\r
60  */\r
61 #define _MILLISECONDS_PER_SECOND    ( 1000 )                                          /**< @brief Milliseconds per second. */\r
62 #define _MILLISECONDS_PER_TICK      ( _MILLISECONDS_PER_SECOND / configTICK_RATE_HZ ) /**< Milliseconds per FreeRTOS tick. */\r
63 \r
64 /*-----------------------------------------------------------*/\r
65 \r
66 /*  Private Callback function for timer expiry, delegate work to a Task to free\r
67  *  up the timer task for managing other timers */\r
68 static void prvTimerCallback( TimerHandle_t xTimerHandle )\r
69 {\r
70     _IotSystemTimer_t * pxTimer = ( _IotSystemTimer_t * ) pvTimerGetTimerID( xTimerHandle );\r
71 \r
72     /* The value of the timer ID, set in timer_create, should not be NULL. */\r
73     configASSERT( pxTimer != NULL );\r
74 \r
75     /* Restart the timer if it is periodic. */\r
76     if( pxTimer->xTimerPeriod > 0 )\r
77     {\r
78         xTimerChangePeriod( xTimerHandle, pxTimer->xTimerPeriod, 0 );\r
79     }\r
80 \r
81     /* Call timer Callback from this task */\r
82     pxTimer->threadRoutine( ( void * ) pxTimer->pArgument );\r
83 }\r
84 \r
85 /*-----------------------------------------------------------*/\r
86 \r
87 bool IotClock_GetTimestring( char * pBuffer,\r
88                              size_t bufferSize,\r
89                              size_t * pTimestringLength )\r
90 {\r
91     uint64_t milliSeconds = IotClock_GetTimeMs();\r
92     int timestringLength = 0;\r
93 \r
94     configASSERT( pBuffer != NULL );\r
95     configASSERT( pTimestringLength != NULL );\r
96 \r
97     /* Convert the localTime struct to a string. */\r
98     timestringLength = snprintf( pBuffer, bufferSize, "%llu", milliSeconds );\r
99 \r
100     /* Check for error from no string */\r
101     if( timestringLength == 0 )\r
102     {\r
103         return false;\r
104     }\r
105 \r
106     /* Set the output parameter. */\r
107     *pTimestringLength = timestringLength;\r
108 \r
109     return true;\r
110 }\r
111 \r
112 /*-----------------------------------------------------------*/\r
113 \r
114 uint64_t IotClock_GetTimeMs( void )\r
115 {\r
116     TimeOut_t xCurrentTime = { 0 };\r
117 \r
118     /* This must be unsigned because the behavior of signed integer overflow is undefined. */\r
119     uint64_t ullTickCount = 0ULL;\r
120 \r
121     /* Get the current tick count and overflow count. vTaskSetTimeOutState()\r
122      * is used to get these values because they are both static in tasks.c. */\r
123     vTaskSetTimeOutState( &xCurrentTime );\r
124 \r
125     /* Adjust the tick count for the number of times a TickType_t has overflowed. */\r
126     ullTickCount = ( uint64_t ) ( xCurrentTime.xOverflowCount ) << ( sizeof( TickType_t ) * 8 );\r
127 \r
128     /* Add the current tick count. */\r
129     ullTickCount += xCurrentTime.xTimeOnEntering;\r
130 \r
131     /* Return the ticks converted to Milliseconds */\r
132     return ullTickCount * _MILLISECONDS_PER_TICK;\r
133 }\r
134 /*-----------------------------------------------------------*/\r
135 \r
136 void IotClock_SleepMs( uint32_t sleepTimeMs )\r
137 {\r
138     vTaskDelay( pdMS_TO_TICKS( sleepTimeMs ) );\r
139 }\r
140 \r
141 /*-----------------------------------------------------------*/\r
142 \r
143 bool IotClock_TimerCreate( IotTimer_t * pNewTimer,\r
144                            IotThreadRoutine_t expirationRoutine,\r
145                            void * pArgument )\r
146 {\r
147     _IotSystemTimer_t * pxTimer = ( _IotSystemTimer_t * ) pNewTimer;\r
148 \r
149     configASSERT( pNewTimer != NULL );\r
150     configASSERT( expirationRoutine != NULL );\r
151 \r
152     IotLogDebug( "Creating new timer %p.", pNewTimer );\r
153 \r
154     /* Set the timer expiration routine, argument and period */\r
155     pxTimer->threadRoutine = expirationRoutine;\r
156     pxTimer->pArgument = pArgument;\r
157     pxTimer->xTimerPeriod = 0;\r
158 \r
159     /* Create a new FreeRTOS timer. This call will not fail because the\r
160      * memory for it has already been allocated, so the output parameter is\r
161      * also set. */\r
162     pxTimer->timer = ( TimerHandle_t ) xTimerCreateStatic( "timer",                  /* Timer name. */\r
163                                                            portMAX_DELAY,            /* Initial timer period. Timers are created disarmed. */\r
164                                                            pdFALSE,                  /* Don't auto-reload timer. */\r
165                                                            ( void * ) pxTimer,       /* Timer id. */\r
166                                                            prvTimerCallback,         /* Timer expiration callback. */\r
167                                                            &pxTimer->xTimerBuffer ); /* Pre-allocated memory for timer. */\r
168 \r
169     return true;\r
170 }\r
171 \r
172 /*-----------------------------------------------------------*/\r
173 \r
174 void IotClock_TimerDestroy( IotTimer_t * pTimer )\r
175 {\r
176     _IotSystemTimer_t * pTimerInfo = ( _IotSystemTimer_t * ) pTimer;\r
177 \r
178     configASSERT( pTimerInfo != NULL );\r
179     configASSERT( pTimerInfo->timer != NULL );\r
180 \r
181     IotLogDebug( "Destroying timer %p.", pTimer );\r
182 \r
183     if( xTimerIsTimerActive( pTimerInfo->timer ) == pdTRUE )\r
184     {\r
185         /* Stop the FreeRTOS timer. Because the timer is statically allocated, no call\r
186          * to xTimerDelete is necessary. The timer is stopped so that it's not referenced\r
187          * anywhere. xTimerStop will not fail when it has unlimited block time. */\r
188         ( void ) xTimerStop( pTimerInfo->timer, portMAX_DELAY );\r
189 \r
190         /* Wait until the timer stop command is processed. */\r
191         while( xTimerIsTimerActive( pTimerInfo->timer ) == pdTRUE )\r
192         {\r
193             vTaskDelay( 1 );\r
194         }\r
195     }\r
196 }\r
197 \r
198 /*-----------------------------------------------------------*/\r
199 \r
200 bool IotClock_TimerArm( IotTimer_t * pTimer,\r
201                         uint32_t relativeTimeoutMs,\r
202                         uint32_t periodMs )\r
203 {\r
204     _IotSystemTimer_t * pTimerInfo = ( _IotSystemTimer_t * ) pTimer;\r
205 \r
206     configASSERT( pTimerInfo != NULL );\r
207 \r
208     TimerHandle_t xTimerHandle = pTimerInfo->timer;\r
209 \r
210     IotLogDebug( "Arming timer %p with timeout %llu and period %llu.",\r
211                  pTimer,\r
212                  relativeTimeoutMs,\r
213                  periodMs );\r
214 \r
215     /* Set the timer period in ticks */\r
216     pTimerInfo->xTimerPeriod = pdMS_TO_TICKS( periodMs );\r
217 \r
218     /* Set the timer to expire after relativeTimeoutMs, and restart it. */\r
219     ( void ) xTimerChangePeriod( xTimerHandle, pdMS_TO_TICKS( relativeTimeoutMs ), portMAX_DELAY );\r
220 \r
221     return true;\r
222 }\r
223 \r
224 /*-----------------------------------------------------------*/\r