Skip to content

Commit b19ba1f

Browse files
committed
fix calculation of subsecond conversion in MIX or BIN mode
Depending on the RTC mode, the SSR subsecond register and AlarmSSR differ when converted to/from a value in milliseconds Correcting the formula in GetTime, GetAlarm/StartAlarm functions. Clarify the use of getEpoch and setAlarmEpoch in BIN only mode. Signed-off-by: Francois Ramu <francois.ramu@st.com>
1 parent d3f6526 commit b19ba1f

File tree

3 files changed

+40
-19
lines changed

3 files changed

+40
-19
lines changed

README.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,10 @@ Three RTC functional modes are available:
174174

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

180182
Refer to the Arduino RTC documentation for the other functions
181183
http://arduino.cc/en/Reference/RTC

src/STM32RTC.cpp

+7-4
Original file line numberDiff line numberDiff line change
@@ -1205,10 +1205,13 @@ void STM32RTC::setAlarmEpoch(time_t ts, Alarm_Match match, uint32_t subSeconds,
12051205
time_t t = ts;
12061206
struct tm *tmp = gmtime(&t);
12071207

1208-
setAlarmDay(tmp->tm_mday, name);
1209-
setAlarmHours(tmp->tm_hour, name);
1210-
setAlarmMinutes(tmp->tm_min, name);
1211-
setAlarmSeconds(tmp->tm_sec, name);
1208+
/* in BIN only mode, the time_t is not relevant, but only the subSeconds in ms */
1209+
if (_mode != MODE_BIN) {
1210+
setAlarmDay(tmp->tm_mday, name);
1211+
setAlarmHours(tmp->tm_hour, name);
1212+
setAlarmMinutes(tmp->tm_min, name);
1213+
setAlarmSeconds(tmp->tm_sec, name);
1214+
}
12121215
setAlarmSubSeconds(subSeconds, name);
12131216
enableAlarm(match, name);
12141217
}

src/rtc.c

