Skip to content

Commit 7714616

Browse files
FRASTMfpistm
authored andcommitted
feat: support binary mode
Configure the alarm depending on the MIX mode In case the RTC is running in MIX mode (binary and calendar), the subsecond register is a 32-bit value (and not msec) The Subsecond parameter is expressed in millisecond in RTC_SetTime/GetTime RTC_StartAlarm/GetAlarm Signed-off-by: Francois Ramu <francois.ramu@st.com>
1 parent 5f53d03 commit 7714616

File tree

4 files changed

+90
-10
lines changed

4 files changed

+90
-10
lines changed

src/STM32RTC.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,21 @@ void STM32RTC::enableAlarm(Alarm_Match match, Alarm name)
220220
RTC_StopAlarm(::ALARM_A);
221221
}
222222
break;
223+
case MATCH_SUBSEC:
224+
/* force _alarmday to 0 to go to the right alarm config in MIX mode */
225+
#ifdef RTC_ALARM_B
226+
if (name == ALARM_B) {
227+
RTC_StartAlarm(::ALARM_B, 0, 0, 0, 0,
228+
_alarmBSubSeconds, (_alarmBPeriod == AM) ? HOUR_AM : HOUR_PM,
229+
static_cast<uint8_t>(31UL));
230+
} else
231+
#endif
232+
{
233+
RTC_StartAlarm(::ALARM_A, 0, 0, 0, 0,
234+
_alarmSubSeconds, (_alarmPeriod == AM) ? HOUR_AM : HOUR_PM,
235+
static_cast<uint8_t>(31UL));
236+
}
237+
break;
223238
case MATCH_YYMMDDHHMMSS://kept for compatibility
224239
case MATCH_MMDDHHMMSS: //kept for compatibility
225240
case MATCH_DHHMMSS:
@@ -615,7 +630,7 @@ uint8_t STM32RTC::getAlarmYear(void)
615630

616631
/**
617632
* @brief set RTC subseconds.
618-
* @param subseconds: 0-999
633+
* @param subseconds: 0-999 milliseconds
619634
* @retval none
620635
*/
621636
void STM32RTC::setSubSeconds(uint32_t subSeconds)
@@ -1250,6 +1265,7 @@ bool STM32RTC::isAlarmEnabled(Alarm name)
12501265
void STM32RTC::syncTime(void)
12511266
{
12521267
hourAM_PM_t p = HOUR_AM;
1268+
12531269
RTC_GetTime(&_hours, &_minutes, &_seconds, &_subSeconds, &p);
12541270
_hoursPeriod = (p == HOUR_AM) ? AM : PM;
12551271
}

src/STM32RTC.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class STM32RTC {
9393

9494
enum Alarm_Match : uint8_t {
9595
MATCH_OFF = OFF_MSK, // Never
96+
MATCH_SUBSEC = SUBSEC_MSK, // Every Subsecond
9697
MATCH_SS = SS_MSK, // Every Minute
9798
MATCH_MMSS = SS_MSK | MM_MSK, // Every Hour
9899
MATCH_HHMMSS = SS_MSK | MM_MSK | HH_MSK, // Every Day

src/rtc.c

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ static uint8_t HSEDiv = 0;
7373
static uint8_t predivSync_bits = 0xFF;
7474
static uint32_t predivAsync = (PREDIVA_MAX + 1);
7575
static uint32_t predivSync = (PREDIVS_MAX + 1);
76+
static uint32_t fqce_apre;
7677
#else
7778
/* Default, let HAL calculate the prescaler*/
7879
static uint32_t predivAsync = RTC_AUTO_1_SECOND;
@@ -335,6 +336,8 @@ static void RTC_computePrediv(uint32_t *asynch, uint32_t *synch)
335336
Error_Handler();
336337
}
337338
*synch = predivS;
339+
340+
fqce_apre = clkVal / (*asynch + 1);
338341
}
339342
#endif /* !STM32F1xx */
340343

