From 89fd987a1ae97f189795c56f2b38ad321352603d Mon Sep 17 00:00:00 2001 From: SPRESENSE <41312067+SPRESENSE@users.noreply.github.com> Date: Wed, 19 May 2021 17:04:01 +0900 Subject: [PATCH] arch: cxd56xx: Fix RTC alarm cancellation process There is an issue that the next alarm is expired immediately after canceling a RTC alarm. Fixed alarm settings to be completely cleared when canceling an RTC alarm. --- arch/arm/src/cxd56xx/cxd56_rtc.c | 36 +++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/arch/arm/src/cxd56xx/cxd56_rtc.c b/arch/arm/src/cxd56xx/cxd56_rtc.c index 58cec8a2eb..410f09f39d 100644 --- a/arch/arm/src/cxd56xx/cxd56_rtc.c +++ b/arch/arm/src/cxd56xx/cxd56_rtc.c @@ -542,6 +542,7 @@ int cxd56_rtc_setalarm(FAR struct alm_setalarm_s *alminfo) int ret = -EBUSY; int id; uint64_t count; + uint32_t mask; ASSERT(alminfo != NULL); DEBUGASSERT(RTC_ALARM_LAST > alminfo->as_id); @@ -565,6 +566,13 @@ int cxd56_rtc_setalarm(FAR struct alm_setalarm_s *alminfo) count -= g_rtc_save->offset; + /* clear previsous setting */ + + mask = RTCREG_ALM0_ERR_FLAG_MASK | RTCREG_ALM0_FLAG_MASK; + mask <<= id; + + putreg32(mask, CXD56_RTC0_ALMCLR); + /* wait until previous alarm request is completed */ while (RTCREG_ASET_BUSY_MASK & getreg32(CXD56_RTC0_SETALMPRECNT(id))); @@ -609,10 +617,11 @@ int cxd56_rtc_cancelalarm(enum alm_id_e alarmid) FAR struct alm_cbinfo_s *cbinfo; irqstate_t flags; int ret = -ENODATA; + uint32_t mask; DEBUGASSERT(RTC_ALARM_LAST > alarmid); - /* Set the alarm in hardware and enable interrupts */ + /* Cancel the alarm in hardware and clear interrupts */ cbinfo = &g_alarmcb[alarmid]; @@ -628,6 +637,31 @@ int cxd56_rtc_cancelalarm(enum alm_id_e alarmid) putreg32(0, CXD56_RTC0_ALMOUTEN(alarmid)); + while (RTCREG_ALM_BUSY_MASK & getreg32(CXD56_RTC0_ALMOUTEN(alarmid))); + + /* wait until previous alarm request is completed */ + + while (RTCREG_ASET_BUSY_MASK & + getreg32(CXD56_RTC0_SETALMPRECNT(alarmid))); + + /* clear the alarm counter */ + + putreg32(0, CXD56_RTC0_SETALMPOSTCNT(alarmid)); + putreg32(0, CXD56_RTC0_SETALMPRECNT(alarmid)); + + while (RTCREG_ASET_BUSY_MASK & + getreg32(CXD56_RTC0_SETALMPRECNT(alarmid))); + + /* wait until the interrupt flag is clear */ + + mask = RTCREG_ALM0_ERR_FLAG_MASK | RTCREG_ALM0_FLAG_MASK; + mask <<= alarmid; + + while (mask & getreg32(CXD56_RTC0_ALMFLG)) + { + putreg32(mask, CXD56_RTC0_ALMCLR); + } + spin_unlock_irqrestore(NULL, flags); ret = OK;