2 * Amazon FreeRTOS Platform V1.0.0
\r
3 * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\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
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\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
22 * http://aws.amazon.com/freertos
\r
23 * http://www.FreeRTOS.org
\r
27 * @file iot_clock_freertos.c
\r
28 * @brief Implementation of the functions in iot_clock.h for Amazon FreeRTOS systems.
\r
31 /* The config header is always included first. */
\r
32 #include "iot_config.h"
\r
34 /* Standard includes. */
\r
37 /* Platform clock include. */
\r
38 #include "platform/iot_platform_types_freertos.h"
\r
39 #include "platform/iot_clock.h"
\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
46 #ifdef IOT_LOG_LEVEL_GLOBAL
\r
47 #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_GLOBAL
\r
49 #define LIBRARY_LOG_LEVEL IOT_LOG_NONE
\r
53 #define LIBRARY_LOG_NAME ( "CLOCK" )
\r
54 #include "iot_logging_setup.h"
\r
56 /*-----------------------------------------------------------*/
\r
59 * Time conversion constants.
\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
64 /*-----------------------------------------------------------*/
\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
70 _IotSystemTimer_t * pxTimer = ( _IotSystemTimer_t * ) pvTimerGetTimerID( xTimerHandle );
\r
72 /* The value of the timer ID, set in timer_create, should not be NULL. */
\r
73 configASSERT( pxTimer != NULL );
\r
75 /* Restart the timer if it is periodic. */
\r
76 if( pxTimer->xTimerPeriod > 0 )
\r
78 xTimerChangePeriod( xTimerHandle, pxTimer->xTimerPeriod, 0 );
\r
81 /* Call timer Callback from this task */
\r
82 pxTimer->threadRoutine( ( void * ) pxTimer->pArgument );
\r
85 /*-----------------------------------------------------------*/
\r
87 bool IotClock_GetTimestring( char * pBuffer,
\r
89 size_t * pTimestringLength )
\r
91 uint64_t milliSeconds = IotClock_GetTimeMs();
\r
92 int timestringLength = 0;
\r
94 configASSERT( pBuffer != NULL );
\r
95 configASSERT( pTimestringLength != NULL );
\r
97 /* Convert the localTime struct to a string. */
\r
98 timestringLength = snprintf( pBuffer, bufferSize, "%llu", milliSeconds );
\r
100 /* Check for error from no string */
\r
101 if( timestringLength == 0 )
\r
106 /* Set the output parameter. */
\r
107 *pTimestringLength = timestringLength;
\r
112 /*-----------------------------------------------------------*/
\r
114 uint64_t IotClock_GetTimeMs( void )
\r
116 TimeOut_t xCurrentTime = { 0 };
\r
118 /* This must be unsigned because the behavior of signed integer overflow is undefined. */
\r
119 uint64_t ullTickCount = 0ULL;
\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
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
128 /* Add the current tick count. */
\r
129 ullTickCount += xCurrentTime.xTimeOnEntering;
\r
131 /* Return the ticks converted to Milliseconds */
\r
132 return ullTickCount * _MILLISECONDS_PER_TICK;
\r
134 /*-----------------------------------------------------------*/
\r
136 void IotClock_SleepMs( uint32_t sleepTimeMs )
\r
138 vTaskDelay( pdMS_TO_TICKS( sleepTimeMs ) );
\r
141 /*-----------------------------------------------------------*/
\r
143 bool IotClock_TimerCreate( IotTimer_t * pNewTimer,
\r
144 IotThreadRoutine_t expirationRoutine,
\r
147 _IotSystemTimer_t * pxTimer = ( _IotSystemTimer_t * ) pNewTimer;
\r
149 configASSERT( pNewTimer != NULL );
\r
150 configASSERT( expirationRoutine != NULL );
\r
152 IotLogDebug( "Creating new timer %p.", pNewTimer );
\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
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
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
172 /*-----------------------------------------------------------*/
\r
174 void IotClock_TimerDestroy( IotTimer_t * pTimer )
\r
176 _IotSystemTimer_t * pTimerInfo = ( _IotSystemTimer_t * ) pTimer;
\r
178 configASSERT( pTimerInfo != NULL );
\r
179 configASSERT( pTimerInfo->timer != NULL );
\r
181 IotLogDebug( "Destroying timer %p.", pTimer );
\r
183 if( xTimerIsTimerActive( pTimerInfo->timer ) == pdTRUE )
\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
190 /* Wait until the timer stop command is processed. */
\r
191 while( xTimerIsTimerActive( pTimerInfo->timer ) == pdTRUE )
\r
198 /*-----------------------------------------------------------*/
\r
200 bool IotClock_TimerArm( IotTimer_t * pTimer,
\r
201 uint32_t relativeTimeoutMs,
\r
202 uint32_t periodMs )
\r
204 _IotSystemTimer_t * pTimerInfo = ( _IotSystemTimer_t * ) pTimer;
\r
206 configASSERT( pTimerInfo != NULL );
\r
208 TimerHandle_t xTimerHandle = pTimerInfo->timer;
\r
210 IotLogDebug( "Arming timer %p with timeout %llu and period %llu.",
\r
215 /* Set the timer period in ticks */
\r
216 pTimerInfo->xTimerPeriod = pdMS_TO_TICKS( periodMs );
\r
218 /* Set the timer to expire after relativeTimeoutMs, and restart it. */
\r
219 ( void ) xTimerChangePeriod( xTimerHandle, pdMS_TO_TICKS( relativeTimeoutMs ), portMAX_DELAY );
\r
224 /*-----------------------------------------------------------*/
\r