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
int up_rtc_gettime(struct timespec *tp)
{
irqstate_t flags;
uint64_t count;
count = cxd56_rtc_count();
flags = spin_lock_irqsave(&g_rtc_lock);
count = cxd56_rtc_count_nolock();
count += g_rtc_save->offset;
spin_unlock_irqrestore(&g_rtc_lock, flags);
/* 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;
irqstate_t flags;
/* The pre register is latched with reading the post rtcounter register,
* so these registers always have to been read in the below order,
* 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 |= 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);
return val;

View file

@ -92,6 +92,7 @@ extern "C"
****************************************************************************/
uint64_t cxd56_rtc_count(void);
uint64_t cxd56_rtc_count_nolock(void);
/****************************************************************************
* Name: cxd56_rtc_almcount

View file

@ -28,6 +28,7 @@
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/timers/rtc.h>
#include <nuttx/spinlock.h>
#include <arch/board/board.h>
#include <stdlib.h>
@ -62,6 +63,10 @@
* Private Data
****************************************************************************/
#ifdef CONFIG_RTC_HIRES
static spinlock_t g_rtc_lock = SP_UNLOCKED;
#endif
#ifdef CONFIG_RTC_ALARM
static alarmcb_t g_alarmcb;
static bool rtc_irq_state = false;
@ -436,7 +441,7 @@ int up_rtc_gettime(struct timespec *tp)
* wrapped-around.
*/
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_rtc_lock);
do
{
prescaler = getreg32(KINETIS_RTC_TPR);
@ -445,7 +450,7 @@ int up_rtc_gettime(struct timespec *tp)
}
while (prescaler > prescaler2);
leave_critical_section(flags);
spin_unlock_irqrestore(&g_rtc_lock, flags);
/* Build seconds + nanoseconds from seconds and prescaler register */
@ -479,7 +484,7 @@ int up_rtc_settime(const struct timespec *tp)
seconds = tp->tv_sec;
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 */
@ -488,7 +493,7 @@ int up_rtc_settime(const struct timespec *tp)
putreg32(RTC_SR_TCE, KINETIS_RTC_SR); /* Re-enable counter */
leave_critical_section(flags);
spin_unlock_irqrestore(&g_rtc_lock, flags);
return OK;
}

View file

@ -403,11 +403,14 @@ time_t up_rtc_time(void)
#ifdef CONFIG_RTC_HIRES
int up_rtc_gettime(struct timespec *tp)
{
irqstate_t flags;
uint64_t tmp;
uint32_t sec;
uint32_t ssec;
uint32_t verify;
flags = spin_lock_irqsave(&g_rtc_lock);
/* Read the time handling rollover to full seconds */
do
@ -418,6 +421,8 @@ int up_rtc_gettime(struct timespec *tp)
}
while (verify != sec);
spin_unlock_irqrestore(&g_rtc_lock, flags);
/* Format as a tm */
tmp = ((uint64_t)ssec * NSEC_PER_SEC) / 256;

View file

@ -37,6 +37,7 @@
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/timers/rtc.h>
#include <nuttx/spinlock.h>
#include <arch/board/board.h>
@ -60,6 +61,12 @@
volatile bool g_rtc_enabled = false;
/****************************************************************************
* Private Data
****************************************************************************/
static spinlock_t g_rtc_lock = SP_UNLOCKED;
/****************************************************************************
* Private Functions
****************************************************************************/
@ -247,7 +254,7 @@ int up_rtc_gettime(struct timespec *tp)
* wrapped-around.
*/
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_rtc_lock);
do
{
prescaler = getreg32(S32K1XX_RTC_TPR);
@ -256,7 +263,7 @@ int up_rtc_gettime(struct timespec *tp)
}
while (prescaler > prescaler2);
leave_critical_section(flags);
spin_unlock_irqrestore(&g_rtc_lock, flags);
/* Build seconds + nanoseconds from seconds and prescaler register */
@ -296,7 +303,7 @@ int up_rtc_settime(const struct timespec *ts)
prescaler = 0;
#endif
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_rtc_lock);
s32k1xx_rtc_disable();
@ -305,7 +312,7 @@ int up_rtc_settime(const struct timespec *ts)
s32k1xx_rtc_enable();
leave_critical_section(flags);
spin_unlock_irqrestore(&g_rtc_lock, flags);
return OK;
}

View file

