mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 02:48:37 +08:00
up_rtc_gettime: add spinlock to protect up_rtc_gettime
reason: We have removed the critical section protection for the up_rtc_gettime function in common code. Signed-off-by: hujun5 <hujun5@xiaomi.com>
This commit is contained in:
parent
89455bc9a1
commit
57ca4e1789
10 changed files with 108 additions and 37 deletions
|
@ -399,10 +399,14 @@ time_t up_rtc_time(void)
|
||||||
#ifdef CONFIG_RTC_HIRES
|
#ifdef CONFIG_RTC_HIRES
|
||||||
int up_rtc_gettime(struct timespec *tp)
|
int up_rtc_gettime(struct timespec *tp)
|
||||||
{
|
{
|
||||||
|
irqstate_t flags;
|
||||||
uint64_t count;
|
uint64_t count;
|
||||||
|
|
||||||
count = cxd56_rtc_count();
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
|
|
||||||
|
count = cxd56_rtc_count_nolock();
|
||||||
count += g_rtc_save->offset;
|
count += g_rtc_save->offset;
|
||||||
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
|
|
||||||
/* Then we can save the time in seconds and fractional seconds. */
|
/* Then we can save the time in seconds and fractional seconds. */
|
||||||
|
|
||||||
|
@ -477,21 +481,28 @@ int up_rtc_settime(const struct timespec *tp)
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
uint64_t cxd56_rtc_count(void)
|
uint64_t cxd56_rtc_count_nolock(void)
|
||||||
{
|
{
|
||||||
uint64_t val;
|
uint64_t val;
|
||||||
irqstate_t flags;
|
|
||||||
|
|
||||||
/* The pre register is latched with reading the post rtcounter register,
|
/* The pre register is latched with reading the post rtcounter register,
|
||||||
* so these registers always have to been read in the below order,
|
* so these registers always have to been read in the below order,
|
||||||
* 1st post -> 2nd pre, and should be operated in atomic.
|
* 1st post -> 2nd pre, and should be operated in atomic.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flags = spin_lock_irqsave(&g_rtc_lock);
|
|
||||||
|
|
||||||
val = (uint64_t)getreg32(CXD56_RTC0_RTPOSTCNT) << 15;
|
val = (uint64_t)getreg32(CXD56_RTC0_RTPOSTCNT) << 15;
|
||||||
val |= getreg32(CXD56_RTC0_RTPRECNT);
|
val |= getreg32(CXD56_RTC0_RTPRECNT);
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t cxd56_rtc_count(void)
|
||||||
|
{
|
||||||
|
uint64_t val;
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
|
val = cxd56_rtc_count_nolock();
|
||||||
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
|
|
|
@ -92,6 +92,7 @@ extern "C"
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
uint64_t cxd56_rtc_count(void);
|
uint64_t cxd56_rtc_count(void);
|
||||||
|
uint64_t cxd56_rtc_count_nolock(void);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: cxd56_rtc_almcount
|
* Name: cxd56_rtc_almcount
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <nuttx/arch.h>
|
#include <nuttx/arch.h>
|
||||||
#include <nuttx/irq.h>
|
#include <nuttx/irq.h>
|
||||||
#include <nuttx/timers/rtc.h>
|
#include <nuttx/timers/rtc.h>
|
||||||
|
#include <nuttx/spinlock.h>
|
||||||
#include <arch/board/board.h>
|
#include <arch/board/board.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -62,6 +63,10 @@
|
||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_RTC_HIRES
|
||||||
|
static spinlock_t g_rtc_lock = SP_UNLOCKED;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_RTC_ALARM
|
#ifdef CONFIG_RTC_ALARM
|
||||||
static alarmcb_t g_alarmcb;
|
static alarmcb_t g_alarmcb;
|
||||||
static bool rtc_irq_state = false;
|
static bool rtc_irq_state = false;
|
||||||
|
@ -436,7 +441,7 @@ int up_rtc_gettime(struct timespec *tp)
|
||||||
* wrapped-around.
|
* wrapped-around.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
prescaler = getreg32(KINETIS_RTC_TPR);
|
prescaler = getreg32(KINETIS_RTC_TPR);
|
||||||
|
@ -445,7 +450,7 @@ int up_rtc_gettime(struct timespec *tp)
|
||||||
}
|
}
|
||||||
while (prescaler > prescaler2);
|
while (prescaler > prescaler2);
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
|
|
||||||
/* Build seconds + nanoseconds from seconds and prescaler register */
|
/* Build seconds + nanoseconds from seconds and prescaler register */
|
||||||
|
|
||||||
|
@ -479,7 +484,7 @@ int up_rtc_settime(const struct timespec *tp)
|
||||||
seconds = tp->tv_sec;
|
seconds = tp->tv_sec;
|
||||||
prescaler = tp->tv_nsec / (1000000000 / CONFIG_RTC_FREQUENCY);
|
prescaler = tp->tv_nsec / (1000000000 / CONFIG_RTC_FREQUENCY);
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
|
|
||||||
putreg32(0, KINETIS_RTC_SR); /* Disable counter */
|
putreg32(0, KINETIS_RTC_SR); /* Disable counter */
|
||||||
|
|
||||||
|
@ -488,7 +493,7 @@ int up_rtc_settime(const struct timespec *tp)
|
||||||
|
|
||||||
putreg32(RTC_SR_TCE, KINETIS_RTC_SR); /* Re-enable counter */
|
putreg32(RTC_SR_TCE, KINETIS_RTC_SR); /* Re-enable counter */
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -403,11 +403,14 @@ time_t up_rtc_time(void)
|
||||||
#ifdef CONFIG_RTC_HIRES
|
#ifdef CONFIG_RTC_HIRES
|
||||||
int up_rtc_gettime(struct timespec *tp)
|
int up_rtc_gettime(struct timespec *tp)
|
||||||
{
|
{
|
||||||
|
irqstate_t flags;
|
||||||
uint64_t tmp;
|
uint64_t tmp;
|
||||||
uint32_t sec;
|
uint32_t sec;
|
||||||
uint32_t ssec;
|
uint32_t ssec;
|
||||||
uint32_t verify;
|
uint32_t verify;
|
||||||
|
|
||||||
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
|
|
||||||
/* Read the time handling rollover to full seconds */
|
/* Read the time handling rollover to full seconds */
|
||||||
|
|
||||||
do
|
do
|
||||||
|
@ -418,6 +421,8 @@ int up_rtc_gettime(struct timespec *tp)
|
||||||
}
|
}
|
||||||
while (verify != sec);
|
while (verify != sec);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
|
|
||||||
/* Format as a tm */
|
/* Format as a tm */
|
||||||
|
|
||||||
tmp = ((uint64_t)ssec * NSEC_PER_SEC) / 256;
|
tmp = ((uint64_t)ssec * NSEC_PER_SEC) / 256;
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include <nuttx/arch.h>
|
#include <nuttx/arch.h>
|
||||||
#include <nuttx/irq.h>
|
#include <nuttx/irq.h>
|
||||||
#include <nuttx/timers/rtc.h>
|
#include <nuttx/timers/rtc.h>
|
||||||
|
#include <nuttx/spinlock.h>
|
||||||
|
|
||||||
#include <arch/board/board.h>
|
#include <arch/board/board.h>
|
||||||
|
|
||||||
|
@ -60,6 +61,12 @@
|
||||||
|
|
||||||
volatile bool g_rtc_enabled = false;
|
volatile bool g_rtc_enabled = false;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static spinlock_t g_rtc_lock = SP_UNLOCKED;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
@ -247,7 +254,7 @@ int up_rtc_gettime(struct timespec *tp)
|
||||||
* wrapped-around.
|
* wrapped-around.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
prescaler = getreg32(S32K1XX_RTC_TPR);
|
prescaler = getreg32(S32K1XX_RTC_TPR);
|
||||||
|
@ -256,7 +263,7 @@ int up_rtc_gettime(struct timespec *tp)
|
||||||
}
|
}
|
||||||
while (prescaler > prescaler2);
|
while (prescaler > prescaler2);
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
|
|
||||||
/* Build seconds + nanoseconds from seconds and prescaler register */
|
/* Build seconds + nanoseconds from seconds and prescaler register */
|
||||||
|
|
||||||
|
@ -296,7 +303,7 @@ int up_rtc_settime(const struct timespec *ts)
|
||||||
prescaler = 0;
|
prescaler = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
|
|
||||||
s32k1xx_rtc_disable();
|
s32k1xx_rtc_disable();
|
||||||
|
|
||||||
|
@ -305,7 +312,7 @@ int up_rtc_settime(const struct timespec *ts)
|
||||||
|
|
||||||
s32k1xx_rtc_enable();
|
s32k1xx_rtc_enable();
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <nuttx/arch.h>
|
#include <nuttx/arch.h>
|
||||||
#include <nuttx/irq.h>
|
#include <nuttx/irq.h>
|
||||||
#include <nuttx/wqueue.h>
|
#include <nuttx/wqueue.h>
|
||||||
|
#include <nuttx/spinlock.h>
|
||||||
|
|
||||||
#include <arch/board/board.h>
|
#include <arch/board/board.h>
|
||||||
|
|
||||||
|
@ -72,6 +73,8 @@
|
||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
static spinlock_t g_rtc_lock = SP_UNLOCKED;
|
||||||
|
|
||||||
/* Callback to use when the alarm expires */
|
/* Callback to use when the alarm expires */
|
||||||
|
|
||||||
#ifdef CONFIG_RTC_ALARM
|
#ifdef CONFIG_RTC_ALARM
|
||||||
|
@ -654,7 +657,8 @@ int sam_rtc_setalarm(const struct timespec *tp, alarmcb_t callback)
|
||||||
|
|
||||||
/* Is there already something waiting on the ALARM? */
|
/* Is there already something waiting on the ALARM? */
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
|
sched_lock();
|
||||||
if (g_alarmcb == NULL)
|
if (g_alarmcb == NULL)
|
||||||
{
|
{
|
||||||
/* No.. Save the callback function pointer */
|
/* No.. Save the callback function pointer */
|
||||||
|
@ -732,7 +736,8 @@ int sam_rtc_setalarm(const struct timespec *tp, alarmcb_t callback)
|
||||||
ret = OK;
|
ret = OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
|
sched_unlock();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -759,11 +764,13 @@ int up_rtc_gettime(struct timespec *tp)
|
||||||
{
|
{
|
||||||
/* This is a hack to emulate a high resolution rtc using the rtt */
|
/* This is a hack to emulate a high resolution rtc using the rtt */
|
||||||
|
|
||||||
|
irqstate_t flags;
|
||||||
uint32_t rtc_cal;
|
uint32_t rtc_cal;
|
||||||
uint32_t rtc_tim;
|
uint32_t rtc_tim;
|
||||||
uint32_t rtt_val;
|
uint32_t rtt_val;
|
||||||
struct tm t;
|
struct tm t;
|
||||||
|
|
||||||
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
rtc_cal = getreg32(SAM_RTC_CALR);
|
rtc_cal = getreg32(SAM_RTC_CALR);
|
||||||
|
@ -774,6 +781,7 @@ int up_rtc_gettime(struct timespec *tp)
|
||||||
rtc_tim != getreg32(SAM_RTC_TIMR) ||
|
rtc_tim != getreg32(SAM_RTC_TIMR) ||
|
||||||
rtt_val != getreg32(SAM_RTT_VR));
|
rtt_val != getreg32(SAM_RTT_VR));
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
t.tm_sec = rtc_bcd2bin((rtc_tim & RTC_TIMR_SEC_MASK) >>
|
t.tm_sec = rtc_bcd2bin((rtc_tim & RTC_TIMR_SEC_MASK) >>
|
||||||
RTC_TIMR_SEC_SHIFT);
|
RTC_TIMR_SEC_SHIFT);
|
||||||
t.tm_min = rtc_bcd2bin((rtc_tim & RTC_TIMR_MIN_MASK) >>
|
t.tm_min = rtc_bcd2bin((rtc_tim & RTC_TIMR_MIN_MASK) >>
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include <nuttx/net/mii.h>
|
#include <nuttx/net/mii.h>
|
||||||
#include <nuttx/net/ip.h>
|
#include <nuttx/net/ip.h>
|
||||||
#include <nuttx/net/netdev.h>
|
#include <nuttx/net/netdev.h>
|
||||||
|
#include <nuttx/spinlock.h>
|
||||||
|
|
||||||
#if defined(CONFIG_NET_PKT)
|
#if defined(CONFIG_NET_PKT)
|
||||||
# include <nuttx/net/pkt.h>
|
# include <nuttx/net/pkt.h>
|
||||||
|
@ -651,6 +652,7 @@ static uint8_t g_alloc[STM32_ETH_NFREEBUFFERS *
|
||||||
static struct stm32_ethmac_s g_stm32ethmac[STM32_NETHERNET];
|
static struct stm32_ethmac_s g_stm32ethmac[STM32_NETHERNET];
|
||||||
|
|
||||||
#ifdef CONFIG_STM32_ETH_PTP_RTC_HIRES
|
#ifdef CONFIG_STM32_ETH_PTP_RTC_HIRES
|
||||||
|
static spinlock_t g_rtc_lock = SP_UNLOCKED;
|
||||||
volatile bool g_rtc_enabled;
|
volatile bool g_rtc_enabled;
|
||||||
static struct timespec g_stm32_eth_ptp_basetime;
|
static struct timespec g_stm32_eth_ptp_basetime;
|
||||||
#endif
|
#endif
|
||||||
|
@ -3778,10 +3780,10 @@ static void stm32_eth_ptp_convert_rxtime(struct stm32_ethmac_s *priv)
|
||||||
|
|
||||||
/* Sample PTP and CLOCK_REALTIME close to each other */
|
/* Sample PTP and CLOCK_REALTIME close to each other */
|
||||||
|
|
||||||
flags = enter_critical_section();
|
|
||||||
clock_gettime(CLOCK_REALTIME, &realtime);
|
clock_gettime(CLOCK_REALTIME, &realtime);
|
||||||
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
ptptime = stm32_eth_ptp_gettime();
|
ptptime = stm32_eth_ptp_gettime();
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
|
|
||||||
/* Compute how much time has elapsed since packet reception
|
/* Compute how much time has elapsed since packet reception
|
||||||
* and add that to current time.
|
* and add that to current time.
|
||||||
|
@ -4308,7 +4310,10 @@ int up_rtc_initialize(void)
|
||||||
|
|
||||||
int up_rtc_gettime(struct timespec *tp)
|
int up_rtc_gettime(struct timespec *tp)
|
||||||
{
|
{
|
||||||
|
irqstate_t flags;
|
||||||
uint64_t timestamp;
|
uint64_t timestamp;
|
||||||
|
|
||||||
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
timestamp = stm32_eth_ptp_gettime();
|
timestamp = stm32_eth_ptp_gettime();
|
||||||
|
|
||||||
if (timestamp == 0)
|
if (timestamp == 0)
|
||||||
|
@ -4317,12 +4322,14 @@ int up_rtc_gettime(struct timespec *tp)
|
||||||
* Normally we shouldn't end up here because g_rtc_enabled is false.
|
* Normally we shouldn't end up here because g_rtc_enabled is false.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
DEBUGASSERT(!g_rtc_enabled);
|
DEBUGASSERT(!g_rtc_enabled);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptp_to_timespec(timestamp, tp);
|
ptp_to_timespec(timestamp, tp);
|
||||||
clock_timespec_add(tp, &g_stm32_eth_ptp_basetime, tp);
|
clock_timespec_add(tp, &g_stm32_eth_ptp_basetime, tp);
|
||||||
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -4346,6 +4353,9 @@ int up_rtc_settime(const struct timespec *tp)
|
||||||
{
|
{
|
||||||
struct timespec ptptime;
|
struct timespec ptptime;
|
||||||
uint64_t timestamp;
|
uint64_t timestamp;
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
timestamp = stm32_eth_ptp_gettime();
|
timestamp = stm32_eth_ptp_gettime();
|
||||||
|
|
||||||
if (timestamp == 0)
|
if (timestamp == 0)
|
||||||
|
@ -4354,6 +4364,7 @@ int up_rtc_settime(const struct timespec *tp)
|
||||||
* Normally we shouldn't end up here because g_rtc_enabled is false.
|
* Normally we shouldn't end up here because g_rtc_enabled is false.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
DEBUGASSERT(!g_rtc_enabled);
|
DEBUGASSERT(!g_rtc_enabled);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
@ -4365,6 +4376,7 @@ int up_rtc_settime(const struct timespec *tp)
|
||||||
|
|
||||||
ptp_to_timespec(timestamp, &ptptime);
|
ptp_to_timespec(timestamp, &ptptime);
|
||||||
clock_timespec_subtract(tp, &ptptime, &g_stm32_eth_ptp_basetime);
|
clock_timespec_subtract(tp, &ptptime, &g_stm32_eth_ptp_basetime);
|
||||||
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include <nuttx/arch.h>
|
#include <nuttx/arch.h>
|
||||||
#include <nuttx/irq.h>
|
#include <nuttx/irq.h>
|
||||||
#include <nuttx/timers/rtc.h>
|
#include <nuttx/timers/rtc.h>
|
||||||
|
#include <nuttx/spinlock.h>
|
||||||
#include <arch/board/board.h>
|
#include <arch/board/board.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -151,6 +152,8 @@ struct rtc_regvals_s
|
||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
static spinlock_t g_rtc_lock = SP_UNLOCKED;
|
||||||
|
|
||||||
/* Callback to use when the alarm expires */
|
/* Callback to use when the alarm expires */
|
||||||
|
|
||||||
#ifdef CONFIG_RTC_ALARM
|
#ifdef CONFIG_RTC_ALARM
|
||||||
|
@ -524,7 +527,7 @@ time_t up_rtc_time(void)
|
||||||
* interrupts will prevent suspensions and interruptions:
|
* interrupts will prevent suspensions and interruptions:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
|
|
||||||
/* And the following loop will handle any clock rollover events that may
|
/* And the following loop will handle any clock rollover events that may
|
||||||
* happen between samples. Most of the time (like 99.9%), the following
|
* happen between samples. Most of the time (like 99.9%), the following
|
||||||
|
@ -546,7 +549,7 @@ time_t up_rtc_time(void)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
while (cntl < tmp);
|
while (cntl < tmp);
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
|
|
||||||
/* Okay.. the samples should be as close together in time as possible and
|
/* Okay.. the samples should be as close together in time as possible and
|
||||||
* we can be assured that no clock rollover occurred between the samples.
|
* we can be assured that no clock rollover occurred between the samples.
|
||||||
|
@ -593,7 +596,7 @@ int up_rtc_gettime(struct timespec *tp)
|
||||||
* interrupts will prevent suspensions and interruptions:
|
* interrupts will prevent suspensions and interruptions:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
|
|
||||||
/* And the following loop will handle any clock rollover events that may
|
/* And the following loop will handle any clock rollover events that may
|
||||||
* happen between samples. Most of the time (like 99.9%), the following
|
* happen between samples. Most of the time (like 99.9%), the following
|
||||||
|
@ -616,7 +619,7 @@ int up_rtc_gettime(struct timespec *tp)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
while (cntl < tmp);
|
while (cntl < tmp);
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
|
|
||||||
/* Okay.. the samples should be as close together in time as possible and
|
/* Okay.. the samples should be as close together in time as possible and
|
||||||
* we can be assured that no clock rollover occurred between the samples.
|
* we can be assured that no clock rollover occurred between the samples.
|
||||||
|
@ -664,7 +667,7 @@ int up_rtc_settime(const struct timespec *tp)
|
||||||
|
|
||||||
/* Enable write access to the backup domain */
|
/* Enable write access to the backup domain */
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
stm32_pwr_enablebkp(true);
|
stm32_pwr_enablebkp(true);
|
||||||
|
|
||||||
/* Then write the broken out values to the RTC counter and BKP overflow
|
/* Then write the broken out values to the RTC counter and BKP overflow
|
||||||
|
@ -682,7 +685,7 @@ int up_rtc_settime(const struct timespec *tp)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
stm32_pwr_enablebkp(false);
|
stm32_pwr_enablebkp(false);
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -709,7 +712,7 @@ int stm32_rtc_setalarm(const struct timespec *tp, alarmcb_t callback)
|
||||||
uint16_t cr;
|
uint16_t cr;
|
||||||
int ret = -EBUSY;
|
int ret = -EBUSY;
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
|
|
||||||
/* Is there already something waiting on the ALARM? */
|
/* Is there already something waiting on the ALARM? */
|
||||||
|
|
||||||
|
@ -743,7 +746,7 @@ int stm32_rtc_setalarm(const struct timespec *tp, alarmcb_t callback)
|
||||||
ret = OK;
|
ret = OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -769,7 +772,7 @@ int stm32_rtc_cancelalarm(void)
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
int ret = -ENODATA;
|
int ret = -ENODATA;
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
|
|
||||||
if (g_alarmcb != NULL)
|
if (g_alarmcb != NULL)
|
||||||
{
|
{
|
||||||
|
@ -789,7 +792,7 @@ int stm32_rtc_cancelalarm(void)
|
||||||
ret = OK;
|
ret = OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include <nuttx/irq.h>
|
#include <nuttx/irq.h>
|
||||||
#include <nuttx/wqueue.h>
|
#include <nuttx/wqueue.h>
|
||||||
#include <nuttx/compiler.h>
|
#include <nuttx/compiler.h>
|
||||||
|
#include <nuttx/spinlock.h>
|
||||||
#include <arch/board/board.h>
|
#include <arch/board/board.h>
|
||||||
#include <rx65n_rtc.h>
|
#include <rx65n_rtc.h>
|
||||||
#include "renesas_internal.h"
|
#include "renesas_internal.h"
|
||||||
|
@ -103,6 +104,8 @@ struct prd_cbinfo_s
|
||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
static spinlock_t g_rtc_lock = SP_UNLOCKED;
|
||||||
|
|
||||||
#ifdef CONFIG_RTC_ALARM
|
#ifdef CONFIG_RTC_ALARM
|
||||||
/* Callback to use when an EXTI is activated */
|
/* Callback to use when an EXTI is activated */
|
||||||
|
|
||||||
|
@ -461,6 +464,7 @@ int up_rtc_initialize(void)
|
||||||
#if defined(CONFIG_RTC_HIRES)
|
#if defined(CONFIG_RTC_HIRES)
|
||||||
int up_rtc_gettime(struct timespec *tp)
|
int up_rtc_gettime(struct timespec *tp)
|
||||||
{
|
{
|
||||||
|
irqstate_t flags;
|
||||||
uint8_t weekcnt;
|
uint8_t weekcnt;
|
||||||
uint8_t daycnt;
|
uint8_t daycnt;
|
||||||
uint8_t monthcnt;
|
uint8_t monthcnt;
|
||||||
|
@ -476,6 +480,9 @@ int up_rtc_gettime(struct timespec *tp)
|
||||||
uint8_t regval;
|
uint8_t regval;
|
||||||
struct tm t;
|
struct tm t;
|
||||||
|
|
||||||
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
|
sched_lock();
|
||||||
|
|
||||||
if (RTC.RCR2.BIT.START == 0)
|
if (RTC.RCR2.BIT.START == 0)
|
||||||
{
|
{
|
||||||
RTC.RCR2.BIT.START = 1;
|
RTC.RCR2.BIT.START = 1;
|
||||||
|
@ -541,6 +548,9 @@ int up_rtc_gettime(struct timespec *tp)
|
||||||
UNUSED(hrcnt);
|
UNUSED(hrcnt);
|
||||||
UNUSED(mincnt);
|
UNUSED(mincnt);
|
||||||
UNUSED(seccnt);
|
UNUSED(seccnt);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
|
sched_unlock();
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -916,7 +926,7 @@ int rx65n_rtc_setalarm(struct alm_setalarm_s *alminfo)
|
||||||
|
|
||||||
/* Is there already something waiting on the ALARM? */
|
/* Is there already something waiting on the ALARM? */
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
|
|
||||||
/* Save the callback info */
|
/* Save the callback info */
|
||||||
|
|
||||||
|
@ -1051,8 +1061,6 @@ int rx65n_rtc_setalarm(struct alm_setalarm_s *alminfo)
|
||||||
dummy_word = RTC.RYRAR.WORD;
|
dummy_word = RTC.RYRAR.WORD;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtc_dumpregs("New alarm setting");
|
|
||||||
|
|
||||||
/* Enable RTC ALARM interrupt */
|
/* Enable RTC ALARM interrupt */
|
||||||
|
|
||||||
RTC.RCR1.BIT.AIE = 1U;
|
RTC.RCR1.BIT.AIE = 1U;
|
||||||
|
@ -1068,7 +1076,9 @@ int rx65n_rtc_setalarm(struct alm_setalarm_s *alminfo)
|
||||||
/* Set Priority of ALM interrupt */
|
/* Set Priority of ALM interrupt */
|
||||||
|
|
||||||
IPR(RTC, ALM) = _0F_RTC_PRIORITY_LEVEL15;
|
IPR(RTC, ALM) = _0F_RTC_PRIORITY_LEVEL15;
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
|
|
||||||
|
rtc_dumpregs("New alarm setting");
|
||||||
UNUSED(dummy_byte);
|
UNUSED(dummy_byte);
|
||||||
UNUSED(dummy_word);
|
UNUSED(dummy_word);
|
||||||
return OK;
|
return OK;
|
||||||
|
@ -1082,7 +1092,7 @@ int rx65n_rtc_setperiodic(const struct timespec *period,
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
volatile uint8_t regval;
|
volatile uint8_t regval;
|
||||||
uint8_t prd;
|
uint8_t prd;
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
|
|
||||||
/* No.. Save the callback function pointer */
|
/* No.. Save the callback function pointer */
|
||||||
|
|
||||||
|
@ -1116,7 +1126,7 @@ int rx65n_rtc_setperiodic(const struct timespec *period,
|
||||||
/* Set PRD priority level */
|
/* Set PRD priority level */
|
||||||
|
|
||||||
IPR(RTC, PRD) = _0F_RTC_PRIORITY_LEVEL15;
|
IPR(RTC, PRD) = _0F_RTC_PRIORITY_LEVEL15;
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1125,7 +1135,7 @@ int rx65n_rtc_setperiodic(const struct timespec *period,
|
||||||
void rx65n_rtc_set_carry(carrycb_t callback)
|
void rx65n_rtc_set_carry(carrycb_t callback)
|
||||||
{
|
{
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
|
|
||||||
/* No.. Save the callback function pointer */
|
/* No.. Save the callback function pointer */
|
||||||
|
|
||||||
|
@ -1148,7 +1158,7 @@ void rx65n_rtc_set_carry(carrycb_t callback)
|
||||||
IPR(PERIB, INTB176) = 15;
|
IPR(PERIB, INTB176) = 15;
|
||||||
RTC.RCR1.BIT.CIE = 1U;
|
RTC.RCR1.BIT.CIE = 1U;
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1158,7 +1168,7 @@ int rx65n_rtc_cancelalarm(void)
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
int ret = -ENODATA;
|
int ret = -ENODATA;
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
|
|
||||||
/* Cancel the global callback function */
|
/* Cancel the global callback function */
|
||||||
|
|
||||||
|
@ -1176,7 +1186,7 @@ int rx65n_rtc_cancelalarm(void)
|
||||||
rx65n_putreg(0x0, RX65N_RTC_RYRAR);
|
rx65n_putreg(0x0, RX65N_RTC_RYRAR);
|
||||||
ret = OK;
|
ret = OK;
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <nuttx/arch.h>
|
#include <nuttx/arch.h>
|
||||||
#include <nuttx/irq.h>
|
#include <nuttx/irq.h>
|
||||||
#include <nuttx/timers/rtc.h>
|
#include <nuttx/timers/rtc.h>
|
||||||
|
#include <nuttx/spinlock.h>
|
||||||
#include <arch/board/board.h>
|
#include <arch/board/board.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -64,6 +65,10 @@
|
||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_RTC_HIRES
|
||||||
|
static spinlock_t g_rtc_lock = SP_UNLOCKED;
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Data
|
* Public Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
@ -85,14 +90,18 @@ static unsigned long rtc_last;
|
||||||
static unsigned long rtc_read(void)
|
static unsigned long rtc_read(void)
|
||||||
{
|
{
|
||||||
uint64_t tmr = rdtscp();
|
uint64_t tmr = rdtscp();
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
flags = spin_lock_irqsave(&g_rtc_lock);
|
||||||
if (tmr < rtc_last)
|
if (tmr < rtc_last)
|
||||||
{
|
{
|
||||||
tmr += (0xffffffffffffffffull - rtc_last);
|
tmr += (0xffffffffffffffffull - rtc_last);
|
||||||
}
|
}
|
||||||
|
|
||||||
rtc_last = tmr;
|
rtc_last = tmr;
|
||||||
|
spin_unlock_irqrestore(&g_rtc_lock, flags);
|
||||||
tmr = (tmr / (g_x86_64_timer_freq / 1000000ul)) * 1000l;
|
tmr = (tmr / (g_x86_64_timer_freq / 1000000ul)) * 1000l;
|
||||||
|
|
||||||
return tmr;
|
return tmr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue