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:
hujun5 2024-12-28 11:33:42 +08:00 committed by Xiang Xiao
parent 89455bc9a1
commit 57ca4e1789
10 changed files with 108 additions and 37 deletions

View file

@ -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;

View file

@ -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

View file

@ -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;
} }

View file

@ -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;

View file

@ -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;
} }

View file

@ -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) >>

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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;
} }