+29-13
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,10 @@ bool RTC_init(hourFormat_t format, binaryMode_t mode, sourceClock_t source, bool
571571
#else
572572
RTC_getPrediv(&(RtcHandle.Init.AsynchPrediv), &(RtcHandle.Init.SynchPrediv));
573573
#endif
574+
/*
575+
* TODO: RTC is already initialized, but RTC BIN mode is changed
576+
* force the update of the BIN register in the RTC_ICSR
577+
*/
574578
#if defined(RTC_BINARY_NONE)
575579
RTC_BinaryConf(mode);
576580
#endif /* RTC_BINARY_NONE */
@@ -615,6 +619,11 @@ bool RTC_init(hourFormat_t format, binaryMode_t mode, sourceClock_t source, bool
615619
HAL_RTCEx_EnableBypassShadow(&RtcHandle);
616620
#endif
617621

622+
/*
623+
* NOTE: freezing the RTC during stop mode (lowPower deepSleep)
624+
* could inhibit the alarm interrupt and prevent the system to wakeUp
625+
* from stop mode even if the RTC alarm flag is set.
626+
*/
618627
return reinit;
619628
}
620629

@@ -733,19 +742,16 @@ void RTC_GetTime(uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint32_t *s
733742
if (subSeconds != NULL) {
734743
/*
735744
* The subsecond is the free-running downcounter, to be converted in milliseconds.
736-
* Give one more to compensate the fqce_apre uncertainty
737745
*/
738-
if (initMode == MODE_BINARY_MIX) {
746+
if (initMode == MODE_BINARY_ONLY) {
739747
*subSeconds = (((UINT32_MAX - RTC_TimeStruct.SubSeconds + 1) & UINT32_MAX)
740748
* 1000) / fqce_apre;
741-
*subSeconds = *subSeconds % 1000; /* nb of milliseconds [0..999] */
742-
} else if (initMode == MODE_BINARY_ONLY) {
743-
*subSeconds = (((UINT32_MAX - RTC_TimeStruct.SubSeconds + 1) & UINT32_MAX)
749+
} else if (initMode == MODE_BINARY_MIX) {
750+
*subSeconds = (((UINT32_MAX - RTC_TimeStruct.SubSeconds) & predivSync)
744751
* 1000) / fqce_apre;
745752
} else {
746753
/* the subsecond register value is converted in millisec on 32bit */
747-
*subSeconds = (((predivSync - RTC_TimeStruct.SubSeconds + 1) & predivSync)
748-
* 1000) / fqce_apre;
754+
*subSeconds = ((predivSync - RTC_TimeStruct.SubSeconds) * 1000) / (predivSync + 1);
749755
}
750756
}
751757
#else
@@ -856,11 +862,14 @@ void RTC_StartAlarm(alarm_t name, uint8_t day, uint8_t hours, uint8_t minutes, u
856862
* The subsecond param is a nb of milliseconds to be converted in a subsecond
857863
* downcounter value and to be comapred to the SubSecond register
858864
*/
859-
if ((initMode == MODE_BINARY_MIX) || (initMode == MODE_BINARY_NONE)) {
865+
if (initMode == MODE_BINARY_ONLY) {
860866
/* the subsecond is the millisecond to be converted in a subsecond downcounter value */
861-
RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - (subSeconds * (predivSync + 1)) / 1000 + 1;
867+
RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - (subSeconds * (predivSync + 1)) / 1000;
868+
} else if (initMode == MODE_BINARY_MIX) {
869+
/* the subsecond is the millisecond to be converted in a subsecond downcounter value */
870+
RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - (subSeconds * (predivSync + 1)) / 1000;
862871
} else {
863-
RTC_AlarmStructure.AlarmTime.SubSeconds = predivSync - (subSeconds * (predivSync + 1)) / 1000 + 1;
872+
RTC_AlarmStructure.AlarmTime.SubSeconds = predivSync - (subSeconds * (predivSync + 1)) / 1000;
864873
}
865874
} else {
866875
RTC_AlarmStructure.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
@@ -922,7 +931,11 @@ void RTC_StartAlarm(alarm_t name, uint8_t day, uint8_t hours, uint8_t minutes, u
922931
RTC_AlarmStructure.AlarmSubSecondMask = mask << RTC_ALRMASSR_MASKSS_Pos;
923932
}
924933
#if defined(RTC_ICSR_BIN)
925-
if ((initMode == MODE_BINARY_MIX) || (initMode == MODE_BINARY_ONLY)) {
934+
if (initMode == MODE_BINARY_ONLY) {
935+
/* We have an SubSecond alarm to set in RTC_BINARY_MIX or RTC_BINARY_ONLY mode */
936+
/* The subsecond in ms is converted in ticks unit 1 tick is 1000 / fqce_apre */
937+
RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - (subSeconds * (predivSync + 1)) / 1000;
938+
} else if (initMode == MODE_BINARY_MIX) {
926939
/* We have an SubSecond alarm to set in RTC_BINARY_MIX or RTC_BINARY_ONLY mode */
927940
/* The subsecond in ms is converted in ticks unit 1 tick is 1000 / fqce_apre */
928941
RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - (subSeconds * (predivSync + 1)) / 1000;
@@ -1026,11 +1039,14 @@ void RTC_GetAlarm(alarm_t name, uint8_t *day, uint8_t *hours, uint8_t *minutes,
10261039
* The subsecond is the bit SS[14:0] of the ALARM SSR register (not ALARMxINR)
10271040
* to be converted in milliseconds
10281041
*/
1029-
if ((initMode == MODE_BINARY_MIX) || (initMode == MODE_BINARY_ONLY)) {
1042+
if (initMode == MODE_BINARY_ONLY) {
1043+
/* read the ALARM SSR register on SS[14:0] bits --> 0x7FFF */
1044+
*subSeconds = (((0x7fff - RTC_AlarmStructure.AlarmTime.SubSeconds + 1) & 0x7fff) * 1000) / fqce_apre;
1045+
} else if (initMode == MODE_BINARY_MIX) {
10301046
/* read the ALARM SSR register on SS[14:0] bits --> 0x7FFF */
10311047
*subSeconds = (((0x7fff - RTC_AlarmStructure.AlarmTime.SubSeconds + 1) & 0x7fff) * 1000) / fqce_apre;
10321048
} else {
1033-
*subSeconds = (((predivSync - RTC_AlarmStructure.AlarmTime.SubSeconds + 1) & predivSync) * 1000) / (predivSync + 1);
1049+
*subSeconds = ((predivSync - RTC_AlarmStructure.AlarmTime.SubSeconds) * 1000) / (predivSync + 1);
10341050
}
10351051
}
10361052
#else

0 commit comments

Comments
 (0)