Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

up_rtc_gettime: add spinlock to protect up_rtc_gettime #15413

Merged
merged 3 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions arch/arm/src/cxd56xx/cxd56_rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */

Expand Down Expand Up @@ -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;
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
5 changes: 5 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 @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions arch/arm/src/rp23xx/rp23xx_pio.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@
#define hw_claim_lock() spin_lock_irqsave(&pio_lock)
#define hw_claim_unlock(save) spin_unlock_irqrestore(&pio_lock, save)
#else
#define hw_claim_lock() spin_lock_irqsave(NULL)
#define hw_claim_unlock(save) spin_unlock_irqrestore(NULL, save)
#define hw_claim_lock() up_irq_save()
#define hw_claim_unlock(save) up_irq_restore(save)
#endif

/****************************************************************************
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
12 changes: 10 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,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);
Expand All @@ -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) >>
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
Loading