From f7279c84bbab92f5f2322b996555d6402c028b53 Mon Sep 17 00:00:00 2001 From: Juan Carrano Date: Tue, 10 Sep 2019 11:41:28 +0200 Subject: [PATCH] cpu/sam0_common: rtt: correcly clear flags. The INTFLAGS register is cleared by writing a 1 to the corresponding interrupt flag bit. From the samr21's manual: > Writing a zero to this bit has no effect. > Writing a one to this bit clears the Compare 0 interrupt flag. This is a common pattern in flag registers. This RTT driver is using or-equal to clear the flags, which means it can possibly clear other interrupts. There's a small chance that one event is missed if it happens very close to another event. Credits to @benpicco, @dylad for pointing out missing fixes. --- cpu/sam0_common/periph/rtt.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cpu/sam0_common/periph/rtt.c b/cpu/sam0_common/periph/rtt.c index b40b2c2d2c..c8793f4463 100644 --- a/cpu/sam0_common/periph/rtt.c +++ b/cpu/sam0_common/periph/rtt.c @@ -98,7 +98,7 @@ void rtt_init(void) _wait_syncbusy(); /* initially clear flag */ - RTC->MODE0.INTFLAG.reg |= RTC_MODE0_INTFLAG_CMP0 + RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0 | RTC_MODE0_INTFLAG_OVF; NVIC_EnableIRQ(RTC_IRQn); @@ -116,12 +116,12 @@ void rtt_set_overflow_cb(rtt_cb_t cb, void *arg) _overflow_arg = arg; /* enable overflow interrupt */ - RTC->MODE0.INTENSET.bit.OVF = 1; + RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_OVF; } void rtt_clear_overflow_cb(void) { /* disable overflow interrupt */ - RTC->MODE0.INTENCLR.bit.OVF = 1; + RTC->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_OVF; } uint32_t rtt_get_counter(void) @@ -158,14 +158,14 @@ void rtt_set_alarm(uint32_t alarm, rtt_cb_t cb, void *arg) _wait_syncbusy(); /* enable compare interrupt and clear flag */ - RTC->MODE0.INTFLAG.reg |= RTC_MODE0_INTFLAG_CMP0; - RTC->MODE0.INTENSET.reg |= RTC_MODE0_INTENSET_CMP0; + RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0; + RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_CMP0; } void rtt_clear_alarm(void) { /* clear compare interrupt */ - RTC->MODE0.INTENCLR.bit.CMP0 = 1; + RTC->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_CMP0; } void rtt_poweron(void) @@ -189,16 +189,16 @@ void rtt_poweroff(void) void isr_rtc(void) { if (RTC->MODE0.INTFLAG.bit.OVF) { - RTC->MODE0.INTFLAG.reg |= RTC_MODE0_INTFLAG_OVF; + RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_OVF; if (_overflow_cb) { _overflow_cb(_overflow_arg); } } if (RTC->MODE0.INTFLAG.bit.CMP0) { /* clear flag */ - RTC->MODE0.INTFLAG.reg |= RTC_MODE0_INTFLAG_CMP0; + RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0; /* disable interrupt */ - RTC->MODE0.INTENCLR.bit.CMP0 = 1; + RTC->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_CMP0; if (_cmp0_cb) { _cmp0_cb(_cmp0_arg); }