@ -34,6 +34,7 @@
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/wqueue.h>
#include <nuttx/spinlock.h>
#include <arch/board/board.h>
@ -72,6 +73,8 @@
* Private Data
****************************************************************************/
static spinlock_t g_rtc_lock = SP_UNLOCKED;
/* Callback to use when the alarm expires */
#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? */
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_rtc_lock);
sched_lock();
if (g_alarmcb == NULL)
{
/* No.. Save the callback function pointer */
@ -732,7 +736,8 @@ int sam_rtc_setalarm(const struct timespec *tp, alarmcb_t callback)
ret = OK;
}
leave_critical_section(flags);
spin_unlock_irqrestore(&g_rtc_lock, flags);
sched_unlock();
return ret;
}
#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 */
irqstate_t flags;
uint32_t rtc_cal;
uint32_t rtc_tim;
uint32_t rtt_val;
struct tm t;
flags = spin_lock_irqsave(&g_rtc_lock);
do
{
rtc_cal = getreg32(SAM_RTC_CALR);
@ -774,6 +781,7 @@ int up_rtc_gettime(struct timespec *tp)
rtc_tim != getreg32(SAM_RTC_TIMR) ||
rtt_val != getreg32(SAM_RTT_VR));
spin_unlock_irqrestore(&g_rtc_lock, flags);
t.tm_sec = rtc_bcd2bin((rtc_tim & RTC_TIMR_SEC_MASK) >>
RTC_TIMR_SEC_SHIFT);
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/ip.h>
#include <nuttx/net/netdev.h>
#include <nuttx/spinlock.h>
#if defined(CONFIG_NET_PKT)
# 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];
#ifdef CONFIG_STM32_ETH_PTP_RTC_HIRES
static spinlock_t g_rtc_lock = SP_UNLOCKED;
volatile bool g_rtc_enabled;
static struct timespec g_stm32_eth_ptp_basetime;
#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 */
flags = enter_critical_section();
clock_gettime(CLOCK_REALTIME, &realtime);
flags = spin_lock_irqsave(&g_rtc_lock);
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
* and add that to current time.
@ -4308,7 +4310,10 @@ int up_rtc_initialize(void)
int up_rtc_gettime(struct timespec *tp)
{
irqstate_t flags;
uint64_t timestamp;
flags = spin_lock_irqsave(&g_rtc_lock);
timestamp = stm32_eth_ptp_gettime();
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.
*/
spin_unlock_irqrestore(&g_rtc_lock, flags);
DEBUGASSERT(!g_rtc_enabled);
return -EBUSY;
}
ptp_to_timespec(timestamp, tp);
clock_timespec_add(tp, &g_stm32_eth_ptp_basetime, tp);
spin_unlock_irqrestore(&g_rtc_lock, flags);
return OK;
}
@ -4346,6 +4353,9 @@ int up_rtc_settime(const struct timespec *tp)
{
struct timespec ptptime;
uint64_t timestamp;
irqstate_t flags;
flags = spin_lock_irqsave(&g_rtc_lock);
timestamp = stm32_eth_ptp_gettime();
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.
*/
spin_unlock_irqrestore(&g_rtc_lock, flags);
DEBUGASSERT(!g_rtc_enabled);
return -EBUSY;
}
@ -4365,6 +4376,7 @@ int up_rtc_settime(const struct timespec *tp)
ptp_to_timespec(timestamp, &ptptime);
clock_timespec_subtract(tp, &ptptime, &g_stm32_eth_ptp_basetime);
spin_unlock_irqrestore(&g_rtc_lock, flags);
return OK;
}

View file

