diff --git a/arch/arm/src/stm32/stm32f40xxx_alarm.h b/arch/arm/src/stm32/stm32f40xxx_alarm.h index a063fd39b0..7bd435f344 100644 --- a/arch/arm/src/stm32/stm32f40xxx_alarm.h +++ b/arch/arm/src/stm32/stm32f40xxx_alarm.h @@ -101,7 +101,7 @@ struct alm_rdalarm_s int stm32_rtc_setalarm(FAR struct alm_setalarm_s *alminfo); -/************************************************************************************ +/**************************************************************************** * Name: stm32_rtc_rdalarm * * Description: @@ -113,7 +113,7 @@ int stm32_rtc_setalarm(FAR struct alm_setalarm_s *alminfo); * Returned Value: * Zero (OK) on success; a negated errno on failure * - ************************************************************************************/ + ****************************************************************************/ int stm32_rtc_rdalarm(FAR struct alm_rdalarm_s *alminfo); diff --git a/arch/arm/src/stm32/stm32l15xxx_alarm.h b/arch/arm/src/stm32/stm32l15xxx_alarm.h index b433fff268..72e8d2455c 100644 --- a/arch/arm/src/stm32/stm32l15xxx_alarm.h +++ b/arch/arm/src/stm32/stm32l15xxx_alarm.h @@ -103,7 +103,7 @@ typedef CODE int (*wakeupcb_t)(void); int stm32_rtc_setalarm(FAR struct alm_setalarm_s *alminfo); -/************************************************************************************ +/**************************************************************************** * Name: stm32_rtc_rdalarm * * Description: @@ -115,7 +115,7 @@ int stm32_rtc_setalarm(FAR struct alm_setalarm_s *alminfo); * Returned Value: * Zero (OK) on success; a negated errno on failure * - ************************************************************************************/ + ****************************************************************************/ int stm32_rtc_rdalarm(FAR struct alm_rdalarm_s *alminfo); diff --git a/arch/arm/src/stm32f7/Make.defs b/arch/arm/src/stm32f7/Make.defs index fb05fecf33..64210d0655 100644 --- a/arch/arm/src/stm32f7/Make.defs +++ b/arch/arm/src/stm32f7/Make.defs @@ -1,7 +1,7 @@ ############################################################################ # arch/arm/src/stm32f7/Make.defs # -# Copyright (C) 2015 Gregory Nutt. All rights reserved. +# Copyright (C) 2015, 2018 Gregory Nutt. All rights reserved. # Author: Gregory Nutt # # Redistribution and use in source and binary forms, with or without @@ -144,6 +144,9 @@ CHIP_CSRCS += stm32_rtc.c ifeq ($(CONFIG_RTC_ALARM),y) CHIP_CSRCS += stm32_exti_alarm.c endif +ifeq ($(CONFIG_RTC_PERIODIC),y) +CHIP_CSRCS += stm32_exti_wakeup.c +endif ifeq ($(CONFIG_RTC_DRIVER),y) CHIP_CSRCS += stm32_rtc_lowerhalf.c endif diff --git a/arch/arm/src/stm32f7/stm32_alarm.h b/arch/arm/src/stm32f7/stm32_alarm.h index a2d8c297cd..71c8b712c4 100644 --- a/arch/arm/src/stm32f7/stm32_alarm.h +++ b/arch/arm/src/stm32f7/stm32_alarm.h @@ -1,8 +1,8 @@ /**************************************************************************** * arch/arm/src/include/stm32f7/stm32_alarm.h * - * Copyright (C) 2016 Gregory Nutt. All rights reserved. - * Authors: Neil hancock - delegated to Gregory Nutt Mar 30, 2016 + * Copyright (C) 2016, 2018 Gregory Nutt. All rights reserved. + * Authors: Neil Hancock - delegated to Gregory Nutt Mar 30, 2016 * David Sidrane * * Redistribution and use in source and binary forms, with or without @@ -44,16 +44,14 @@ #include #include -#ifdef CONFIG_RTC_ALARM - /**************************************************************************** * Public Types ****************************************************************************/ +#ifdef CONFIG_RTC_ALARM typedef CODE void (*alm_callback_t)(FAR void *arg, unsigned int alarmid); -/* These features map to STM32 RTC from stm32F7xx - */ +/* These features map to STM32 RTC from stm32F7xx */ enum alm_id_e { @@ -79,11 +77,17 @@ struct alm_rdalarm_s int ar_id; /* enum alm_id_e */ FAR struct rtc_time *ar_time; /* Argument for storing ALARM RTC time */ }; +#endif + +#ifdef CONFIG_RTC_PERIODIC +typedef CODE int (*wakeupcb_t)(void); +#endif /**************************************************************************** * Public Function Prototypes ****************************************************************************/ +#ifdef CONFIG_RTC_ALARM /**************************************************************************** * Name: stm32_rtc_setalarm * @@ -100,7 +104,7 @@ struct alm_rdalarm_s int stm32_rtc_setalarm(FAR struct alm_setalarm_s *alminfo); -/************************************************************************************ +/**************************************************************************** * Name: stm32_rtc_rdalarm * * Description: @@ -112,7 +116,7 @@ int stm32_rtc_setalarm(FAR struct alm_setalarm_s *alminfo); * Returned Value: * Zero (OK) on success; a negated errno on failure * - ************************************************************************************/ + ****************************************************************************/ int stm32_rtc_rdalarm(FAR struct alm_rdalarm_s *alminfo); @@ -131,6 +135,41 @@ int stm32_rtc_rdalarm(FAR struct alm_rdalarm_s *alminfo); ****************************************************************************/ int stm32_rtc_cancelalarm(enum alm_id_e alarmid); - #endif /* CONFIG_RTC_ALARM */ + +#ifdef CONFIG_RTC_PERIODIC +/**************************************************************************** + * Name: stm32_rtc_setperiodic + * + * Description: + * Set a periodic RTC wakeup + * + * Input Parameters: + * period - Time to sleep between wakeups + * callback - Function to call when the period expires. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +int stm32_rtc_setperiodic(FAR const struct timespec *period, + wakeupcb_t callback); + +/**************************************************************************** + * Name: stm32_rtc_cancelperiodic + * + * Description: + * Cancel a periodic wakeup + * + * Input Parameters: + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +int stm32_rtc_cancelperiodic(void); +#endif /* CONFIG_RTC_PERIODIC */ + #endif /* __ARCH_ARM_SRC_STM32F7_STM32_ALARM_H */ diff --git a/arch/arm/src/stm32f7/stm32_exti.h b/arch/arm/src/stm32f7/stm32_exti.h index f9b1f2eaa0..e6e4786d95 100644 --- a/arch/arm/src/stm32f7/stm32_exti.h +++ b/arch/arm/src/stm32f7/stm32_exti.h @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/stm32f7/stm32_exti.h * - * Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2015, 2017-2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -84,7 +84,7 @@ extern "C" * Zero (OK) on success; a negated errno value on failure indicating the * nature of the failure. * - ************************************************************************************/ + ****************************************************************************/ int stm32_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge, bool event, xcpt_t func, void *arg); @@ -113,6 +113,29 @@ int stm32_exti_alarm(bool risingedge, bool fallingedge, bool event, xcpt_t func, void *arg); #endif +/**************************************************************************** + * Name: stm32_exti_wakeup + * + * Description: + * Sets/clears EXTI wakeup interrupt. + * + * Input Parameters: + * - rising/falling edge: enables interrupt on rising/falling edges + * - event: generate event when set + * - func: when non-NULL, generate interrupt + * - arg: Argument passed to the interrupt callback + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure indicating the + * nature of the failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_PERIODIC +int stm32_exti_wakeup(bool risingedge, bool fallingedge, bool event, + xcpt_t func, void *arg); +#endif + #undef EXTERN #if defined(__cplusplus) } diff --git a/arch/arm/src/stm32f7/stm32_rtc.c b/arch/arm/src/stm32f7/stm32_rtc.c index cea967769d..2bf6392402 100644 --- a/arch/arm/src/stm32f7/stm32_rtc.c +++ b/arch/arm/src/stm32f7/stm32_rtc.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/stm32f7/stm32_rtc.c * - * Copyright (C) 2011, 2015-2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2011, 2015-2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * David Sidrane * @@ -137,6 +137,11 @@ struct alm_cbinfo_s static struct alm_cbinfo_s g_alarmcb[RTC_ALARM_LAST]; #endif +#ifdef CONFIG_RTC_PERIODIC +static wakeupcb_t g_wakeupcb; +static bool g_wakeup_enabled; /* True: Wakeup interrupts are enabled */ +#endif + /**************************************************************************** * Public Data ****************************************************************************/ @@ -268,8 +273,8 @@ static void rtc_wprunlock(void) stm32_pwr_enablebkp(true); - /* The following steps are required to unlock the write protection on all the - * RTC registers (except for RTC_ISR[13:8], RTC_TAFCR, and RTC_BKPxR). + /* The following steps are required to unlock the write protection on all + * the RTC registers (except for RTC_ISR[13:8], RTC_TAFCR, and RTC_BKPxR). * * 1. Write 0xCA into the RTC_WPR register. * 2. Write 0x53 into the RTC_WPR register. @@ -1551,7 +1556,7 @@ int stm32_rtc_setalarm(FAR struct alm_setalarm_s *alminfo) * Cancel an alarm. * * Input Parameters: - * alarmid - Identifies the alarm to be cancelled + * alarmid - Identifies the alarm to be canceled * * Returned Value: * Zero (OK) on success; a negated errno on failure @@ -1700,4 +1705,281 @@ int stm32_rtc_rdalarm(FAR struct alm_rdalarm_s *alminfo) } #endif +/**************************************************************************** + * Name: stm32_rtc_wakeup_handler + * + * Description: + * RTC WAKEUP interrupt service routine through the EXTI line + * + * Input Parameters: + * irq - The IRQ number that generated the interrupt + * + * Returned Value: + * Zero (OK) on success; A negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_PERIODIC +static int stm32_rtc_wakeup_handler(int irq, FAR void *context, + FAR void *arg) +{ + uint32_t regval = 0; + + stm32_pwr_enablebkp(true); + + regval = getreg32(STM32_RTC_ISR); + regval &= ~RTC_ISR_WUTF; + putreg32(regval, STM32_RTC_ISR); + + stm32_pwr_enablebkp(false); + + if (g_wakeupcb != NULL) + { + g_wakeupcb(); + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: rtc_enable_wakeup + * + * Description: + * Enable periodic wakeup interrupts + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_PERIODIC +static inline void rtc_enable_wakeup(void) +{ + if (!g_wakeup_enabled) + { + (void)stm32_exti_wakeup(true, false, true, stm32_rtc_wakeup_handler, + NULL); + g_wakeup_enabled = true; + } +} +#endif + +/************************************************************************************ + * Name: rtc_set_wcksel + * + * Description: + * Sets RTC wakeup clock selection value + * + ************************************************************************************/ + +#ifdef CONFIG_RTC_PERIODIC +static inline void rtc_set_wcksel(unsigned int wucksel) +{ + uint32_t regval = 0; + + regval = getreg32(STM32_RTC_CR); + regval &= ~RTC_CR_WUCKSEL_MASK; + regval |= wucksel; + putreg32(regval, STM32_RTC_CR); +} +#endif + +/**************************************************************************** + * Name: stm32_rtc_setperiodic + * + * Description: + * Set a periodic RTC wakeup + * + * Input Parameters: + * period - Time to sleep between wakeups + * callback - Function to call when the period expires. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_PERIODIC +int stm32_rtc_setperiodic(FAR const struct timespec *period, + wakeupcb_t callback) +{ + unsigned int wutr_val; + int ret; + int timeout; + uint32_t regval; + uint32_t secs; + uint32_t millisecs; + +#if defined(CONFIG_STM32F7_RTC_HSECLOCK) +# error "Periodic wakeup not available for HSE" +#elif defined(CONFIG_STM32F7_RTC_LSICLOCK) +# error "Periodic wakeup not available for LSI (and it is too inaccurate!)" +#elif defined(CONFIG_STM32F7_RTC_LSECLOCK) + const uint32_t rtc_div16_max_msecs = 16 * 1000 * 0xffffU / STM32_LSE_FREQUENCY; +#else +# error "No clock for RTC!" +#endif + + /* Lets use RTC wake-up with 0.001 sec to ~18 hour range. + * + * TODO: scale to higher periods, with necessary losing some precision. + * We currently go for subseconds accuracy instead of maximum period. + */ + + if (period->tv_sec > 0xffffU || + (period->tv_sec == 0xffffU && period->tv_nsec > 0)) + { + /* More than max. */ + + secs = 0xffffU; + millisecs = secs * 1000; + } + else + { + secs = period->tv_sec; + millisecs = secs * 1000 + period->tv_nsec / NSEC_PER_MSEC; + } + + if (millisecs == 0) + { + return -EINVAL; + } + + /* Make sure the alarm interrupt is enabled at the NVIC */ + + rtc_enable_wakeup(); + + rtc_wprunlock(); + + /* Clear WUTE in RTC_CR to disable the wakeup timer */ + + regval = getreg32(STM32_RTC_CR); + regval &= ~RTC_CR_WUTE; + putreg32(regval, STM32_RTC_CR); + + /* Poll WUTWF until it is set in RTC_ISR (takes around 2 RTCCLK clock + * cycles) + */ + + ret = -ETIMEDOUT; + for (timeout = 0; timeout < SYNCHRO_TIMEOUT; timeout++) + { + regval = getreg32(STM32_RTC_ISR); + if ((regval & RTC_ISR_WUTWF) != 0) + { + /* Synchronized */ + + ret = OK; + break; + } + } + + /* Set callback function pointer. */ + + g_wakeupcb = callback; + + if (millisecs <= rtc_div16_max_msecs) + { + unsigned int ticks; + + /* Select wake-up with 32768/16 hz counter. */ + + rtc_set_wcksel(RTC_CR_WUCKSEL_RTCDIV16); + + /* Get number of ticks. */ + + ticks = millisecs * STM32_LSE_FREQUENCY / (16 * 1000); + + /* Wake-up is after WUT+1 ticks. */ + + wutr_val = ticks - 1; + } + else + { + /* Select wake-up with 1hz counter. */ + + rtc_set_wcksel(RTC_CR_WUCKSEL_CKSPRE); + + /* Wake-up is after WUT+1 ticks. */ + + wutr_val = secs - 1; + } + + /* Program the wakeup auto-reload value WUT[15:0], and the wakeup clock + * selection. + */ + + putreg32(wutr_val, STM32_RTC_WUTR); + + regval = getreg32(STM32_RTC_CR); + regval |= RTC_CR_WUTIE | RTC_CR_WUTE; + putreg32(regval, STM32_RTC_CR); + + /* Just in case resets the WUTF flag in RTC_ISR */ + + regval = getreg32(STM32_RTC_ISR); + regval &= ~RTC_ISR_WUTF; + putreg32(regval, STM32_RTC_ISR); + + rtc_wprlock(); + + return ret; +} +#endif + +/**************************************************************************** + * Name: stm32_rtc_cancelperiodic + * + * Description: + * Cancel a periodic wakeup + * + * Input Parameters: + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_PERIODIC +int stm32_rtc_cancelperiodic(void) +{ + int ret = OK; + int timeout = 0; + uint32_t regval = 0; + + rtc_wprunlock(); + + /* Clear WUTE and WUTIE in RTC_CR to disable the wakeup timer */ + + regval = getreg32(STM32_RTC_CR); + regval &= ~(RTC_CR_WUTE | RTC_CR_WUTIE); + putreg32(regval, STM32_RTC_CR); + + /* Poll WUTWF until it is set in RTC_ISR (takes around 2 RTCCLK clock + * cycles) + */ + + ret = -ETIMEDOUT; + for (timeout = 0; timeout < SYNCHRO_TIMEOUT; timeout++) + { + regval = getreg32(STM32_RTC_ISR); + if ((regval & RTC_ISR_WUTWF) != 0) + { + /* Synchronized */ + + ret = OK; + break; + } + } + + /* Clears RTC_WUTR register */ + + regval = getreg32(STM32_RTC_WUTR); + regval &= ~RTC_WUTR_MASK; + putreg32(regval, STM32_RTC_WUTR); + + rtc_wprlock(); + + return ret; +} +#endif + #endif /* CONFIG_RTC */ diff --git a/arch/arm/src/stm32f7/stm32_rtc_lowerhalf.c b/arch/arm/src/stm32f7/stm32_rtc_lowerhalf.c index 03a0d518f2..26e746848f 100644 --- a/arch/arm/src/stm32f7/stm32_rtc_lowerhalf.c +++ b/arch/arm/src/stm32f7/stm32_rtc_lowerhalf.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/stm32f7/stm32_rtc_lowerhalf.c * - * Copyright (C) 2015-2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2015-2016, 2018 Gregory Nutt. All rights reserved. * Authors: Gregory Nutt * David Sidrane * @@ -34,8 +34,6 @@ * ****************************************************************************/ -/* REVISIT: This driver is *not* thread-safe! */ - /**************************************************************************** * Included Files ****************************************************************************/ @@ -71,7 +69,7 @@ struct stm32_cbinfo_s { volatile rtc_alarm_callback_t cb; /* Callback when the alarm expires */ - volatile FAR void *priv; /* Private argurment to accompany callback */ + volatile FAR void *priv; /* Private argument to accompany callback */ uint8_t id; /* Identifies the alarm */ }; #endif @@ -92,16 +90,25 @@ struct stm32_lowerhalf_s * this file. */ + sem_t devsem; /* Threads can only exclusively access the RTC */ + #ifdef CONFIG_RTC_ALARM /* Alarm callback information */ struct stm32_cbinfo_s cbinfo[STM32_NALARMS]; #endif + +#ifdef CONFIG_RTC_PERIODIC + /* Periodic wakeup information */ + + struct lower_setperiodic_s periodic; +#endif }; /**************************************************************************** * Private Function Prototypes ****************************************************************************/ + /* Prototypes for static methods in struct rtc_ops_s */ static int stm32_rdtime(FAR struct rtc_lowerhalf_s *lower, @@ -121,6 +128,12 @@ static int stm32_rdalarm(FAR struct rtc_lowerhalf_s *lower, FAR struct lower_rdalarm_s *alarminfo); #endif +#ifdef CONFIG_RTC_PERIODIC +static int stm32_setperiodic(FAR struct rtc_lowerhalf_s *lower, + FAR const struct lower_setperiodic_s *alarminfo); +static int stm32_cancelperiodic(FAR struct rtc_lowerhalf_s *lower, int id); +#endif + /**************************************************************************** * Private Data ****************************************************************************/ @@ -137,6 +150,10 @@ static const struct rtc_ops_s g_rtc_ops = .cancelalarm = stm32_cancelalarm, .rdalarm = stm32_rdalarm, #endif +#ifdef CONFIG_RTC_PERIODIC + .setperiodic = stm32_setperiodic, + .cancelperiodic = stm32_cancelperiodic, +#endif #ifdef CONFIG_RTC_IOCTL .ioctl = NULL, #endif @@ -149,7 +166,7 @@ static const struct rtc_ops_s g_rtc_ops = static struct stm32_lowerhalf_s g_rtc_lowerhalf = { - .ops = &g_rtc_ops, + .ops = &g_rtc_ops, }; /**************************************************************************** @@ -179,6 +196,7 @@ static void stm32_alarm_callback(FAR void *arg, unsigned int alarmid) rtc_alarm_callback_t cb; FAR void *priv; + DEBUGASSERT(arg != NULL); DEBUGASSERT(alarmid == RTC_ALARMA || alarmid == RTC_ALARMB); lower = (struct stm32_lowerhalf_s *)arg; @@ -223,42 +241,23 @@ static void stm32_alarm_callback(FAR void *arg, unsigned int alarmid) static int stm32_rdtime(FAR struct rtc_lowerhalf_s *lower, FAR struct rtc_time *rtctime) { + FAR struct stm32_lowerhalf_s *priv; + int ret; + + priv = (FAR struct stm32_lowerhalf_s *)lower; + + ret = nxsem_wait(&priv->devsem); + if (ret < 0) + { + return ret; + } + #if defined(CONFIG_RTC_DATETIME) /* This operation depends on the fact that struct rtc_time is cast * compatible with struct tm. */ - return up_rtc_getdatetime((FAR struct tm *)rtctime); - -#elif defined(CONFIG_RTC_HIRES) - FAR struct timespec ts; - int ret; - - /* Get the higher resolution time */ - - ret = up_rtc_gettime(&ts); - if (ret < 0) - { - goto errout_with_errno; - } - - /* Convert the one second epoch time to a struct tm. This operation - * depends on the fact that struct rtc_time and struct tm are cast - * compatible. - */ - - if (!gmtime_r(&ts.tv_sec, (FAR struct tm *)rtctime)) - { - goto errout_with_errno; - } - - return OK; - -errout_with_errno: - ret = get_errno(); - DEBUGASSERT(ret > 0); - return -ret; - + ret = up_rtc_getdatetime((FAR struct tm *)rtctime); #else time_t timer; @@ -272,11 +271,13 @@ errout_with_errno: { int errcode = get_errno(); DEBUGASSERT(errcode > 0); + nxsem_post(&priv->devsem); return -errcode; } - return OK; #endif + nxsem_post(&priv->devsem); + return ret; } /**************************************************************************** @@ -298,12 +299,23 @@ errout_with_errno: static int stm32_settime(FAR struct rtc_lowerhalf_s *lower, FAR const struct rtc_time *rtctime) { + FAR struct stm32_lowerhalf_s *priv; + int ret; + + priv = (FAR struct stm32_lowerhalf_s *)lower; + + ret = nxsem_wait(&priv->devsem); + if (ret < 0) + { + return ret; + } + #ifdef CONFIG_RTC_DATETIME /* This operation depends on the fact that struct rtc_time is cast * compatible with struct tm. */ - return stm32_rtc_setdatetime((FAR const struct tm *)rtctime); + ret = stm32_rtc_setdatetime((FAR const struct tm *)rtctime); #else struct timespec ts; @@ -317,8 +329,11 @@ static int stm32_settime(FAR struct rtc_lowerhalf_s *lower, /* Now set the time (to one second accuracy) */ - return up_rtc_settime(&ts); + ret = up_rtc_settime(&ts); #endif + + nxsem_post(&priv->devsem); + return ret; } /**************************************************************************** @@ -337,7 +352,7 @@ static int stm32_settime(FAR struct rtc_lowerhalf_s *lower, static bool stm32_havesettime(FAR struct rtc_lowerhalf_s *lower) { - return getreg32(RTC_MAGIC_REG) == RTC_MAGIC_TIME_SET; + return stm32_rtc_havesettime(); } /**************************************************************************** @@ -364,7 +379,7 @@ static int stm32_setalarm(FAR struct rtc_lowerhalf_s *lower, FAR struct stm32_lowerhalf_s *priv; FAR struct stm32_cbinfo_s *cbinfo; struct alm_setalarm_s lowerinfo; - int ret = -EINVAL; + int ret; /* ID0-> Alarm A; ID1 -> Alarm B */ @@ -372,6 +387,13 @@ static int stm32_setalarm(FAR struct rtc_lowerhalf_s *lower, DEBUGASSERT(alarminfo->id == RTC_ALARMA || alarminfo->id == RTC_ALARMB); priv = (FAR struct stm32_lowerhalf_s *)lower; + ret = nxsem_wait(&priv->devsem); + if (ret < 0) + { + return ret; + } + + ret = -EINVAL; if (alarminfo->id == RTC_ALARMA || alarminfo->id == RTC_ALARMB) { /* Remember the callback information */ @@ -398,6 +420,8 @@ static int stm32_setalarm(FAR struct rtc_lowerhalf_s *lower, } } + nxsem_post(&priv->devsem); + return ret; } #endif @@ -483,7 +507,7 @@ static int stm32_setrelative(FAR struct rtc_lowerhalf_s *lower, * method of the RTC driver interface * * Input Parameters: - * lower - A reference to RTC lower half driver state structure + * lower - A reference to RTC lower half driver state structure * alarminfo - Provided information needed to set the alarm * * Returned Value: @@ -497,14 +521,21 @@ static int stm32_cancelalarm(FAR struct rtc_lowerhalf_s *lower, int alarmid) { FAR struct stm32_lowerhalf_s *priv; FAR struct stm32_cbinfo_s *cbinfo; - int ret = -EINVAL; + int ret; DEBUGASSERT(lower != NULL); DEBUGASSERT(alarmid == RTC_ALARMA || alarmid == RTC_ALARMB); priv = (FAR struct stm32_lowerhalf_s *)lower; + ret = nxsem_wait(&priv->devsem); + if (ret < 0) + { + return ret; + } + /* ID0-> Alarm A; ID1 -> Alarm B */ + ret = -EINVAL; if (alarmid == RTC_ALARMA || alarmid == RTC_ALARMB) { /* Nullify callback information to reduce window for race conditions */ @@ -518,6 +549,8 @@ static int stm32_cancelalarm(FAR struct rtc_lowerhalf_s *lower, int alarmid) ret = stm32_rtc_cancelalarm((enum alm_id_e)alarmid); } + nxsem_post(&priv->devsem); + return ret; } #endif @@ -529,7 +562,7 @@ static int stm32_cancelalarm(FAR struct rtc_lowerhalf_s *lower, int alarmid) * Query the RTC alarm. * * Input Parameters: - * lower - A reference to RTC lower half driver state structure + * lower - A reference to RTC lower half driver state structure * alarminfo - Provided information needed to query the alarm * * Returned Value: @@ -568,6 +601,132 @@ static int stm32_rdalarm(FAR struct rtc_lowerhalf_s *lower, } #endif +/**************************************************************************** + * Name: stm32_periodic_callback + * + * Description: + * This is the function that is called from the RTC driver when the + * periodic wakeup goes off. It just invokes the upper half driver's + * callback. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_PERIODIC +static int stm32_periodic_callback(void) +{ + FAR struct stm32_lowerhalf_s *lower; + struct lower_setperiodic_s *cbinfo; + rtc_wakeup_callback_t cb; + FAR void *priv; + + lower = (FAR struct stm32_lowerhalf_s *)&g_rtc_lowerhalf; + + cbinfo = &lower->periodic; + cb = (rtc_wakeup_callback_t)cbinfo->cb; + priv = (FAR void *)cbinfo->priv; + + /* Perform the callback */ + + if (cb != NULL) + { + cb(priv, 0); + } + + return OK; +} +#endif /* CONFIG_RTC_PERIODIC */ + +/**************************************************************************** + * Name: stm32_setperiodic + * + * Description: + * Set a new periodic wakeup relative to the current time, with a given + * period. This function implements the setperiodic() method of the RTC + * driver interface + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure + * alarminfo - Provided information needed to set the wakeup activity + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_PERIODIC +static int stm32_setperiodic(FAR struct rtc_lowerhalf_s *lower, + FAR const struct lower_setperiodic_s *alarminfo) +{ + FAR struct stm32_lowerhalf_s *priv; + int ret; + + ASSERT(lower != NULL && alarminfo != NULL); + priv = (FAR struct stm32_lowerhalf_s *)lower; + + ret = nxsem_wait(&priv->devsem); + if (ret < 0) + { + return ret; + } + + memcpy(&priv->periodic, alarminfo, sizeof(struct lower_setperiodic_s)); + + ret = stm32_rtc_setperiodic(&alarminfo->period, stm32_periodic_callback); + + nxsem_post(&priv->devsem); + + return ret; +} +#endif + +/**************************************************************************** + * Name: stm32_cancelperiodic + * + * Description: + * Cancel the current periodic wakeup activity. This function implements + * the cancelperiodic() method of the RTC driver interface + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_PERIODIC +static int stm32_cancelperiodic(FAR struct rtc_lowerhalf_s *lower, int id) +{ + FAR struct stm32_lowerhalf_s *priv; + int ret; + + DEBUGASSERT(lower != NULL); + priv = (FAR struct stm32_lowerhalf_s *)lower; + + DEBUGASSERT(id == 0); + + ret = nxsem_wait(&priv->devsem); + if (ret < 0) + { + return ret; + } + + ret = stm32_rtc_cancelperiodic(); + + nxsem_post(&priv->devsem); + + return ret; +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -596,6 +755,8 @@ static int stm32_rdalarm(FAR struct rtc_lowerhalf_s *lower, FAR struct rtc_lowerhalf_s *stm32_rtc_lowerhalf(void) { + nxsem_init(&g_rtc_lowerhalf.devsem, 0, 1); + return (FAR struct rtc_lowerhalf_s *)&g_rtc_lowerhalf; } diff --git a/arch/arm/src/stm32l4/stm32l4_exti_wakeup.c b/arch/arm/src/stm32l4/stm32l4_exti_wakeup.c index ddac94add3..aa44a9322a 100644 --- a/arch/arm/src/stm32l4/stm32l4_exti_wakeup.c +++ b/arch/arm/src/stm32l4/stm32l4_exti_wakeup.c @@ -102,7 +102,7 @@ static int stm32l4_exti_wakeup_isr(int irq, void *context, FAR void *arg) * Description: * Sets/clears EXTI wakeup interrupt. * - * Parameters: + * Input Parameters: * - rising/falling edge: enables interrupt on rising/falling edges * - event: generate event when set * - func: when non-NULL, generate interrupt diff --git a/libc/syslog/lib_setlogmask.c b/libc/syslog/lib_setlogmask.c index 1d91d40555..02aaa70107 100644 --- a/libc/syslog/lib_setlogmask.c +++ b/libc/syslog/lib_setlogmask.c @@ -74,17 +74,17 @@ uint8_t g_syslog_mask = LOG_ALL; * is not modified." In this implementation, the value zero is permitted * in order to disable all syslog levels. * - * REVISIT: Per POSIX the syslog mask should be a per-process value but in - * NuttX, the scope of the mask is dependent on the nature of the build: + * REVISIT: Per POSIX the syslog mask should be a per-process value but in + * NuttX, the scope of the mask is dependent on the nature of the build: * * Flat Build: There is one, global SYSLOG mask that controls all output. * Protected Build: There are two SYSLOG masks. One within the kernel * that controls only kernel output. And one in user-space that controls * only user SYSLOG output. * Kernel Build: The kernel build is compliant with the POSIX requirement: - * There will be one mask for for each user process, controlling the - * SYSLOG output only form that process. There will be a separate mask - * accessable only in the kernel code to control kernel SYSLOG output. + * There will be one mask for each user process, controlling the SYSLOG + * output only form that process. There will be a separate mask + * accessible only in the kernel code to control kernel SYSLOG output. * ****************************************************************************/