Skip to content
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

fix calculation of subsecond conversion in MIX or BIN mode #102

Merged
merged 1 commit into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,10 @@ Three RTC functional modes are available:

Any API using the Subsecond parameter is expressed in milliseconds
whatever the RTC input clock. This parameter is [0..999] in MIX or BCD mode
and [0..0xFFFFFFFF] in BIN mode. In this configuration, time and date registers
are not used by the RTC.
and [0..0xFFFFFFFF] in BIN mode. In BIN only mode, time and date registers are not used
by the RTC. Thus the getEpoch function is only to be called to get the subsecond [0..0xFFFFFFFF]
(returned time_t is not valid). The setAlarmEpoch only uses the sub-second [0..0xFFFFFFFF]
(time_t value is useless).

Refer to the Arduino RTC documentation for the other functions
http://arduino.cc/en/Reference/RTC
Expand Down
11 changes: 7 additions & 4 deletions src/STM32RTC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1205,10 +1205,13 @@ void STM32RTC::setAlarmEpoch(time_t ts, Alarm_Match match, uint32_t subSeconds,
time_t t = ts;
struct tm *tmp = gmtime(&t);

setAlarmDay(tmp->tm_mday, name);
setAlarmHours(tmp->tm_hour, name);
setAlarmMinutes(tmp->tm_min, name);
setAlarmSeconds(tmp->tm_sec, name);
/* in BIN only mode, the time_t is not relevant, but only the subSeconds in ms */
if (_mode != MODE_BIN) {
setAlarmDay(tmp->tm_mday, name);
setAlarmHours(tmp->tm_hour, name);
setAlarmMinutes(tmp->tm_min, name);
setAlarmSeconds(tmp->tm_sec, name);
}
setAlarmSubSeconds(subSeconds, name);
enableAlarm(match, name);
}
Expand Down
34 changes: 20 additions & 14 deletions src/rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,10 @@ bool RTC_init(hourFormat_t format, binaryMode_t mode, sourceClock_t source, bool
#else
RTC_getPrediv(&(RtcHandle.Init.AsynchPrediv), &(RtcHandle.Init.SynchPrediv));
#endif
/*
* TODO: RTC is already initialized, but RTC BIN mode is changed
* force the update of the BIN register in the RTC_ICSR
*/
#if defined(RTC_BINARY_NONE)
RTC_BinaryConf(mode);
#endif /* RTC_BINARY_NONE */
Expand Down Expand Up @@ -615,6 +619,11 @@ bool RTC_init(hourFormat_t format, binaryMode_t mode, sourceClock_t source, bool
HAL_RTCEx_EnableBypassShadow(&RtcHandle);
#endif

/*
* NOTE: freezing the RTC during stop mode (lowPower deepSleep)
* could inhibit the alarm interrupt and prevent the system to wakeUp
* from stop mode even if the RTC alarm flag is set.
*/
return reinit;
}

Expand Down Expand Up @@ -733,19 +742,16 @@ void RTC_GetTime(uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint32_t *s
if (subSeconds != NULL) {
/*
* The subsecond is the free-running downcounter, to be converted in milliseconds.
* Give one more to compensate the fqce_apre uncertainty
*/
if (initMode == MODE_BINARY_MIX) {
if (initMode == MODE_BINARY_ONLY) {
*subSeconds = (((UINT32_MAX - RTC_TimeStruct.SubSeconds + 1) & UINT32_MAX)
* 1000) / fqce_apre;
*subSeconds = *subSeconds % 1000; /* nb of milliseconds [0..999] */
} else if (initMode == MODE_BINARY_ONLY) {
*subSeconds = (((UINT32_MAX - RTC_TimeStruct.SubSeconds + 1) & UINT32_MAX)
} else if (initMode == MODE_BINARY_MIX) {
*subSeconds = (((UINT32_MAX - RTC_TimeStruct.SubSeconds) & predivSync)
* 1000) / fqce_apre;
} else {
/* the subsecond register value is converted in millisec on 32bit */
*subSeconds = (((predivSync - RTC_TimeStruct.SubSeconds + 1) & predivSync)
* 1000) / fqce_apre;
*subSeconds = ((predivSync - RTC_TimeStruct.SubSeconds) * 1000) / (predivSync + 1);
}
}
#else
Expand Down Expand Up @@ -854,13 +860,13 @@ void RTC_StartAlarm(alarm_t name, uint8_t day, uint8_t hours, uint8_t minutes, u
}
/*
* The subsecond param is a nb of milliseconds to be converted in a subsecond
* downcounter value and to be comapred to the SubSecond register
* downcounter value and to be compared to the SubSecond register
*/
if ((initMode == MODE_BINARY_MIX) || (initMode == MODE_BINARY_NONE)) {
if ((initMode == MODE_BINARY_ONLY) || (initMode == MODE_BINARY_MIX)) {
/* the subsecond is the millisecond to be converted in a subsecond downcounter value */
RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - (subSeconds * (predivSync + 1)) / 1000 + 1;
RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - (subSeconds * (predivSync + 1)) / 1000;
} else {
RTC_AlarmStructure.AlarmTime.SubSeconds = predivSync - (subSeconds * (predivSync + 1)) / 1000 + 1;
RTC_AlarmStructure.AlarmTime.SubSeconds = predivSync - (subSeconds * (predivSync + 1)) / 1000;
}
} else {
RTC_AlarmStructure.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
Expand Down Expand Up @@ -922,7 +928,7 @@ void RTC_StartAlarm(alarm_t name, uint8_t day, uint8_t hours, uint8_t minutes, u
RTC_AlarmStructure.AlarmSubSecondMask = mask << RTC_ALRMASSR_MASKSS_Pos;
}
#if defined(RTC_ICSR_BIN)
if ((initMode == MODE_BINARY_MIX) || (initMode == MODE_BINARY_ONLY)) {
if ((initMode == MODE_BINARY_ONLY) || (initMode == MODE_BINARY_MIX)) {
/* We have an SubSecond alarm to set in RTC_BINARY_MIX or RTC_BINARY_ONLY mode */
/* The subsecond in ms is converted in ticks unit 1 tick is 1000 / fqce_apre */
RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - (subSeconds * (predivSync + 1)) / 1000;
Expand Down Expand Up @@ -1026,11 +1032,11 @@ void RTC_GetAlarm(alarm_t name, uint8_t *day, uint8_t *hours, uint8_t *minutes,
* The subsecond is the bit SS[14:0] of the ALARM SSR register (not ALARMxINR)
* to be converted in milliseconds
*/
if ((initMode == MODE_BINARY_MIX) || (initMode == MODE_BINARY_ONLY)) {
if ((initMode == MODE_BINARY_ONLY) || (initMode == MODE_BINARY_MIX)) {
/* read the ALARM SSR register on SS[14:0] bits --> 0x7FFF */
*subSeconds = (((0x7fff - RTC_AlarmStructure.AlarmTime.SubSeconds + 1) & 0x7fff) * 1000) / fqce_apre;
} else {
*subSeconds = (((predivSync - RTC_AlarmStructure.AlarmTime.SubSeconds + 1) & predivSync) * 1000) / (predivSync + 1);
*subSeconds = ((predivSync - RTC_AlarmStructure.AlarmTime.SubSeconds) * 1000) / (predivSync + 1);
}
}
#else
Expand Down