Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Jul 2020 12:15:28 -0300
From:      "Dr. Rolf Jansen" <freebsd-rj@obsigna.com>
To:        freebsd-arm@freebsd.org
Subject:   Re: DS3231 on BeagleBone Black with FreeBSD 13-CURRENT exactly 20 h off  backwards
Message-ID:  <CECBFBC7-6C63-4762-9A55-BE84DA53BBD2@obsigna.com>
In-Reply-To: <3BE2A8B4-AD53-4DFE-8C38-D5BB4063CFE9@obsigna.com>
References:  <3BE2A8B4-AD53-4DFE-8C38-D5BB4063CFE9@obsigna.com>

next in thread | previous in thread | raw e-mail | index | archive | help
> Am 15.07.2020 um 09:52 schrieb Dr. Rolf Jansen =
<freebsd-rj@obsigna.com>:
>=20
> I added a DS3231 module to the i2c2 bus of the BBB running 13-CURRENT. =
Everything  work fine, except that when I set a time in the range of =
20:00 to 24:00 UTC, then on starting up the RTC reports a date/time of =
exactly 20 hours off backwards. While, when I set a time in the range =
from 0:00 to 19:59 UTC, it would be correctly stored by the RTC.
>=20
> Looking at the Maxim DS3231 datasheet =
(https://datasheets.maximintegrated.com/en/ds/DS3231.pdf#page=3D11 =
<https://datasheets.maximintegrated.com/en/ds/DS3231.pdf#page=3D11>), it =
might be that something gets mixed-up when setting bits 5 and 6 of the =
hours register. In the history of ds3231.c, I saw that 24 hour mode is =
not more forced anymore. Perhaps an unresolved ambiguity was introduced =
by this change.
>=20
> BTW: the following looks strange:
>=20
> =
https://github.com/freebsd/freebsd/blob/b2d136be8c26e5efaf82b7bb25432207a6=
82e250/sys/dev/iicbus/ds3231.c#L526 =
<https://github.com/freebsd/freebsd/blob/b2d136be8c26e5efaf82b7bb25432207a=
682e250/sys/dev/iicbus/ds3231.c#L526>
>=20
> This would add 256 instead of 100 when rolling over the century, =
really? On real world systems this will let to a Year-2100 problem, =
better we solve this quickly, since the time is running, and 80 years =
compares to nothing on the geologic time scale :-D

For the time being I resolved the issue for me, by completely dropping =
AM/PM support - I don=E2=80=99t need it, and I anyway always need to =
remember that AM means (Am Morgen :-).

DS3231_HOUR_MASK_24HR is definitely wrong, since this prevents the =
setting of times above 20 h. Reading said data sheet, I am almost sure, =
that DS3231_HOUR_MASK_24HR must be the same as DS3231_HOUR_MASK_12HR =3D =
0x3f.


# svn diff https://svn.freebsd.org/base/head/sys/dev/iicbus/ds3231.c =
./ds3231.c
Index: ds3231.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- ds3231.c	(revision 363224)
+++ ds3231.c	(working copy)
@@ -62,7 +62,6 @@
 	uint16_t	sc_addr;	/* DS3231 slave address. */
 	uint8_t		sc_ctrl;
 	uint8_t		sc_status;
-	bool		sc_use_ampm;
 };
=20
 static void ds3231_start(void *);
@@ -142,6 +141,25 @@
 }
=20
 static int
