From: ljsebald <ljs...@us...> - 2023-12-04 12:34:57
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 8d98948f2b6dfc9aedd8a1edd6fb209f300403ff (commit) via 036af84aa28358763ab2e4ee123755ba4b2cd902 (commit) via a96afcc11ecf820293475df23968e6c181a4de6d (commit) from b9b86efd2f32900f3c1725304c53d1ad462ec079 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 8d98948f2b6dfc9aedd8a1edd6fb209f300403ff Author: Falco Girgis <gyr...@gm...> Date: Mon Dec 4 06:34:31 2023 -0600 RTC Date/Time Fix for Negative Unix Timestamps (#394) * First attempt at making RTC driver robust - Fixing time_t over/underflow for RTC API - Moved a bunch of private stuff that was polluting the global API into the .c file - Fixed up documentation in a few places, added more info on error conditions * Fixed all issues with date/time negatives/overflow - Had a precision issue with getting the current unix seconds where a subtraction that should've been done on an int64_t was done on a uint32_t, freaking out upon negatives - Had a precision issue with setting the current unix seconds where the updated boot time did a similar subtraction which got truncated as a uint32_t rather than an int64_t commit 036af84aa28358763ab2e4ee123755ba4b2cd902 Author: Falco Girgis <gyr...@gm...> Date: Sun Dec 3 23:22:10 2023 -0600 Doxygen GitHub link (#404) * Doxygen Layout Path Fix - Still wasn't the correct $(KOS_BASE) relative path. commit a96afcc11ecf820293475df23968e6c181a4de6d Author: Falco Girgis <gyr...@gm...> Date: Sun Dec 3 23:16:15 2023 -0600 Changed Doxygen to use $(KOS_BASE) for Navigator Layout Path (#403) * Changed Doxygen layout file to use KOS ENV path - Was previously using a relative path which would screw up depending on where Doxygen was run. ----------------------------------------------------------------------- Summary of changes: doc/Doxyfile | 2 +- kernel/arch/dreamcast/include/arch/rtc.h | 49 +++----------------- kernel/arch/dreamcast/kernel/rtc.c | 77 +++++++++++++++++++++++++++----- 3 files changed, 73 insertions(+), 55 deletions(-) diff --git a/doc/Doxyfile b/doc/Doxyfile index 2f7c77a..290d332 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -786,7 +786,7 @@ FILE_VERSION_FILTER = # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. -LAYOUT_FILE = pages/DoxygenLayout.xml +LAYOUT_FILE = $(KOS_BASE)/doc/pages/DoxygenLayout.xml # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib diff --git a/kernel/arch/dreamcast/include/arch/rtc.h b/kernel/arch/dreamcast/include/arch/rtc.h index a68f7cf..9951cf4 100644 --- a/kernel/arch/dreamcast/include/arch/rtc.h +++ b/kernel/arch/dreamcast/include/arch/rtc.h @@ -59,48 +59,6 @@ __BEGIN_DECLS \sa wdt */ -/** \defgroup rtc_regs Registers - \brief RTC registers - \ingroup rtc - - All registers are located on the G2 BUS and must be read and - written to as full 32-byte values. -@{*/ - -/** \brief High 16-bit timestamp value - - 32-bit register containing the upper 16-bits of - the 32-bit timestamp in seconds. Only the lower 16-bits - are valid. - - \note Writing to this register will lock the timestamp registers. - */ -#define RTC_TIMESTAMP_HIGH_ADDR 0xa0710000 - -/** \brief Low 16-bit timestamp value - - 32-bit register containing the lower 16-bits of - the 32-bit timestamp in seconds. Only the lower 16-bits - are valid. - */ -#define RTC_TIMESTAMP_LOW_ADDR 0xa0710004 - -/** \brief Timestamp control register - - All fields are reserved except for #RTC_CTRL_WRITE_EN, - which is write-only. - */ -#define RTC_CTRL_ADDR 0xa0710008 -/** -@} */ - -/** \brief Timestamp write enable - - #RTC_CTRL_ADDR value to be written in order to unlock - writing to the timestamp registers. -*/ -#define RTC_CTRL_WRITE_EN (1 << 0) - /** \brief Get the current date/time. \ingroup rtc @@ -114,13 +72,18 @@ __BEGIN_DECLS */ time_t rtc_unix_secs(void); -/** \brief Get the current date/time. +/** \brief Set the current date/time. \ingroup rtc This function sets the current RTC value as a standard UNIX timestamp (with an epoch of January 1, 1970 00:00). This is assumed to be in the timezone of the user (as the RTC does not support timezones). + \warning + This function may fail! Since `time_t` is typically 64-bit while the RTC + uses a 32-bit timestamp (which also has a different epoch), not all + `time_t` values can be represented within the RTC! + \param time Unix timestamp to set the current time to \return 0 for success or -1 for failure diff --git a/kernel/arch/dreamcast/kernel/rtc.c b/kernel/arch/dreamcast/kernel/rtc.c index 53564b6..db83694 100644 --- a/kernel/arch/dreamcast/kernel/rtc.c +++ b/kernel/arch/dreamcast/kernel/rtc.c @@ -7,7 +7,8 @@ Copyright (C) 2023 Megavolt85 */ -/* Real-Time Clock (RTC) support +/* + Real-Time Clock (RTC) Support The functions in here return various info about the real-world time and date stored in the machine. The general process here is to retrieve @@ -28,16 +29,64 @@ #include <arch/timer.h> #include <dc/g2bus.h> #include <stdint.h> +#include <assert.h> -#define RTC_UNIX_EPOCH_DELTA 631152000 /* Twenty years in seconds */ -#define RTC_RETRY_COUNT 3 /* # of times to repeat on bad access */ +/* + High 16-bit Timestamp Value + + 32-bit register containing the upper 16-bits of + the 32-bit timestamp in seconds. Only the lower 16-bits + are valid. + + Writing to this register will lock the timestamp registers. +*/ +#define RTC_TIMESTAMP_HIGH_ADDR 0xa0710000 + +/* + Low 16-bit Timestamp Value + + 32-bit register containing the lower 16-bits of + the 32-bit timestamp in seconds. Only the lower 16-bits + are valid. +*/ +#define RTC_TIMESTAMP_LOW_ADDR 0xa0710004 + +/* + Timestamp Control Register + + All fields are reserved except for RTC_CTRL_WRITE_EN, + which is write-only. +*/ +#define RTC_CTRL_ADDR 0xa0710008 + +/* + Timestamp Write Enable + + RTC_CTRL_ADDR field to be written in order to unlock + writing to the timestamp registers. +*/ +#define RTC_CTRL_WRITE_EN (1 << 0) + +/* + Second Delta between Sega and Unix Epochs + + Twenty years in seconds. +*/ +#define RTC_UNIX_EPOCH_DELTA 631152000 + +/* + # of Read/Write Retry Attempts + + To ensure a coherent, race-free read/write operation. +*/ +#define RTC_RETRY_COUNT 3 /* The boot time; we'll save this in rtc_init() */ static time_t boot_time = 0; /* Returns the date/time value as a UNIX epoch time stamp */ time_t rtc_unix_secs(void) { - uint32 rtcold, rtcnew; + uint32_t rtcold, rtcnew; int i; /* Try several times to make sure we don't read one value, then the @@ -60,10 +109,7 @@ time_t rtc_unix_secs(void) { break; } - /* Subtract out 20 years */ - rtcnew = rtcnew - RTC_UNIX_EPOCH_DELTA; - - return rtcnew; + return rtcnew - RTC_UNIX_EPOCH_DELTA; } /* Sets the date/time value from a UNIX epoch time stamp, @@ -72,9 +118,16 @@ int rtc_set_unix_secs(time_t secs) { int result = 0; uint32_t rtcnew; int i; + uint32_t s, ms; /* Adjust by 20 years to get to the expected RTC time. */ - const uint32_t adjusted = secs + RTC_UNIX_EPOCH_DELTA; + const time_t adjusted_time = secs + RTC_UNIX_EPOCH_DELTA; + const uint32_t adjusted = (const uint32_t)adjusted_time; + + /* Protect against underflowing or overflowing our 32-bit timestamp. */ + if(adjusted_time < 0 || adjusted_time > UINT32_MAX) + return -1; + /* Enable writing by setting LSB of control */ g2_write_32(RTC_CTRL_ADDR, RTC_CTRL_WRITE_EN); @@ -94,6 +147,9 @@ int rtc_set_unix_secs(time_t secs) { break; } + /* Disable further writing by clearing LSB of control */ + g2_write_32(RTC_CTRL_ADDR, 0); + /* Signify failure if the fetched time never matched the time we attempted to set. */ if(i == RTC_RETRY_COUNT) @@ -102,9 +158,8 @@ int rtc_set_unix_secs(time_t secs) { /* We have to update the boot time now as well, subtracting the amount of time that has elapsed since boot from the new time we've just set. */ - uint32 s, ms; timer_ms_gettime(&s, &ms); - boot_time = rtcnew - RTC_UNIX_EPOCH_DELTA - s; + boot_time = ((time_t)rtcnew - RTC_UNIX_EPOCH_DELTA) - s; return result; } hooks/post-receive -- A pseudo Operating System for the Dreamcast. |