2 * FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
\r
3 * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
4 * Authors include James Walmsley, Hein Tibosch and Richard Barry
\r
6 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
7 * this software and associated documentation files (the "Software"), to deal in
\r
8 * the Software without restriction, including without limitation the rights to
\r
9 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
10 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
11 * subject to the following conditions:
\r
13 * The above copyright notice and this permission notice shall be included in all
\r
14 * copies or substantial portions of the Software.
\r
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
18 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
19 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
23 * https://www.FreeRTOS.org
\r
31 #include "FreeRTOS.h"
\r
34 #include "ff_time.h"
\r
40 * @defgroup TIME Real-Time Clock Interface
\r
41 * @brief Allows FreeRTOS+FAT to time-stamp files.
\r
43 * Provides a means for receiving the time on any platform.
\r
46 #if( ffconfigTIME_SUPPORT != 0 ) /* This if-block spans the rest of the source file. */
\r
49 * @brief Populates an FF_SystemTime_t object with the current time from the system.
\r
51 * The developer must modify this function so that it is suitable for their platform.
\r
52 * The function must return with 0, and if the time is not available all elements of the
\r
53 * FF_SystemTime_t object must be zero'd, as in the examples provided.
\r
55 * @param pxTime Pointer to an FF_TIME object.
\r
57 * @return Always returns 0.
\r
60 int32_t FF_GetSystemTime( FF_SystemTime_t *pxTime )
\r
62 FF_TimeStruct_t xTimeStruct;
\r
64 /* Fetch the current time. */
\r
65 time_t secs = FreeRTOS_time( NULL );
\r
67 /* Fill the fields in 'xTimeStruct'. */
\r
68 FreeRTOS_gmtime_r( &secs, &xTimeStruct );
\r
70 pxTime->Hour = xTimeStruct.tm_hour;
\r
71 pxTime->Minute = xTimeStruct.tm_min;
\r
72 pxTime->Second = xTimeStruct.tm_sec;
\r
73 pxTime->Day = xTimeStruct.tm_mday;
\r
74 pxTime->Month = xTimeStruct.tm_mon + 1;
\r
75 pxTime->Year = xTimeStruct.tm_year + 1900;
\r
78 } /* FF_GetSystemTime() */
\r
79 /*-----------------------------------------------------------*/
\r
83 * Time conversion functions:
\r
85 * FF_TimeStruct_t *FreeRTOS_gmtime_r( const time_t *pxTime, FF_TimeStruct_t *pxTimeBuf )
\r
86 * time_t FreeRTOS_mktime(FF_TimeStruct_t *pxTimeBuf)
\r
89 #define GMTIME_FIRST_YEAR ( 1970 )
\r
90 #define TM_STRUCT_FIRST_YEAR ( 1900 )
\r
91 #define SECONDS_PER_MINUTE ( 60 )
\r
92 #define MINUTES_PER_HOUR ( 60 )
\r
93 #define HOURS_PER_DAY ( 24 )
\r
94 #define SECONDS_PER_HOUR ( MINUTES_PER_HOUR * SECONDS_PER_MINUTE )
\r
95 #define SECONDS_PER_DAY ( HOURS_PER_DAY * SECONDS_PER_HOUR )
\r
97 /* The first weekday in 'FF_TimeStruct_t' is Sunday. */
\r
98 #define WEEK_DAY_SUNDAY 0
\r
99 #define WEEK_DAY_MONNDAY 1
\r
100 #define WEEK_DAY_TUESDAY 2
\r
101 #define WEEK_DAY_WEDNESDAY 3
\r
102 #define WEEK_DAY_THURSDAY 4
\r
103 #define WEEK_DAY_FRIDAY 5
\r
104 #define WEEK_DAY_SATURDAY 6
\r
106 /* Make a bitmask with a '1' for each 31-day month. */
\r
107 #define _MM(month) ( 1u << ( month - 1 ) )
\r
108 #define MASK_LONG_MONTHS ( _MM(1) | _MM(3) | _MM(5) | _MM(7) | _MM(8) | _MM(10) | _MM(12) )
\r
110 #define DAYS_UNTIL_1970 ( ( 1970 * 365 ) + ( 1970 / 4 ) - ( 1970 / 100 ) + ( 1970 / 400 ) )
\r
111 #define DAYS_BEFORE_MARCH ( 59 )
\r
113 static portINLINE int iIsLeapyear( int iYear )
\r
117 if( ( iYear % 4 ) != 0 )
\r
119 /* Not a multiple of 4 years. */
\r
122 else if( ( iYear % 400 ) == 0 )
\r
124 /* Every 4 centuries there is a leap year */
\r
127 else if( ( iYear % 100 ) == 0 )
\r
129 /* Other centuries are not a leap year */
\r
134 /* Otherwise every fourth year. */
\r
141 static portINLINE unsigned long ulDaysPerYear( int iYear )
\r
145 if( iIsLeapyear( iYear ) )
\r
157 static int iDaysPerMonth( int iYear, int iMonth )
\r
161 /* Month is zero-based, 1 is February. */
\r
164 /* 30 or 31 days? */
\r
165 if( ( MASK_LONG_MONTHS & ( 1u << iMonth ) ) != 0 )
\r
174 else if( iIsLeapyear( iYear ) == pdFALSE )
\r
176 /* February, non leap year. */
\r
181 /* February, leap year. */
\r
187 FF_TimeStruct_t *FreeRTOS_gmtime_r( const time_t *pxTime, FF_TimeStruct_t *pxTimeBuf )
\r
189 time_t xTime = *pxTime;
\r
190 unsigned long ulDaySeconds, ulDayNumber;
\r
191 int iYear = GMTIME_FIRST_YEAR;
\r
194 /* Clear all fields, some might not get set here. */
\r
195 memset( ( void * )pxTimeBuf, '\0', sizeof( *pxTimeBuf ) );
\r
197 /* Seconds since last midnight. */
\r
198 ulDaySeconds = ( unsigned long ) ( xTime % SECONDS_PER_DAY ) ;
\r
200 /* Days since 1 Jan 1970. */
\r
201 ulDayNumber = ( unsigned long ) ( xTime / SECONDS_PER_DAY ) ;
\r
203 /* Today's HH:MM:SS */
\r
204 pxTimeBuf->tm_hour = ulDaySeconds / SECONDS_PER_HOUR;
\r
205 pxTimeBuf->tm_min = ( ulDaySeconds % SECONDS_PER_HOUR ) / 60;
\r
206 pxTimeBuf->tm_sec = ulDaySeconds % 60;
\r
208 /* Today's week day, knowing that 1-1-1970 was a THursday. */
\r
209 pxTimeBuf->tm_wday = ( ulDayNumber + WEEK_DAY_THURSDAY ) % 7;
\r
213 /* Keep subtracting 365 (or 366) days while possible. */
\r
214 unsigned long ulDays = ulDaysPerYear( iYear );
\r
215 if( ulDayNumber < ulDays )
\r
219 ulDayNumber -= ulDays;
\r
222 /* Subtract 1900. */
\r
223 pxTimeBuf->tm_year = iYear - TM_STRUCT_FIRST_YEAR;
\r
225 /* The day within this year. */
\r
226 pxTimeBuf->tm_yday = ulDayNumber;
\r
228 /* Month are counted as 0..11 */
\r
232 unsigned long ulDays = iDaysPerMonth( iYear, iMonth );
\r
233 /* Keep subtracting 30 (or 28, 29, or 31) days while possible. */
\r
234 if( ulDayNumber < ulDays )
\r
238 ulDayNumber -= ulDays;
\r
241 pxTimeBuf->tm_mon = iMonth;
\r
243 /* Month days are counted as 1..31 */
\r
244 pxTimeBuf->tm_mday = ulDayNumber + 1;
\r
249 time_t FreeRTOS_mktime( const FF_TimeStruct_t *pxTimeBuf )
\r
252 int iYear = 1900 + pxTimeBuf->tm_year; /* 20xx */
\r
253 /* Get month zero-based. */
\r
254 int iMonth = pxTimeBuf->tm_mon; /* 0..11 */
\r
258 ulDays = pxTimeBuf->tm_mday - 1; /* 1..31 */
\r
260 /* Make March the first month. */
\r
264 /* January or February: leap day has yet to come for this year. */
\r
269 /* Add the number of days past until this month. */
\r
270 ulDays += ( ( 306 * iMonth ) + 5 ) / 10;
\r
272 /* Add days past before this year: */
\r
274 + ( iYear * 365 ) /* Every normal year. */
\r
275 + ( iYear / 4 ) /* Plus a day for every leap year. */
\r
276 - ( iYear / 100 ) /* Minus the centuries. */
\r
277 + ( iYear / 400 ) /* Except every fourth century. */
\r
278 - ( DAYS_UNTIL_1970 ) /* Minus the days before 1-1-1970 */
\r
279 + ( DAYS_BEFORE_MARCH );/* Because 2 months were subtracted. */
\r
282 ( ulDays * SECONDS_PER_DAY ) +
\r
283 ( pxTimeBuf->tm_hour * SECONDS_PER_HOUR ) +
\r
284 ( pxTimeBuf->tm_min * SECONDS_PER_MINUTE ) +
\r
290 #endif /* ffconfigTIME_SUPPORT */
\r