Skip to content

Add support and tests for extended RTC #5363

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 12, 2017
Merged

Conversation

mprse
Copy link
Contributor

@mprse mprse commented Oct 23, 2017

Description

Add support for extended RTC.
Add tests for extended RTC.

Provide support to use whole 32-bit range (unsigned int) to hold time since UNIX epoch.
The supported time range is now from the 1st of January 1970 at 00:00:00 to the 7th of February 2106 at 06:28:15.
Add support for two types of RTC devices:

  • RTCs which handles all leap years in the mentioned year range correctly. Leap year is determined by checking if the year counter value is divisible by 400, 100, and 4.
  • RTCs which handles leap years correctly up to 2100. The RTC does a simple bit comparison to see if the two lowest order bits of the year counter are zero. In this case 2100 year will be considered incorrectly as a leap year, so the last valid point in time will be 28.02.2100 23:59:59 and next day will be 29.02.2100 (invalid). So after 28.02.2100 the day counter will be off by a day.

Status

READY

Migrations

YES

Modified API of _rtc_is_leap_year(), _rtc_mktime(), _rtc_localtime() functions.
Renamed _rtc_mktime() to _rtc_maketime().

Each function has additional parameter which informs if function is used for RTC which provides full leap year detection or not.

@theotherjimmy
Copy link
Contributor

@c1728p9 Could you review?

@bulislaw
Copy link
Member

@c1728p9 ping

@0xc0170 0xc0170 requested a review from c1728p9 October 26, 2017 19:41
@c1728p9
Copy link
Contributor

c1728p9 commented Oct 26, 2017

The functions functions _rtc_mktime and _rtc_localtime are intended to convert time reported in by RTC hardware in year, month, day, hour, minute and second to and from a 32-bit second value. Because of this, time ranges across the whole 32-bit range should be supported so these devices can comply to the RTC API.

The problem that needs to be addressed is that different devices calculate leap year differently. For example after year 2100 the LPC1768's counter will be off by a day, since it's hardware has a simpler leap year calculation. The RZ-A1H does not have this problem, as it factors in 100 and 400 year leap years. To account for these two types of behavior there should be two variants of each function, or an extra parameter of each function to choose this behavior at run time. A separate enhancement to the RTC HAL tests also needs to be made (in a separate PR), to test both 4 year leap year calculations and 100 year leap year handling on hardware.

For reference here is the RTC behavior of two separate devices:

LPC1768 User Manual:

27.6.4.1 Leap year calculation

The RTC does a simple bit comparison to see if the two lowest order bits of the year counter are zero. If true, then the RTC considers that year a leap year. The RTC considers all years evenly divisible by 4 as leap years. This algorithm is accurate from the year 1901 through the year 2099, but fails for the year 2100, which is not a leap year. The only effect of leap year on the RTC is to alter the length of the month of February for the month, day of month, and year counters.

RZ_A1H User Manual:

13.3.6 Day Counter (RDAYCNT)

A leap year is determined by checking if the year counter (RYRCNT) value is divisible by 400, 100, and 4.

@adbridge
Copy link
Contributor

@mprse could you please address @c1728p9 comments ?

@mprse
Copy link
Contributor Author

mprse commented Nov 1, 2017

@c1728p9 Thank you for detailed objectives. I will come back to this PR next week.

Because of this, time ranges across the whole 32-bit range should be supported so these devices can comply to the RTC API.

We can use entire 32-bit range, but then we will not have value which indicate error. Can we modify the _rtc_mktime() function to return Boolean value (true on successful conversion) and calculated value of seconds via additional parameter? It would be consistent with _rtc_localtime() function. e.g. bool _rtc_mktime(const struct tm* time, time_t * timestamp);

@mprse
Copy link
Contributor Author

mprse commented Nov 2, 2017

@c1728p9 Could you please confirm if I correctly understand the problem:

  1. For all RTC devices _rtc_mktime and _rtc_localtime shell support whole 32-bit range for count of elapsed seconds since the 1 of January 1970.
  2. We have two types of RTC devices:
    a) RTC devices which handle leap years properly for entire possible date range: from the 1st of January 1970 at 00:00:00 to the 7th of February 2106 at 06:28:15 (0 - 0xffff_ffff).
    b) RTC devices which incorrectly recognise 2100 year as a leap year. So after 28.02.2100 23:59:59 RTC time will be invalid. On these devices next point of time will be 29.02.2100 0:0:0 which is invalid date.

