Skip to content

Commit

Permalink
up_rtc_gettime: add spinlock to protect up_rtc_gettime
Browse files Browse the repository at this point in the history
reason:
We have removed the critical section protection
for the up_rtc_gettime function in common code.

Signed-off-by: hujun5 <hujun5@xiaomi.com>
  • Loading branch information
hujun260 committed Jan 3, 2025
1 parent f0137d5 commit 7220acd
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 35 deletions.
22 changes: 17 additions & 5 deletions arch/arm/src/cxd56xx/cxd56_rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -399,9 +399,12 @@ 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;

/* Then we can save the time in seconds and fractional seconds. */
Expand All @@ -410,6 +413,8 @@ int up_rtc_gettime(struct timespec *tp)
tp->tv_nsec = (count % CONFIG_RTC_FREQUENCY) *
(NSEC_PER_SEC / CONFIG_RTC_FREQUENCY);

spin_unlock_irqrestore(&g_rtc_lock, flags);

rtc_dumptime(tp, "Getting time");

return OK;
Expand Down Expand Up @@ -477,21 +482,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;
Expand Down
1 change: 1 addition & 0 deletions arch/arm/src/cxd56xx/cxd56_rtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ extern "C"
****************************************************************************/

uint64_t cxd56_rtc_count(void);
uint64_t cxd56_rtc_count_nolock(void);

/****************************************************************************
* Name: cxd56_rtc_almcount
Expand Down
13 changes: 9 additions & 4 deletions arch/arm/src/kinetis/kinetis_rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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 */

Expand Down Expand Up @@ -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 */

Expand All @@ -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;
}
Expand Down
4 changes: 4 additions & 0 deletions arch/arm/src/max326xx/max32660/max32660_rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -424,6 +427,7 @@ int up_rtc_gettime(struct timespec *tp)

tp->tv_sec = sec;
tp->tv_nsec = (long)tmp;
spin_unlock_irqrestore(&g_rtc_lock, flags);

return OK;
}
Expand Down
15 changes: 11 additions & 4 deletions arch/arm/src/s32k1xx/s32k1xx_rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand All @@ -60,6 +61,12 @@

volatile bool g_rtc_enabled = false;

/****************************************************************************
* Private Data
****************************************************************************/

static spinlock_t g_rtc_lock = SP_UNLOCKED;

/****************************************************************************
* Private Functions
****************************************************************************/
Expand Down Expand Up @@ -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);
Expand All @@ -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 */

Expand Down Expand Up @@ -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();

Expand All @@ -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;
}
Expand Down
14 changes: 12 additions & 2 deletions arch/arm/src/sam34/sam_rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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
Expand All @@ -759,11 +764,14 @@ 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);
sched_lock();
do
{
rtc_cal = getreg32(SAM_RTC_CALR);
Expand Down Expand Up @@ -794,6 +802,8 @@ int up_rtc_gettime(struct timespec *tp)
tp->tv_nsec = (((rtt_val - g_rtt_offset) & (CONFIG_RTC_FREQUENCY - 1)) *
1000000000ull) / CONFIG_RTC_FREQUENCY;

spin_unlock_irqrestore(&g_rtc_lock, flags);
sched_unlock();
return OK;
}
#endif
Expand Down
16 changes: 14 additions & 2 deletions arch/arm/src/stm32/stm32_eth.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand All @@ -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;
}
Expand All @@ -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)
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down
Loading

0 comments on commit 7220acd

Please sign in to comment.