From 19aa5880e759685720ab67aa984a6a5d2a5dc66a Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 4 Apr 2016 08:15:48 -0600 Subject: [PATCH] STM32 RTC Alarm: Add Neil's alarm cancellation logic --- arch/arm/src/stm32/stm32_rtc_lowerhalf.c | 22 ++-- arch/arm/src/stm32/stm32f40xxx_rtcc.c | 124 ++++++++++++++++++- arch/arm/src/stm32l4/stm32l4_rtc_lowerhalf.c | 2 + 3 files changed, 138 insertions(+), 10 deletions(-) diff --git a/arch/arm/src/stm32/stm32_rtc_lowerhalf.c b/arch/arm/src/stm32/stm32_rtc_lowerhalf.c index c87c438d4f..a9f90304e6 100644 --- a/arch/arm/src/stm32/stm32_rtc_lowerhalf.c +++ b/arch/arm/src/stm32/stm32_rtc_lowerhalf.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/stm32/stm32_rtc_lowerhalf.c * - * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2015-2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -33,6 +33,8 @@ * ****************************************************************************/ +/* REVISIT: This driver is *not* thread-safe! */ + /**************************************************************************** * Included Files ****************************************************************************/ @@ -490,9 +492,11 @@ static int stm32_setrelative(FAR struct rtc_lowerhalf_s *lower, seconds = mktime(&time); - /* Add the seconds offset */ + /* Add the seconds offset. Add one to the number of seconds + * because we are unsure of the phase of the timer. + */ - seconds += alarminfo->reltime; + seconds += (alarminfo->reltime + 1); /* And convert the time back to broken out format */ @@ -563,15 +567,17 @@ static int stm32_setrelative(FAR struct rtc_lowerhalf_s *lower, ts.tv_nsec = 0; #endif - /* Add the seconds offset */ + /* Add the seconds offset. Add one to the number of seconds because + * we are unsure of the phase of the timer. + */ - ts.tv_sec += alarminfo->reltime; + ts.tv_sec += (alarminfo->reltime + 1); /* Remember the callback information */ - cbinfo = &priv->cbinfo[0]; - cbinfo->cb = alarminfo->cb; - cbinfo->priv = alarminfo->priv; + cbinfo = &priv->cbinfo[0]; + cbinfo->cb = alarminfo->cb; + cbinfo->priv = alarminfo->priv; /* And set the alarm */ diff --git a/arch/arm/src/stm32/stm32f40xxx_rtcc.c b/arch/arm/src/stm32/stm32f40xxx_rtcc.c index 1ad1d5ca60..0f38fcff53 100644 --- a/arch/arm/src/stm32/stm32f40xxx_rtcc.c +++ b/arch/arm/src/stm32/stm32f40xxx_rtcc.c @@ -787,7 +787,7 @@ static int rtchw_set_alrmar(rtc_alarmreg_t alarmreg) ret = rtchw_check_alrawf(); if (ret != OK) { - goto rtchw_set_alrmar_exit; + goto errout_with_wprunlock; } /* Set the RTC Alarm register */ @@ -802,7 +802,7 @@ static int rtchw_set_alrmar(rtc_alarmreg_t alarmreg) cr |= (RTC_CR_ALRAE | RTC_CR_ALRAIE); putreg32(cr, STM32_RTC_CR); -rtchw_set_alrmar_exit: +errout_with_wprunlock: rtc_wprlock(); return ret; } @@ -1406,4 +1406,124 @@ int stm32_rtc_setalarm(FAR struct alm_setalarm_s *alminfo) } #endif +/**************************************************************************** + * Name: stm32_rtc_cancelalarm + * + * Description: + * Cancel an alaram. + * + * Input Parameters: + * alarmid - Identifies the alarm to be cancelled + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +int stm32_rtc_cancelalarm(enum alm_id_e alarmid) +{ + int ret = -EINVAL; + + DEBUGASSERT(RTC_ALARM_LAST > alarmid); + + /* Cancel the alarm in hardware and disable interrupts */ + + switch (alarmid) + { + case RTC_ALARMA: + { + /* Cancel the global callback function */ + + g_alarmcb[alarmid].ac_cb = NULL; + g_alarmcb[alarmid].ac_arg = NULL; + + /* Need to follow RTC register wrote protection. + * Disable the write protection for RTC registers + */ + + rtc_wprunlock(); + +#if 0 + /* Set Initialization mode */ + + ret = rtc_enterinit(); + if (ret < 0) + { + goto errout_with_wprunlock; + } +#endif + + /* Disable RTC alarm and interrupt */ + + modifyreg32(STM32_RTC_CR, (RTC_CR_ALRAE | RTC_CR_ALRAIE), 0); + + ret = rtchw_check_alrawf(); + if (ret < 0) + { + goto errout_with_wprunlock; + } + + /* Unset the alarm */ + + putreg32(-1, STM32_RTC_ALRMAR); + rtc_wprlock(); + ret = OK; + } + break; + + case RTC_ALARMB: + { + /* Cancel the global callback function */ + + g_alarmcb[alarmid].ac_cb = NULL; + g_alarmcb[alarmid].ac_arg = NULL; + + /* Need to follow RTC register wrote protection. + * Disable the write protection for RTC registers + */ + + rtc_wprunlock(); + +#if 0 + /* Set Initialization mode */ + + ret = rtc_enterinit(); + if (ret < 0) + { + goto errout_with_wprunlock; + } +#endif + + /* Disable RTC alarm and interrupt */ + + modifyreg32(STM32_RTC_CR, (RTC_CR_ALRBE | RTC_CR_ALRBIE), 0); + + ret = rtchw_check_alrbwf(); + if (ret < 0) + { + goto errout_with_wprunlock; + } + + /* Unset the alarm */ + + putreg32(-1, STM32_RTC_ALRMBR); + rtc_wprlock(); + ret = OK; + } + break; + + default: + rtcvdbg("ERROR: Invalid ALARM%d\n", alminfo->as_id); + break; + } + + return ret; + +errout_with_wprunlock: + rtc_wprlock(); + return ret; +} +#endif + #endif /* CONFIG_RTC */ diff --git a/arch/arm/src/stm32l4/stm32l4_rtc_lowerhalf.c b/arch/arm/src/stm32l4/stm32l4_rtc_lowerhalf.c index 6c6429f6f6..033a191e41 100644 --- a/arch/arm/src/stm32l4/stm32l4_rtc_lowerhalf.c +++ b/arch/arm/src/stm32l4/stm32l4_rtc_lowerhalf.c @@ -34,6 +34,8 @@ * ****************************************************************************/ +/* REVISIT: This driver is *not* thread-safe! */ + /**************************************************************************** * Included Files ****************************************************************************/