Skip to content

Commit 04f5706

Browse files
authored
Merge pull request #57 from FRASTM/seconds_int
implement a One-Second interrupt on stm32 MCUs
2 parents d65b81a + 4be30fe commit 04f5706

File tree

6 files changed

+285
-2
lines changed

6 files changed

+285
-2
lines changed

README.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,20 @@ _Library version management_
100100
#endif
101101
```
102102

103+
### Since STM32RTC version higher than 1.1.1
104+
105+
_One-Second interrupt_
106+
107+
STM32 RTC includes a one-second interrupt for generating a periodic interrupt signal.
108+
- This feature is native on the stm32F1xx and mapped on the existing WakeUp interrupt on other stm32 mcus.
109+
- It is not available on some stm32F0 devices.
110+
111+
* **new API:**
112+
* **`void attachSecondsInterrupt(voidFuncPtr callback)`**
113+
* **`void detachSecondsInterrupt(void)`**
114+
115+
116+
103117
### Since STM32 Core version > 1.5.0
104118
_Reset time management_
105119

@@ -118,10 +132,10 @@ To know if a time has already been set use:
118132
}
119133
```
120134
121-
Refer to the Arduino RTC documentation for the other functions
135+
Refer to the Arduino RTC documentation for the other functions
122136
http://arduino.cc/en/Reference/RTC
123137
124138
## Source
125139
126-
Source files available at:
140+
Source files available at:
127141
https://github.com/stm32duino/STM32RTC

examples/RTC_Seconds/RTC_Seconds.ino

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
RTC_Seconds
3+
4+
This sketch allows to test STM32RTC Seconds IRQ.
5+
6+
Creation 25 nov 2021
7+
by FRASTM for STMicroelectronics
8+
9+
This example code is in the public domain.
10+
11+
Note that this sketch is valid for STM32F1xx or stm32 MCU with WakeUp interrupt
12+
(WUTE flag present in the RTC CR register)
13+
14+
https://github.com/stm32duino/STM32RTC
15+
16+
*/
17+
18+
#include <STM32RTC.h>
19+
20+
#ifndef ONESECOND_IRQn
21+
#error "RTC has no feature for One-Second interrupt"
22+
#endif
23+
24+
/* use led to display seconds */
25+
#if defined(LED_BUILTIN)
26+
#define pin LED_BUILTIN
27+
#endif
28+
29+
/* Get the rtc object */
30+
STM32RTC& rtc = STM32RTC::getInstance();
31+
32+
/* Change these values to set the current initial time
33+
34+
format: date: "Dec 31 2017" and time: "23:59:56"
35+
by default use built date and time
36+
*/
37+
/* Change these values to set the current initial time */
38+
const byte seconds = 0;
39+
const byte minutes = 5;
40+
const byte hours = 11;
41+
42+
/* Change these values to set the current initial date */
43+
/* Monday 25 Nov. 2021 */
44+
const byte weekDay = 4;
45+
const byte day = 25;
46+
const byte month = 11;
47+
const byte year = 21;
48+
49+
bool toggling = false; // changed each second by the CallBack function
50+
51+
static STM32RTC::Hour_Format hourFormat = STM32RTC::HOUR_24;
52+
static STM32RTC::AM_PM period = STM32RTC::AM;
53+
54+
void setup()
55+
{
56+
Serial.begin(115200);
57+
while (!Serial) {}
58+
59+
#if defined(LED_BUILTIN)
60+
// configure pin in output mode
61+
pinMode(pin, OUTPUT);
62+
digitalWrite(pin, HIGH);
63+
#endif /* LED_BUILTIN */
64+
65+
Serial.print("RTC Init ");
66+
67+
// Select RTC clock source: LSI_CLOCK, LSE_CLOCK or HSE_CLOCK.
68+
// By default the LSI is selected as source. Use LSE for better accuracy if available
69+
// rtc.setClockSource(STM32RTC::LSE_CLOCK);
70+
71+
// initialize RTC 24H format
72+
rtc.begin(hourFormat);
73+
74+
// Set the time
75+
rtc.setHours(hours, period);
76+
rtc.setMinutes(minutes);
77+
rtc.setSeconds(seconds);
78+
79+
// Set the date
80+
rtc.setWeekDay(weekDay);
81+
rtc.setDay(day);
82+
rtc.setMonth(month);
83+
rtc.setYear(year);
84+
85+
Serial.println("with seconds Alarm");
86+
rtc.attachSecondsInterrupt(rtc_SecondsCB);
87+
}
88+
89+
void loop()
90+
{
91+
uint8_t sec = 0;
92+
uint8_t mn = 0;
93+
uint8_t hrs = 0;
94+
uint32_t subs = 0;
95+
rtc.getTime(&hrs, &mn, &sec, &subs);
96+
97+
if (toggling) {
98+
Serial.printf("%02d:%02d:%02d\n", hrs, mn, sec);
99+
} else {
100+
Serial.printf("%02d %02d %02d\n", hrs, mn, sec);
101+
}
102+
#if defined(LED_BUILTIN)
103+
digitalWrite(pin, toggling);
104+
#endif /* LED_BUILTIN */
105+
delay(1000);
106+
}
107+
108+
/* callback function on each second interrupt */
109+
void rtc_SecondsCB(void *data)
110+
{
111+
UNUSED(data);
112+
toggling = !toggling;
113+
}