+ds3231_set_24hrs_mode(struct ds3231_softc *sc)
+{
+	int error;
+	uint8_t hour;
+
+	error =3D ds3231_read1(sc->sc_dev, DS3231_HOUR, &hour);
+	if (error) {
+		device_printf(sc->sc_dev, "cannot read from RTC.\n");
+		return (error);
+	}
+	hour &=3D ~DS3231_C_MASK;
+	error =3D ds3231_write1(sc->sc_dev, DS3231_HOUR, hour);
+	if (error !=3D 0)
+		device_printf(sc->sc_dev, "cannot write to RTC.\n");
+
+	return (error);
+}
+
+static int
 ds3231_temp_read(struct ds3231_softc *sc, int *temp)
 {
 	int error, neg, t;
@@ -440,6 +458,10 @@
 	ds3231_status_write(sc, 1, 1);
 	ds3231_ctrl_write(sc);
=20
+	/* Set the 24 hours mode. */
+	if (ds3231_set_24hrs_mode(sc) !=3D 0)
+		return;
+
 	/* Temperature. */
 	SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "temperature",
 	    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
@@ -479,7 +501,7 @@
 	int c, error;
 	struct bcd_clocktime bct;
 	struct ds3231_softc *sc;
-	uint8_t data[7], hourmask;
+	uint8_t data[7];
=20
 	sc =3D device_get_softc(dev);
=20
@@ -498,17 +520,10 @@
 		return (error);
 	}
=20
-	/* If chip is in AM/PM mode remember that. */
-	if (data[DS3231_HOUR] & DS3231_HOUR_USE_AMPM) {
-		sc->sc_use_ampm =3D true;
-		hourmask =3D DS3231_HOUR_MASK_12HR;
-	} else
-		hourmask =3D DS3231_HOUR_MASK_24HR;
-
 	bct.nsec =3D 0;
 	bct.sec  =3D data[DS3231_SECS]  & DS3231_SECS_MASK;
 	bct.min  =3D data[DS3231_MINS]  & DS3231_MINS_MASK;
-	bct.hour =3D data[DS3231_HOUR]  & hourmask;
+	bct.hour =3D data[DS3231_HOUR]  & DS3231_HOUR_MASK_12HR;
 	bct.day  =3D data[DS3231_DATE]  & DS3231_DATE_MASK;
 	bct.mon  =3D data[DS3231_MONTH] & DS3231_MONTH_MASK;
 	bct.year =3D data[DS3231_YEAR]  & DS3231_YEAR_MASK;
@@ -523,13 +538,13 @@
 	if (sc->sc_last_c =3D=3D -1)
 		sc->sc_last_c =3D c;
 	else if (c !=3D sc->sc_last_c) {
-		sc->sc_year0 +=3D 0x100;
+		sc->sc_year0 +=3D 100;
 		sc->sc_last_c =3D c;
 	}
 	bct.year |=3D sc->sc_year0;
=20
 	clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_READ, &bct);=20
-	return (clock_bcd_to_ts(&bct, ts, sc->sc_use_ampm));
+	return (clock_bcd_to_ts(&bct, ts, false));
 }
=20
 static int
@@ -539,7 +554,6 @@
 	struct bcd_clocktime bct;
 	struct ds3231_softc *sc;
 	uint8_t data[7];
-	uint8_t pmflags;
=20
 	sc =3D device_get_softc(dev);
=20
@@ -548,20 +562,13 @@
 	 * disables utc adjustment, so apply that ourselves.
 	 */
 	ts->tv_sec -=3D utc_offset();
-	clock_ts_to_bcd(ts, &bct, sc->sc_use_ampm);
+	clock_ts_to_bcd(ts, &bct, false);
 	clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_WRITE, &bct);=20
=20
-	/* If the chip is in AM/PM mode, adjust hour and set flags as =
needed. */
-	if (sc->sc_use_ampm) {
-		pmflags =3D DS3231_HOUR_USE_AMPM;
-		if (bct.ispm)
-			pmflags |=3D DS3231_HOUR_IS_PM;
-	} else
-		pmflags =3D 0;
=20
 	data[DS3231_SECS]    =3D bct.sec;
 	data[DS3231_MINS]    =3D bct.min;
-	data[DS3231_HOUR]    =3D bct.hour | pmflags;
+	data[DS3231_HOUR]    =3D bct.hour | 0b01000000;
 	data[DS3231_DATE]    =3D bct.day;
 	data[DS3231_WEEKDAY] =3D bct.dow + 1;
 	data[DS3231_MONTH]   =3D bct.mon;





Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CECBFBC7-6C63-4762-9A55-BE84DA53BBD2>