Skip to content

Commit 532c40a

Browse files
committed
rtc: Add settimeofday()
1 parent b1ce3b1 commit 532c40a

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

teensy3/pins_teensy.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,36 @@ int _gettimeofday(struct timeval *tv, void *ignore)
404404
}
405405
}
406406

407+
__attribute__((weak))
408+
int settimeofday(const struct timeval *const tv,
409+
const struct timezone *const tz __attribute__((unused))) {
410+
// Disable time counter
411+
RTC_SR = 0;
412+
413+
// Notes:
414+
// * The type of tv_usec is suseconds_t, range is [-1, 1000000]
415+
// * There are 32768 ticks per 1,000,000 microseconds; that's where 512/15625
416+
// comes from, it's 32768/1000000 in lowest terms
417+
// Refs:
418+
// * https://pubs.opengroup.org/onlinepubs/007904975/basedefs/sys/time.h.html
419+
// * https://pubs.opengroup.org/onlinepubs/007904975/basedefs/sys/types.h.html
420+
uint32_t sec = (uint32_t)tv->tv_sec;
421+
uint32_t usec = (uint32_t)tv->tv_usec;
422+
if (usec == 1000000) {
423+
sec++;
424+
usec = 0;
425+
} else if (usec == UINT32_MAX) {
426+
sec--;
427+
usec = 999999;
428+
}
429+
RTC_TPR = ((usec << 9) / 15625) & 0x7fff;
430+
RTC_TSR = sec;
431+
432+
// Enable time counter
433+
RTC_SR = RTC_SR_TCE;
434+
return 0;
435+
}
436+
407437
#else
408438

409439
unsigned long rtc_get(void) { return 0; }
@@ -413,6 +443,12 @@ void rtc_compensate(int adjust) { }
413443
__attribute__((weak))
414444
int _gettimeofday(struct timeval *tv, void *ignore) { return -1; }
415445

446+
__attribute__((weak))
447+
int settimeofday(const struct timeval *const tv __attribute__((unused)),
448+
const struct timezone *const tz __attribute__((unused))) {
449+
return -1;
450+
}
451+
416452
#endif
417453

418454

teensy4/rtc.c

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
#include "imxrt.h"
3232
#include "debug/printf.h"
33-
#include <sys/time.h> // for struct timeval
33+
#include <sys/time.h> // for struct timeval and struct timezone
3434

3535
unsigned long rtc_get(void)
3636
{
@@ -88,3 +88,50 @@ int _gettimeofday(struct timeval *tv, void *ignore __attribute__((unused)))
8888
lo1 = lo2;
8989
}
9090
}
91+
92+
__attribute__((weak))
93+
int settimeofday(const struct timeval *const tv,
94+
const struct timezone *const tz __attribute__((unused))) {
95+
// Stop the RTC
96+
SNVS_HPCR &= ~(SNVS_HPCR_RTC_EN | SNVS_HPCR_HP_TS);
97+
while (SNVS_HPCR & SNVS_HPCR_RTC_EN) {
98+
// Wait
99+
}
100+
101+
// Stop the SRTC
102+
SNVS_LPCR &= ~SNVS_LPCR_SRTC_ENV;
103+
while (SNVS_LPCR & SNVS_LPCR_SRTC_ENV) {
104+
// Wait
105+
}
106+
107+
// Set the SRTC
108+
// Notes:
109+
// * The type of tv_usec is suseconds_t, range is [-1, 1000000]
110+
// * There are 32768 ticks per 1,000,000 microseconds; that's where 512/15625
111+
// comes from, it's 32768/1000000 in lowest terms
112+
// Refs:
113+
// * https://pubs.opengroup.org/onlinepubs/007904975/basedefs/sys/time.h.html
114+
// * https://pubs.opengroup.org/onlinepubs/007904975/basedefs/sys/types.h.html
115+
uint32_t sec = (uint32_t)tv->tv_sec;
116+
uint32_t usec = (uint32_t)tv->tv_usec;
117+
if (usec == 1000000) {
118+
sec++;
119+
usec = 0;
120+
} else if (usec == UINT32_MAX) {
121+
sec--;
122+
usec = 999999;
123+
}
124+
SNVS_LPSRTCLR = (sec << 15) | (((usec << 9) / 15625) & 0x7fff);
125+
SNVS_LPSRTCMR = (sec >> 17) & 0x7fff;
126+
127+
// Start the SRTC
128+
SNVS_LPCR |= SNVS_LPCR_SRTC_ENV;
129+
while (!(SNVS_LPCR & SNVS_LPCR_SRTC_ENV)) {
130+
// Wait
131+
}
132+
133+
// Start the RTC and sync it to the SRTC
134+
SNVS_HPCR |= SNVS_HPCR_RTC_EN | SNVS_HPCR_HP_TS;
135+
136+
return 0;
137+
}

0 commit comments

Comments
 (0)