src/STM32RTC.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,27 @@ void STM32RTC::detachInterrupt(void)
249249
detachAlarmCallback();
250250
}
251251

252+
#ifdef ONESECOND_IRQn
253+
/**
254+
* @brief attach a callback to the RTC Seconds interrupt.
255+
* @param callback: pointer to the callback
256+
* @retval None
257+
*/
258+
void STM32RTC::attachSecondsInterrupt(voidFuncPtr callback)
259+
{
260+
attachSecondsIrqCallback(callback);
261+
}
262+
263+
/**
264+
* @brief detach the RTC Seconds callback.
265+
* @retval None
266+
*/
267+
void STM32RTC::detachSecondsInterrupt(void)
268+
{
269+
detachSecondsIrqCallback();
270+
}
271+
272+
#endif /* ONESECOND_IRQn */
252273
// Kept for compatibility. Use STM32LowPower library.
253274
void STM32RTC::standbyMode(void)
254275
{

src/STM32RTC.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@ class STM32RTC {
125125
void attachInterrupt(voidFuncPtr callback, void *data = nullptr);
126126
void detachInterrupt(void);
127127

128+
#ifdef ONESECOND_IRQn
129+
// Other mcu than stm32F1 will use the WakeUp feature to interrupt each second.
130+
void attachSecondsInterrupt(voidFuncPtr callback);
131+
void detachSecondsInterrupt(void);
132+
133+
#endif /* ONESECOND_IRQn */
128134
// Kept for compatibility: use STM32LowPower library.
129135
void standbyMode();
130136

src/rtc.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ extern "C" {
5858
static RTC_HandleTypeDef RtcHandle = {0};
5959
static voidCallbackPtr RTCUserCallback = NULL;
6060
static void *callbackUserData = NULL;
61+
static voidCallbackPtr RTCSecondsIrqCallback = NULL;
6162

6263
static sourceClock_t clkSrc = LSI_CLOCK;
6364
static uint8_t HSEDiv = 0;
@@ -388,6 +389,7 @@ void RTC_DeInit(void)
388389
HAL_RTC_DeInit(&RtcHandle);
389390
RTCUserCallback = NULL;
390391
callbackUserData = NULL;
392+
RTCSecondsIrqCallback = NULL;
391393
}
392394

393395
/**
@@ -731,6 +733,107 @@ void RTC_Alarm_IRQHandler(void)
731733
HAL_RTC_AlarmIRQHandler(&RtcHandle);
732734
}
733735

736+
#ifdef ONESECOND_IRQn
737+
/**
738+
* @brief Attach Seconds interrupt callback.
739+
* @note stm32F1 has a second interrupt capability
740+
* other MCUs map this on their WakeUp feature
741+
* @param func: pointer to the callback
742+
* @retval None
743+
*/
744+
void attachSecondsIrqCallback(voidCallbackPtr func)
745+
{
746+
#if defined(STM32F1xx)
747+
/* callback called on Seconds interrupt */
748+
RTCSecondsIrqCallback = func;
749+
750+
HAL_RTCEx_SetSecond_IT(&RtcHandle);
751+
__HAL_RTC_SECOND_CLEAR_FLAG(&RtcHandle, RTC_FLAG_SEC);
752+
#else
753+
/* callback called on wakeUp interrupt for One-Second purpose*/
754+
RTCSecondsIrqCallback = func;
755+
756+
/* for MCUs using the wakeup feature : irq each second */
757+
#if defined(RTC_WUTR_WUTOCLR)
758+
HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, 0, RTC_WAKEUPCLOCK_CK_SPRE_16BITS, 0);
759+
#else
760+
HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, 0, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);
761+
#endif /* RTC_WUTR_WUTOCLR */
762+
763+
#endif /* STM32F1xx */
764+
/* enable the IRQ that will trig the one-second interrupt */
765+
HAL_NVIC_EnableIRQ(ONESECOND_IRQn);
766+
}
767+
768+
/**
769+
* @brief Detach Seconds interrupt callback.
770+
* @param None
771+
* @retval None
772+
*/
773+
void detachSecondsIrqCallback(void)
774+
{
775+
#if defined(STM32F1xx)
776+
HAL_RTCEx_DeactivateSecond(&RtcHandle);
777+
#else
778+
/* for MCUs using the wakeup feature : do not deactivate the WakeUp
779+
as it might be used for another reason than the One-Second purpose */
780+
// HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle);
781+
#endif /* STM32F1xx */
782+
RTCSecondsIrqCallback = NULL;
783+
}
784+
785+
#if defined(STM32F1xx)
786+
/**
787+
* @brief Seconds interrupt callback.
788+
* @param hrtc RTC handle
789+
* @retval None
790+
*/
791+
void HAL_RTCEx_RTCEventCallback(RTC_HandleTypeDef *hrtc)
792+
{
793+
UNUSED(hrtc);
794+
795+
if (RTCSecondsIrqCallback != NULL) {
796+
RTCSecondsIrqCallback(NULL);
797+
}
798+
}
799+
800+
/**
801+
* @brief This function handles RTC Seconds interrupt request.
802+
* @param None
803+
* @retval None
804+
*/
805+
void RTC_IRQHandler(void)
806+
{
807+
HAL_RTCEx_RTCIRQHandler(&RtcHandle);
808+
}
809+
810+
#else
811+
/**
812+
* @brief WakeUp event mapping the Seconds interrupt callback.
813+
* @param hrtc RTC handle
814+
* @retval None
815+
*/
816+
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
817+
{
818+
UNUSED(hrtc);
819+
820+
if (RTCSecondsIrqCallback != NULL) {
821+
RTCSecondsIrqCallback(NULL);
822+
}
823+
}
824+
825+
/**
826+
* @brief This function handles RTC Seconds through wakeup interrupt request.
827+
* @param None
828+
* @retval None
829+
*/
830+
void RTC_WKUP_IRQHandler(void)
831+
{
832+
HAL_RTCEx_WakeUpTimerIRQHandler(&RtcHandle);
833+
}
834+
#endif /* STM32F1xx */
835+
#endif /* ONESECOND_IRQn */
836+
734837
#ifdef __cplusplus
735838
}
736839
#endif

