cpu/sam0_common: RTC: add timeout to spurious tamper event
Errate 2.17.4 says: > Upon enabling the RTC tamper detection feature, a false tamper > detection *can* be reported by the RTC. It turns out that this spurious event is not always generated. If RTC alarm is used and the CPU was previously woken from hibernate by RTC, it *can* happen that the false tamper event is *not* generated. In this case, we will block indefinitely on the mutex. To solve this, add a timeout to the event. Also poll the event instead of using a mutex, as we have already set `PM->SLEEPCFG.bit.SLEEPMODE` at this point.
This commit is contained in:
parent
7a6dec464e
commit
3a7aa5d09a
@ -25,7 +25,6 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mutex.h"
|
||||
#include "periph/rtc.h"
|
||||
#include "periph/rtt.h"
|
||||
#include "periph_conf.h"
|
||||
@ -337,14 +336,9 @@ int rtc_tamper_register(gpio_t pin, gpio_flank_t flank)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _unlock(void *m)
|
||||
{
|
||||
mutex_unlock(m);
|
||||
}
|
||||
|
||||
void rtc_tamper_enable(void)
|
||||
{
|
||||
mutex_t m = MUTEX_INIT;
|
||||
DEBUG("enable tamper\n");
|
||||
|
||||
/* clear tamper id */
|
||||
RTC->MODE0.TAMPID.reg = 0xF;
|
||||
@ -352,16 +346,32 @@ void rtc_tamper_enable(void)
|
||||
/* work around errata 2.17.4:
|
||||
* ignore the first tamper event on the rising edge */
|
||||
if (RTC->MODE0.TAMPCTRL.reg & RTC_TAMPCTRL_TAMLVL_Msk) {
|
||||
mutex_lock(&m);
|
||||
tamper_cb.cb = _unlock;
|
||||
tamper_cb.arg = &m;
|
||||
|
||||
/* If an RTC alarm happened before, the spurious tamper
|
||||
* event is sometimes not generated.
|
||||
* Tamper event must happen within one RTC clock period. */
|
||||
unsigned timeout = CLOCK_CORECLOCK / 32768;
|
||||
|
||||
/* prevent RTC interrupt from triggering */
|
||||
NVIC_DisableIRQ(RTC_IRQn);
|
||||
|
||||
/* enable tamper detect as wake-up source */
|
||||
RTC->MODE0.INTENSET.bit.TAMPER = 1;
|
||||
|
||||
/* wait for first tamper event */
|
||||
while (!RTC->MODE0.INTFLAG.bit.TAMPER && --timeout) {}
|
||||
|
||||
/* clear tamper flag flag */
|
||||
RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_TAMPER;
|
||||
|
||||
/* restore RTC IRQ */
|
||||
NVIC_EnableIRQ(RTC_IRQn);
|
||||
} else {
|
||||
/* no spurious event on falling edge */
|
||||
RTC->MODE0.INTENSET.bit.TAMPER = 1;
|
||||
}
|
||||
|
||||
/* enable tamper detect as wake-up source */
|
||||
RTC->MODE0.INTENSET.bit.TAMPER = 1;
|
||||
|
||||
/* wait for first tamper event */
|
||||
mutex_lock(&m);
|
||||
DEBUG("tamper enabled\n");
|
||||
}
|
||||
|
||||
#endif /* RTC_NUM_OF_TAMPERS */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user