| /* |
| * FreeRTOS Platform V1.1.1 |
| * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a copy of |
| * this software and associated documentation files (the "Software"), to deal in |
| * the Software without restriction, including without limitation the rights to |
| * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of |
| * the Software, and to permit persons to whom the Software is furnished to do so, |
| * subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included in all |
| * copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
| * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
| * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
| * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| * |
| * http://aws.amazon.com/freertos |
| * http://www.FreeRTOS.org |
| */ |
| |
| /** |
| * @file iot_clock_freertos.c |
| * @brief Implementation of the functions in iot_clock.h for FreeRTOS systems. |
| */ |
| |
| /* The config header is always included first. */ |
| #include "iot_config.h" |
| |
| /* Standard includes. */ |
| #include <stdio.h> |
| |
| /* Platform clock include. */ |
| #include "platform/iot_platform_types_freertos.h" |
| #include "platform/iot_clock.h" |
| #include "task.h" |
| |
| /* Configure logs for the functions in this file. */ |
| #ifdef IOT_LOG_LEVEL_PLATFORM |
| #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_PLATFORM |
| #else |
| #ifdef IOT_LOG_LEVEL_GLOBAL |
| #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_GLOBAL |
| #else |
| #define LIBRARY_LOG_LEVEL IOT_LOG_NONE |
| #endif |
| #endif |
| |
| #define LIBRARY_LOG_NAME ( "CLOCK" ) |
| #include "iot_logging_setup.h" |
| |
| /*-----------------------------------------------------------*/ |
| |
| /* |
| * Time conversion constants. |
| */ |
| #define _MILLISECONDS_PER_SECOND ( 1000 ) /**< @brief Milliseconds per second. */ |
| #define _MILLISECONDS_PER_TICK ( _MILLISECONDS_PER_SECOND / configTICK_RATE_HZ ) /**< Milliseconds per FreeRTOS tick. */ |
| |
| /*-----------------------------------------------------------*/ |
| |
| /* Private Callback function for timer expiry, delegate work to a Task to free |
| * up the timer task for managing other timers */ |
| static void prvTimerCallback( TimerHandle_t xTimerHandle ) |
| { |
| _IotSystemTimer_t * pxTimer = ( _IotSystemTimer_t * ) pvTimerGetTimerID( xTimerHandle ); |
| |
| /* The value of the timer ID, set in timer_create, should not be NULL. */ |
| configASSERT( pxTimer != NULL ); |
| |
| /* Restart the timer if it is periodic. */ |
| if( pxTimer->xTimerPeriod > 0 ) |
| { |
| xTimerChangePeriod( xTimerHandle, pxTimer->xTimerPeriod, 0 ); |
| } |
| |
| /* Call timer Callback from this task */ |
| pxTimer->threadRoutine( ( void * ) pxTimer->pArgument ); |
| } |
| |
| /*-----------------------------------------------------------*/ |
| |
| bool IotClock_GetTimestring( char * pBuffer, |
| size_t bufferSize, |
| size_t * pTimestringLength ) |
| { |
| uint64_t milliSeconds = IotClock_GetTimeMs(); |
| int timestringLength = 0; |
| |
| configASSERT( pBuffer != NULL ); |
| configASSERT( pTimestringLength != NULL ); |
| |
| /* Convert the localTime struct to a string. */ |
| timestringLength = snprintf( pBuffer, bufferSize, "%llu", milliSeconds ); |
| |
| /* Check for error from no string */ |
| if( timestringLength == 0 ) |
| { |
| return false; |
| } |
| |
| /* Set the output parameter. */ |
| *pTimestringLength = timestringLength; |
| |
| return true; |
| } |
| |
| /*-----------------------------------------------------------*/ |
| |
| uint64_t IotClock_GetTimeMs( void ) |
| { |
| TimeOut_t xCurrentTime = { 0 }; |
| |
| /* This must be unsigned because the behavior of signed integer overflow is undefined. */ |
| uint64_t ullTickCount = 0ULL; |
| |
| /* Get the current tick count and overflow count. vTaskSetTimeOutState() |
| * is used to get these values because they are both static in tasks.c. */ |
| vTaskSetTimeOutState( &xCurrentTime ); |
| |
| /* Adjust the tick count for the number of times a TickType_t has overflowed. */ |
| ullTickCount = ( uint64_t ) ( xCurrentTime.xOverflowCount ) << ( sizeof( TickType_t ) * 8 ); |
| |
| /* Add the current tick count. */ |
| ullTickCount += xCurrentTime.xTimeOnEntering; |
| |
| /* Return the ticks converted to Milliseconds */ |
| return ullTickCount * _MILLISECONDS_PER_TICK; |
| } |
| /*-----------------------------------------------------------*/ |
| |
| void IotClock_SleepMs( uint32_t sleepTimeMs ) |
| { |
| vTaskDelay( pdMS_TO_TICKS( sleepTimeMs ) ); |
| } |
| |
| /*-----------------------------------------------------------*/ |
| |
| bool IotClock_TimerCreate( IotTimer_t * pNewTimer, |
| IotThreadRoutine_t expirationRoutine, |
| void * pArgument ) |
| { |
| _IotSystemTimer_t * pxTimer = ( _IotSystemTimer_t * ) pNewTimer; |
| |
| configASSERT( pNewTimer != NULL ); |
| configASSERT( expirationRoutine != NULL ); |
| |
| IotLogDebug( "Creating new timer %p.", pNewTimer ); |
| |
| /* Set the timer expiration routine, argument and period */ |
| pxTimer->threadRoutine = expirationRoutine; |
| pxTimer->pArgument = pArgument; |
| pxTimer->xTimerPeriod = 0; |
| |
| /* Create a new FreeRTOS timer. This call will not fail because the |
| * memory for it has already been allocated, so the output parameter is |
| * also set. */ |
| pxTimer->timer = ( TimerHandle_t ) xTimerCreateStatic( "timer", /* Timer name. */ |
| portMAX_DELAY, /* Initial timer period. Timers are created disarmed. */ |
| pdFALSE, /* Don't auto-reload timer. */ |
| ( void * ) pxTimer, /* Timer id. */ |
| prvTimerCallback, /* Timer expiration callback. */ |
| &pxTimer->xTimerBuffer ); /* Pre-allocated memory for timer. */ |
| |
| return true; |
| } |
| |
| /*-----------------------------------------------------------*/ |
| |
| void IotClock_TimerDestroy( IotTimer_t * pTimer ) |
| { |
| _IotSystemTimer_t * pTimerInfo = ( _IotSystemTimer_t * ) pTimer; |
| |
| configASSERT( pTimerInfo != NULL ); |
| configASSERT( pTimerInfo->timer != NULL ); |
| |
| IotLogDebug( "Destroying timer %p.", pTimer ); |
| |
| if( xTimerIsTimerActive( pTimerInfo->timer ) == pdTRUE ) |
| { |
| /* Stop the FreeRTOS timer. Because the timer is statically allocated, no call |
| * to xTimerDelete is necessary. The timer is stopped so that it's not referenced |
| * anywhere. xTimerStop will not fail when it has unlimited block time. */ |
| ( void ) xTimerStop( pTimerInfo->timer, portMAX_DELAY ); |
| |
| /* Wait until the timer stop command is processed. */ |
| while( xTimerIsTimerActive( pTimerInfo->timer ) == pdTRUE ) |
| { |
| vTaskDelay( 1 ); |
| } |
| } |
| } |
| |
| /*-----------------------------------------------------------*/ |
| |
| bool IotClock_TimerArm( IotTimer_t * pTimer, |
| uint32_t relativeTimeoutMs, |
| uint32_t periodMs ) |
| { |
| _IotSystemTimer_t * pTimerInfo = ( _IotSystemTimer_t * ) pTimer; |
| |
| configASSERT( pTimerInfo != NULL ); |
| |
| TimerHandle_t xTimerHandle = pTimerInfo->timer; |
| |
| IotLogDebug( "Arming timer %p with timeout %llu and period %llu.", |
| pTimer, |
| relativeTimeoutMs, |
| periodMs ); |
| |
| /* Set the timer period in ticks */ |
| pTimerInfo->xTimerPeriod = pdMS_TO_TICKS( periodMs ); |
| |
| /* Set the timer to expire after relativeTimeoutMs, and restart it. */ |
| ( void ) xTimerChangePeriod( xTimerHandle, pdMS_TO_TICKS( relativeTimeoutMs ), portMAX_DELAY ); |
| |
| return true; |
| } |
| |
| /*-----------------------------------------------------------*/ |