I'm not sure how these invalid dates should be handled. Lets take an example:
Last valid point of time for both RTC types:
28.02.2100 23:59:59 <----> 4107542399
After a second we will have the following case:
a) 01.03.2100 0:0:0 <----> 4107542400
b) 29.02.2100 0:0:0 <----> 4107542400

Expected functions behaviour:
a) _rtc_mktime (01.03.2100 0:0:0) ----> 4107542400
_rtc_localtime (4107542400) ----> 01.03.2100 0:0:0
_rtc_is_leap_year(2100) ----> false

b) _rtc_mktime (29.02.2100 0:0:0) ----> 4107542400
_rtc_localtime (4107542400) ----> 29.02.2100 0:0:0
_rtc_is_leap_year(2100) ----> true

Questions:

  1. Is that correct behaviour? Or maybe invalid dates should be fixed by the software?
  2. It looks like to achieve such results modification of _rtc_is_leap_year function is sufficient. You wrote that "there should be two variants of each function, or an extra parameter of each function". Why we can not use special symbol for this purpose and preprocesor directives? e.g:
bool _rtc_is_leap_year(int year) {
#ifdef DEVICE_RTC_100
    if(year == 200) {
        return false; // 2100 is not a leap year
    }
#endif
    return (year) % 4 ? false : true;
}

@c1728p9
Copy link
Contributor

c1728p9 commented Nov 2, 2017

Could you please confirm if I correctly understand the problem

@mprse your understanding of this is correct based on the points you made.

bool _rtc_mktime(const struct tm* time, time_t * timestamp);

Adding a bool to this works for me. @pan- are you ok with this?

Why we can not use special symbol for this purpose and preprocesor directives?

A preprocessor directive should only be used as a last resort as it complicates the code (in this case the same function behaves differently) and prevents testing all configurations in the same build.

@mprse
Copy link
Contributor Author

mprse commented Nov 6, 2017

@c1728p9 This PR has been updated to meet the requirements.