src/rtc.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,28 @@ typedef void(*voidCallbackPtr)(void *);
109109
#define RTC_Alarm_IRQHandler RTC_TAMP_IRQHandler
110110
#endif
111111

112+
/* mapping the IRQn for the one-second interrupt depending on the soc */
113+
#if defined(STM32F1xx) || (defined(STM32F0xx) && defined(RTC_CR_WUTE)) || \
114+
defined(STM32L0xx) || defined(STM32L5xx) || defined(STM32U5xx) || \
115+
defined(STM32WLE4xx)
116+
// specific WakeUp interrupt
117+
#define ONESECOND_IRQn RTC_IRQn
118+
#elif defined(STM32MP1xx)
119+
// global RTC interrupt
120+
#define ONESECOND_IRQn RTC_WKUP_ALARM_IRQn
121+
#elif defined(STM32G0xx)
122+
// global RTC/TAMP interrupt
123+
#define ONESECOND_IRQn RTC_TAMP_IRQn
124+
#elif defined(STM32WL54xx)|| defined(STM32WL55xx)
125+
// global RTC/LSS interrupt
126+
#define ONESECOND_IRQn RTC_LSECSS_IRQn
127+
#elif defined(RTC_CR_WUTE)
128+
// specific WakeUp interrupt (including M4 cpu of the STM32WLE5xx)
129+
#define ONESECOND_IRQn RTC_WKUP_IRQn
130+
#else
131+
// no One-Second IRQ available for the series
132+
#endif /* STM32F1xx || etc */
133+
112134
#if defined(STM32F1xx) && !defined(IS_RTC_WEEKDAY)
113135
/* Compensate missing HAL definition */
114136
#define IS_RTC_WEEKDAY(WEEKDAY) (((WEEKDAY) == RTC_WEEKDAY_MONDAY) || \
@@ -161,6 +183,10 @@ void RTC_StopAlarm(void);
161183
void RTC_GetAlarm(uint8_t *day, uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint32_t *subSeconds, hourAM_PM_t *period, uint8_t *mask);
162184
void attachAlarmCallback(voidCallbackPtr func, void *data);
163185
void detachAlarmCallback(void);
186+
#ifdef ONESECOND_IRQn
187+
void attachSecondsIrqCallback(voidCallbackPtr func);
188+
void detachSecondsIrqCallback(void);
189+
#endif /* ONESECOND_IRQn */
164190

165191
#ifdef __cplusplus
166192
}

0 commit comments

Comments
 (0)