@ -46,6 +46,7 @@
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/timers/rtc.h>
#include <nuttx/spinlock.h>
#include <arch/board/board.h>
#include <stdlib.h>
@ -151,6 +152,8 @@ struct rtc_regvals_s
* Private Data
****************************************************************************/
static spinlock_t g_rtc_lock = SP_UNLOCKED;
/* Callback to use when the alarm expires */
#ifdef CONFIG_RTC_ALARM
@ -524,7 +527,7 @@ time_t up_rtc_time(void)
* 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
* 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);
leave_critical_section(flags);
spin_unlock_irqrestore(&g_rtc_lock, flags);
/* 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.
@ -593,7 +596,7 @@ int up_rtc_gettime(struct timespec *tp)
* 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
* 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);
leave_critical_section(flags);
spin_unlock_irqrestore(&g_rtc_lock, flags);
/* 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.
@ -664,7 +667,7 @@ int up_rtc_settime(const struct timespec *tp)
/* Enable write access to the backup domain */
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_rtc_lock);
stm32_pwr_enablebkp(true);
/* 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
stm32_pwr_enablebkp(false);
leave_critical_section(flags);
spin_unlock_irqrestore(&g_rtc_lock, flags);
return OK;
}
@ -709,7 +712,7 @@ int stm32_rtc_setalarm(const struct timespec *tp, alarmcb_t callback)
uint16_t cr;
int ret = -EBUSY;
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_rtc_lock);
/* 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;
}
leave_critical_section(flags);
spin_unlock_irqrestore(&g_rtc_lock, flags);
return ret;
}
@ -769,7 +772,7 @@ int stm32_rtc_cancelalarm(void)
irqstate_t flags;
int ret = -ENODATA;
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_rtc_lock);
if (g_alarmcb != NULL)
{
@ -789,7 +792,7 @@ int stm32_rtc_cancelalarm(void)
ret = OK;
}
leave_critical_section(flags);
spin_unlock_irqrestore(&g_rtc_lock, flags);
return ret;
}

View file

@ -35,6 +35,7 @@
#include <nuttx/irq.h>
#include <nuttx/wqueue.h>
#include <nuttx/compiler.h>
#include <nuttx/spinlock.h>
#include <arch/board/board.h>
#include <rx65n_rtc.h>
#include "renesas_internal.h"
@ -103,6 +104,8 @@ struct prd_cbinfo_s
* Private Data
****************************************************************************/
static spinlock_t g_rtc_lock = SP_UNLOCKED;
#ifdef CONFIG_RTC_ALARM
/* Callback to use when an EXTI is activated */
@ -461,6 +464,7 @@ int up_rtc_initialize(void)
#if defined(CONFIG_RTC_HIRES)
int up_rtc_gettime(struct timespec *tp)
{
irqstate_t flags;
uint8_t weekcnt;
uint8_t daycnt;
uint8_t monthcnt;
@ -476,6 +480,9 @@ int up_rtc_gettime(struct timespec *tp)
uint8_t regval;
struct tm t;
flags = spin_lock_irqsave(&g_rtc_lock);
sched_lock();
if (RTC.RCR2.BIT.START == 0)
{
RTC.RCR2.BIT.START = 1;
@ -541,6 +548,9 @@ int up_rtc_gettime(struct timespec *tp)
UNUSED(hrcnt);
UNUSED(mincnt);
UNUSED(seccnt);
spin_unlock_irqrestore(&g_rtc_lock, flags);
sched_unlock();
return OK;
}
#endif
@ -916,7 +926,7 @@ int rx65n_rtc_setalarm(struct alm_setalarm_s *alminfo)
/* Is there already something waiting on the ALARM? */
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_rtc_lock);
/* Save the callback info */
@ -1051,8 +1061,6 @@ int rx65n_rtc_setalarm(struct alm_setalarm_s *alminfo)
dummy_word = RTC.RYRAR.WORD;
}
rtc_dumpregs("New alarm setting");
/* Enable RTC ALARM interrupt */
RTC.RCR1.BIT.AIE = 1U;
@ -1068,7 +1076,9 @@ int rx65n_rtc_setalarm(struct alm_setalarm_s *alminfo)
/* Set Priority of ALM interrupt */
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_word);
return OK;
@ -1082,7 +1092,7 @@ int rx65n_rtc_setperiodic(const struct timespec *period,
irqstate_t flags;
volatile uint8_t regval;
uint8_t prd;
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_rtc_lock);
/* No.. Save the callback function pointer */
@ -1116,7 +1126,7 @@ int rx65n_rtc_setperiodic(const struct timespec *period,
/* Set PRD priority level */
IPR(RTC, PRD) = _0F_RTC_PRIORITY_LEVEL15;
leave_critical_section(flags);
spin_unlock_irqrestore(&g_rtc_lock, flags);
return OK;
}
#endif
@ -1125,7 +1135,7 @@ int rx65n_rtc_setperiodic(const struct timespec *period,
void rx65n_rtc_set_carry(carrycb_t callback)
{
irqstate_t flags;
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_rtc_lock);
/* No.. Save the callback function pointer */
@ -1148,7 +1158,7 @@ void rx65n_rtc_set_carry(carrycb_t callback)
IPR(PERIB, INTB176) = 15;
RTC.RCR1.BIT.CIE = 1U;
leave_critical_section(flags);
spin_unlock_irqrestore(&g_rtc_lock, flags);
}
#endif
@ -1158,7 +1168,7 @@ int rx65n_rtc_cancelalarm(void)
irqstate_t flags;
int ret = -ENODATA;
flags = enter_critical_section();
flags = spin_lock_irqsave(&g_rtc_lock);
/* Cancel the global callback function */
@ -1176,7 +1186,7 @@ int rx65n_rtc_cancelalarm(void)
rx65n_putreg(0x0, RX65N_RTC_RYRAR);
ret = OK;
leave_critical_section(flags);
spin_unlock_irqrestore(&g_rtc_lock, flags);
return ret;
}

View file

@ -28,6 +28,7 @@
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/timers/rtc.h>
#include <nuttx/spinlock.h>
#include <arch/board/board.h>
#include <stdlib.h>
@ -64,6 +65,10 @@
* Private Data
****************************************************************************/
#ifdef CONFIG_RTC_HIRES
static spinlock_t g_rtc_lock = SP_UNLOCKED;
#endif
/****************************************************************************
* Public Data
****************************************************************************/
@ -85,14 +90,18 @@ static unsigned long rtc_last;
static unsigned long rtc_read(void)
{
uint64_t tmr = rdtscp();
irqstate_t flags;
flags = spin_lock_irqsave(&g_rtc_lock);
if (tmr < rtc_last)
{
tmr += (0xffffffffffffffffull - rtc_last);
}
rtc_last = tmr;
spin_unlock_irqrestore(&g_rtc_lock, flags);
tmr = (tmr / (g_x86_64_timer_freq / 1000000ul)) * 1000l;
return tmr;
}