*/
typedef enum {
RTC_FULL_LEAP_YEAR_SUPPORT,
RTC_PARTIAL_LEAP_YEAR_SUPPORT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To remove some ambiguity it may be good to rename this to something like RTC_4_YEAR_LEAP_YEAR_SUPPORT

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed as suggested.


/* Macros which will be used to determine if we are within valid range. */
#define EDGE_TIMESTAMP_FULL_LEAP_YEAR_SUPPORT 3220095 // 7th of February 1970 at 06:28:15
#define EDGE_TIMESTAMP_PARTIAL_LEAP_YEAR_SUPPORT 3133695 // 6th of February 1970 at 06:28:15
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this date chosen? Also, why is it different for partial vs full?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a shortcut to check if calendar date provided to _rtc_mktime() function is within valid range. This is used to check upper limit. Function first only checks if the year range is valid. Then it calculates elapsed time since the beginning of the specified year. At this point we can check if provided date is within the range using these macros. If specified year is 2106 (last valid) and seconds since the beginning of the year are greater than edge timestamp, then we are out of range.
Different values are used for these two types of RTC devices. On devices which support full leap year detection last valid point of time is the 7th of February 2106 at 06:28:15 and on devices which have only 4 year leap year detection last valid date is 6th of February 2106 at 06:28:15 (at this point we are one day off). Both dates correspond to 0xffff_ffff number of seconds since the start of unix epoch.

@bulislaw
Copy link
Member

bulislaw commented Nov 8, 2017

@mprse ping

@pan-
Copy link
Member

pan- commented Nov 8, 2017

Adding a bool to this works for me. @pan- are you ok with this?

I would also rename the function to discriminate it from mktime which has a well defined semantic.

@mprse
Copy link
Contributor Author

mprse commented Nov 9, 2017

I would also rename the function to discriminate it from mktime which has a well defined semantic.

Changed mktime to maketime.

@mprse ping

All change requests are processed now.

@bulislaw
Copy link
Member

@mprse can you fix the conflict please.

@mprse
Copy link
Contributor Author

mprse commented Nov 13, 2017

@mprse can you fix the conflict please.

Conflict has been resolved.

@0xc0170
Copy link
Contributor

0xc0170 commented Nov 13, 2017

@mprse Can you please check travis , the failures are related to this patch

@mprse
Copy link
Contributor Author

mprse commented Nov 13, 2017

@mprse Can you please check travis , the failures are related to this patch.

This PR modifies API of _rtc_is_leap_year(), _rtc_mktime(), _rtc_localtime() functions and renames _rtc_mktime() to _rtc_maketime(). Travis reports errors since Vendor's RTC drivers are not updated.

@c1728p9 @0xc0170 @bulislaw
I'm not sure how we handle such cases. We expect that Vendors will update their RTC drivers? So maybe in such case we need a feature branch for this?
Or maybe I should adjust also all RTC drivers in additional commit?

@c1728p9
Copy link
Contributor

c1728p9 commented Nov 13, 2017

@mprse I would recommend updating the targets RTC drivers. There should be < 10 files that need updating. This global update of targets was done when mktime was initially added here:
f880e44

@mprse mprse changed the base branch from master to feature-hal-spec-rtc November 14, 2017 12:42
@mprse
Copy link
Contributor Author

mprse commented Nov 14, 2017

Changed base of this PR from ARMmbed:master to ARMmbed:feature-hal-spec-rtc.

@bulislaw
Copy link
Member

@mprse @0xc0170 What's the next step here? We need to merge it ASAP

@mprse
Copy link
Contributor Author

mprse commented Dec 4, 2017

Test : FAILURE
Build number : 469
Test logs :http://mbed-os-logs.s3-website-us-west-1.amazonaws.com/?prefix=logs/5363/469

Increased timeout for rtc_time_conv test.

@0xc0170
Copy link
Contributor

0xc0170 commented Dec 4, 2017

/morph build

@mbed-ci
Copy link

mbed-ci commented Dec 4, 2017

Build : SUCCESS

Build number : 649
Build artifacts/logs : http://mbed-os.s3-website-eu-west-1.amazonaws.com/?prefix=builds/5363/

Triggering tests

/morph test
/morph uvisor-test
/morph export-build

@mbed-ci
Copy link

mbed-ci commented Dec 4, 2017

Exporter Build : ABORTED

Build number : 288
Build artifacts/logs : http://mbed-os.s3-website-eu-west-1.amazonaws.com/?prefix=builds/exporter/5363/

@mbed-ci
Copy link

mbed-ci commented Dec 4, 2017

Test : FAILURE

Build number : 472
Test logs :http://mbed-os-logs.s3-website-us-west-1.amazonaws.com/?prefix=logs/5363/472

@mprse
Copy link
Contributor Author

mprse commented Dec 5, 2017

Increased timeout for rtc_time_conv test again.

@0xc0170
Copy link
Contributor

0xc0170 commented Dec 5, 2017

/morph build

@0xc0170
Copy link
Contributor

0xc0170 commented Dec 5, 2017

@mprse Please test locally if possible

@mbed-ci
Copy link

mbed-ci commented Dec 5, 2017

Build : SUCCESS

Build number : 652
Build artifacts/logs : http://mbed-os.s3-website-eu-west-1.amazonaws.com/?prefix=builds/5363/

Triggering tests

/morph test
/morph uvisor-test
/morph export-build

@mbed-ci
Copy link

mbed-ci commented Dec 5, 2017

@mbed-ci
Copy link

mbed-ci commented Dec 5, 2017

Test : SUCCESS

Build number : 476
Test logs :http://mbed-os-logs.s3-website-us-west-1.amazonaws.com/?prefix=logs/5363/476

@0xc0170 0xc0170 merged commit be52ba2 into ARMmbed:master Dec 12, 2017
TomoYamanaka added a commit to TomoYamanaka/mbed-os that referenced this pull request Dec 21, 2017
Although the extened RTC is supported by ARMmbed#5363 commit ("Add support and tests for extended RTC"), it seems that the changes was overlooked in RZ_A1H_api.c.
So I added the changes with reference to other rtc_api.c.
adbridge pushed a commit that referenced this pull request Dec 29, 2017
Although the extened RTC is supported by #5363 commit ("Add support and tests for extended RTC"), it seems that the changes was overlooked in RZ_A1H_api.c.
So I added the changes with reference to other rtc_api.c.
adbridge pushed a commit that referenced this pull request Jan 2, 2018
Although the extened RTC is supported by #5363 commit ("Add support and tests for extended RTC"), it seems that the changes was overlooked in RZ_A1H_api.c.
So I added the changes with reference to other rtc_api.c.
@0xc0170
Copy link
Contributor

0xc0170 commented Jan 2, 2018

@mprse We should review this As a result, even though it was tagged for 5.8, this is causing some new target dependencies that we should avoid.

I am thinking if this can be made backward compatible (it is internal API but affects targets) - having the functionality as it was, and the new one with suffix _extended in this case, . This would allow us to use old API for current patch releases, and would port it over to the new one for 5.8. Or just revert this changeset (simpler approach?), have feature branch and get this in right for 5.8 (5.7 would be as it was, and 5.8 would get the extended support in).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants