arch/srm/src/stm32f7: Add CONFIG_RTC_PERIODIC support. Also makes the RTC lowerhalf more like in STM32L4.
This commit is contained in:
parent
de6b13b3ab
commit
628821fdf4
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 <gnutt@nuttx.org>
|
||||
#
|
||||
# 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
|
||||
|
@ -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 <david_s5@nscdg.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -44,16 +44,14 @@
|
||||
#include <nuttx/config.h>
|
||||
#include <time.h>
|
||||
|
||||
#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 */
|
||||
|
@ -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 <gnutt@nuttx.org>
|
||||
*
|
||||
* 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)
|
||||
}
|
||||
|
@ -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 <gnutt@nuttx.org>
|
||||
* David Sidrane <david_s5@nscdg.com>
|
||||
*
|
||||
@ -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 */
|
||||
|
@ -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 <gnutt@nuttx.org>
|
||||
* David Sidrane <david_s5@nscdg.com>
|
||||
*
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user