@@ -597,14 +600,14 @@ bool RTC_IsConfigured(void)
597600
* @param hours: 0-12 or 0-23. Depends on the format used.
598601
* @param minutes: 0-59
599602
* @param seconds: 0-59
600-
* @param subSeconds: 0-999
603+
* @param subSeconds: 0-999 (not used)
601604
* @param period: select HOUR_AM or HOUR_PM period in case RTC is set in 12 hours mode. Else ignored.
602605
* @retval None
603606
*/
604607
void RTC_SetTime(uint8_t hours, uint8_t minutes, uint8_t seconds, uint32_t subSeconds, hourAM_PM_t period)
605608
{
606609
RTC_TimeTypeDef RTC_TimeStruct;
607-
UNUSED(subSeconds);
610+
UNUSED(subSeconds); /* not used (read-only register) */
608611
/* Ignore time AM PM configuration if in 24 hours format */
609612
if (initFormat == HOUR_FORMAT_24) {
610613
period = HOUR_AM;
@@ -670,7 +673,16 @@ void RTC_GetTime(uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint32_t *s
670673
}
671674
#if defined(RTC_SSR_SS)
672675
if (subSeconds != NULL) {
673-
*subSeconds = ((predivSync - RTC_TimeStruct.SubSeconds) * 1000) / (predivSync + 1);
676+
if (initMode == MODE_BINARY_MIX) {
677+
/* The subsecond is the free-running downcounter, to be converted in milliseconds */
678+
*subSeconds = (((UINT32_MAX - RTC_TimeStruct.SubSeconds + 1) & UINT32_MAX)
679+
* 1000) / fqce_apre; /* give one more to compensate the 3.9ms uncertainty */
680+
*subSeconds = *subSeconds % 1000; /* nb of milliseconds */
681+
/* predivAsync is 0x7F with LSE clock source */
682+
} else {
683+
/* the subsecond register value is converted in millisec */
684+
*subSeconds = ((predivSync - RTC_TimeStruct.SubSeconds) * 1000) / (predivSync + 1);
685+
}
674686
}
675687
#else
676688
UNUSED(subSeconds);
@@ -738,7 +750,7 @@ void RTC_GetDate(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *wday)
738750
* @param hours: 0-12 or 0-23 depends on the hours mode.
739751
* @param minutes: 0-59
740752
* @param seconds: 0-59
741-
* @param subSeconds: 0-999
753+
* @param subSeconds: 0-999 milliseconds
742754
* @param period: HOUR_AM or HOUR_PM if in 12 hours mode else ignored.
743755
* @param mask: configure alarm behavior using alarmMask_t combination.
744756
* See AN4579 Table 5 for possible values.
@@ -753,11 +765,12 @@ void RTC_StartAlarm(alarm_t name, uint8_t day, uint8_t hours, uint8_t minutes, u
753765
period = HOUR_AM;
754766
}
755767

768+
/* Use alarm A by default because it is common to all STM32 HAL */
769+
RTC_AlarmStructure.Alarm = name;
770+
756771
if ((((initFormat == HOUR_FORMAT_24) && IS_RTC_HOUR24(hours)) || IS_RTC_HOUR12(hours))
757772
&& IS_RTC_DATE(day) && IS_RTC_MINUTES(minutes) && IS_RTC_SECONDS(seconds)) {
758773
/* Set RTC_AlarmStructure with calculated values*/
759-
/* Use alarm A by default because it is common to all STM32 HAL */
760-
RTC_AlarmStructure.Alarm = name;
761774
RTC_AlarmStructure.AlarmTime.Seconds = seconds;
762775
RTC_AlarmStructure.AlarmTime.Minutes = minutes;
763776
RTC_AlarmStructure.AlarmTime.Hours = hours;
@@ -772,7 +785,12 @@ void RTC_StartAlarm(alarm_t name, uint8_t day, uint8_t hours, uint8_t minutes, u
772785
{
773786
RTC_AlarmStructure.AlarmSubSecondMask = predivSync_bits << RTC_ALRMASSR_MASKSS_Pos;
774787
}
775-
RTC_AlarmStructure.AlarmTime.SubSeconds = predivSync - (subSeconds * (predivSync + 1)) / 1000;
788+
if (initMode == MODE_BINARY_MIX) {
789+
/* the subsecond is the millisecond to be converted in a subsecond downcounter value */
790+
RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - ((subSeconds * fqce_apre) / 1000 + 1);
791+
} else {
792+
RTC_AlarmStructure.AlarmTime.SubSeconds = predivSync - (subSeconds * (predivSync + 1)) / 1000;
793+
}
776794
} else {
777795
RTC_AlarmStructure.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
778796
}
@@ -813,6 +831,41 @@ void RTC_StartAlarm(alarm_t name, uint8_t day, uint8_t hours, uint8_t minutes, u
813831
UNUSED(mask);
814832
#endif /* !STM32F1xx */
815833

834+
/* Set RTC_Alarm */
835+
HAL_RTC_SetAlarm_IT(&RtcHandle, &RTC_AlarmStructure, RTC_FORMAT_BIN);
836+
HAL_NVIC_SetPriority(RTC_Alarm_IRQn, RTC_IRQ_PRIO, RTC_IRQ_SUBPRIO);
837+
HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
838+
#if defined(RTC_ICSR_BIN)
839+
} else if (RtcHandle.Init.BinMode != RTC_BINARY_NONE) {
840+
/* We have an SubSecond alarm to set in RTC_BINARY_MIX or RTC_BINARY_ONLY mode */
841+
#else
842+
} else {
843+
#endif /* RTC_ICSR_BIN */
844+
#if defined(RTC_SSR_SS)
845+
{
846+
#if defined(RTC_ALRMASSR_SSCLR)
847+
RTC_AlarmStructure.BinaryAutoClr = RTC_ALARMSUBSECONDBIN_AUTOCLR_NO;
848+
#endif /* RTC_ALRMASSR_SSCLR */
849+
RTC_AlarmStructure.AlarmMask = RTC_ALARMMASK_ALL;
850+
851+
#ifdef RTC_ALARM_B
852+
if (name == ALARM_B)
853+
{
854+
/* Expecting RTC_ALARMSUBSECONDBINMASK_NONE for the subsecond mask on ALARM B */
855+
RTC_AlarmStructure.AlarmSubSecondMask = mask << RTC_ALRMBSSR_MASKSS_Pos;
856+
} else
857+
#endif
858+
{
859+
/* Expecting RTC_ALARMSUBSECONDBINMASK_NONE for the subsecond mask on ALARM A */
860+
RTC_AlarmStructure.AlarmSubSecondMask = mask << RTC_ALRMASSR_MASKSS_Pos;
861+
}
862+
/* The subsecond in ms is converted in ticks unit 1 tick is 1000 / fqce_apre */
863+
RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - (subSeconds * fqce_apre) / 1000;
864+
}
865+
866+
#else
867+
UNUSED(subSeconds);
868+
#endif /* RTC_SSR_SS */
816869
/* Set RTC_Alarm */
817870
HAL_RTC_SetAlarm_IT(&RtcHandle, &RTC_AlarmStructure, RTC_FORMAT_BIN);
818871
HAL_NVIC_SetPriority(RTC_Alarm_IRQn, RTC_IRQ_PRIO, RTC_IRQ_SUBPRIO);
@@ -903,7 +956,15 @@ void RTC_GetAlarm(alarm_t name, uint8_t *day, uint8_t *hours, uint8_t *minutes,
903956
}
904957
#if defined(RTC_SSR_SS)
905958
if (subSeconds != NULL) {
906-
*subSeconds = ((predivSync - RTC_AlarmStructure.AlarmTime.SubSeconds) * 1000) / (predivSync + 1);
959+
if (initMode == MODE_BINARY_MIX) {
960+
/*
961+
* The subsecond is the bit SS[14:0] of the ALARM SSR register (not ALARMxINR)
962+
* to be converted in milliseconds
963+
*/
964+
*subSeconds = (((0x7fff - RTC_AlarmStructure.AlarmTime.SubSeconds + 1) & 0x7fff) * 1000) / fqce_apre;
965+
} else {
966+
*subSeconds = ((predivSync - RTC_AlarmStructure.AlarmTime.SubSeconds) * 1000) / (predivSync + 1);
967+
}
907968
}
908969
#else
909970
UNUSED(subSeconds);

src/rtc.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ typedef enum {
7676
/* NOTE: STM32 RTC can't assign a month or a year to an alarm. Those enum
7777
are kept for compatibility but are ignored inside enableAlarm(). */
7878
M_MSK = 16,
79-
Y_MSK = 32
79+
Y_MSK = 32,
80+
SUBSEC_MSK = 48,
81+
ALL_MSK = 0xFF
8082
} alarmMask_t;
8183

8284
typedef enum {

0 commit comments

Comments
 (0)