Date: Thu, 16 Jul 2020 12:35:55 -0300 From: "Dr. Rolf Jansen" <freebsd-rj@obsigna.com> To: Ian Lepore <ian@freebsd.org> Cc: freebsd-arm@freebsd.org Subject: Re: DS3231 on BeagleBone Black with FreeBSD 13-CURRENT exactly 20 h off backwards Message-ID: <BC3C9537-FC1F-436B-A898-265D3D320271@obsigna.com> In-Reply-To: <99ec5bfbe697e0cbf8b6262783256bffcbf55f55.camel@freebsd.org> References: <3BE2A8B4-AD53-4DFE-8C38-D5BB4063CFE9@obsigna.com> <CECBFBC7-6C63-4762-9A55-BE84DA53BBD2@obsigna.com> <99ec5bfbe697e0cbf8b6262783256bffcbf55f55.camel@freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
> Am 15.07.2020 um 23:32 schrieb Ian Lepore <ian@freebsd.org>: >=20 > On Wed, 2020-07-15 at 12:15 -0300, Dr. Rolf Jansen wrote: >>> Am 15.07.2020 um 09:52 schrieb Dr. Rolf Jansen < >>> freebsd-rj@obsigna.com <mailto: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> < >>> 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 >>>=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> >>> < >>> = 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 >>>=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 >>=20 >> 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 :-). >>=20 >> 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. >>=20 >=20 > The driver originally forced the chip into 24-hour mode. I'm the one > who added support for 12 or 24 hour mode, so this is probably my = fault. > It seems nicer to me to try to deal with whatever mode the chip is > already in (in case you're dual-booting into some other OS that wants > it to be a certain way). I'm pretty sure I've got one of those chips > around here somewhere, I'll find some time this weekend to get the > driver fixed. >=20 > -- Ian I appreciate your efforts for AM/PM support, only I am not sufficiently = familiar with the very details of this format, for example I always got = wrong the special meanings of 0:00 AM vs. 0:00 PM and 12:00 AM vs. 12:00 = PM. So, I am the wrong person to bugfix AM/PM issues. I applied the = temporary dirty fix of dropping out AM/PM only for getting the driver = quickly working on my side, and I could continue with my current = project. Once the driver is fixed upstream, I will use that one, of = course. That said, I wrote a sysctl function for directly getting/setting the = time in the RTC with unix time values. Perhaps, something like this = would facilitate your debugging efforts, and here it comes: static int ds3231_unixtime_sysctl(SYSCTL_HANDLER_ARGS) { int c, error; struct timespec ts =3D {}; struct bcd_clocktime bct; struct ds3231_softc *sc =3D (struct ds3231_softc *)arg1; uint8_t data[7]; if (req->newptr =3D=3D NULL) { // get the unixtime /* If the clock halted, we don't have good data. */ if ((error =3D ds3231_status_read(sc)) !=3D 0) { device_printf(sc->sc_dev, "cannot read from = RTC.\n"); return (error); } if (sc->sc_status & DS3231_STATUS_OSF) return (EINVAL); error =3D iicdev_readfrom(sc->sc_dev, DS3231_SECS, data, = sizeof(data), IIC_INTRWAIT); if (error !=3D 0) { device_printf(sc->sc_dev, "cannot read from = RTC.\n"); return (error); } 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] & 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; bct.ispm =3D data[DS3231_HOUR] & DS3231_HOUR_IS_PM; /* * If the century flag has toggled since we last saw it, = there has been * a century rollover. If this is the first time we're = seeing it, * remember the state so we can preserve its polarity on = writes. */ c =3D (data[DS3231_MONTH] & DS3231_C_MASK) ? 1 : 0; 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 100; sc->sc_last_c =3D c; } bct.year |=3D sc->sc_year0; error =3D clock_bcd_to_ts(&bct, &ts, false); if (error =3D=3D 0) { error =3D sysctl_handle_long(oidp, &ts.tv_sec, = 0, req); } } else if ((error =3D sysctl_handle_long(oidp, &ts.tv_sec, 0, req) = =3D=3D 0)) { // set the unixtime /* * We request a timespec with no resolution-adjustment. = That also * disables utc adjustment, so apply that ourselves. */ ts.tv_sec -=3D utc_offset(); clock_ts_to_bcd(&ts, &bct, false); data[DS3231_SECS] =3D bct.sec; data[DS3231_MINS] =3D bct.min; 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; data[DS3231_YEAR] =3D bct.year & 0xff; if (sc->sc_last_c) data[DS3231_MONTH] |=3D DS3231_C_MASK; /* Write the time back to RTC. */ error =3D iicdev_writeto(sc->sc_dev, DS3231_SECS, data, = sizeof(data), IIC_INTRWAIT); if (error !=3D 0) { device_printf(sc->sc_dev, "cannot write to = RTC.\n"); return (error); } /* * Unlike most hardware, the osc-was-stopped bit does = not clear itself * after setting the time, it has to be manually written = to zero. */ if (sc->sc_status & DS3231_STATUS_OSF) { if ((error =3D ds3231_status_read(sc)) !=3D 0) { device_printf(sc->sc_dev, "cannot read = from RTC.\n"); return (error); } sc->sc_status &=3D ~DS3231_STATUS_OSF; if ((error =3D ds3231_status_write(sc, 0, 0)) !=3D= 0) { device_printf(sc->sc_dev, "cannot write = to RTC.\n"); return (error); } } } return (error); } ... /* Date/Time. */ SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "unixtime", CTLFLAG_RW | CTLTYPE_ULONG | CTLFLAG_MPSAFE, sc, 0, ds3231_unixtime_sysctl, "LU", "get/set the Date/Time = formatted as a UNIX time stamp"); /* Temperature. */ ... Then, I wrote a shell script for testing, whether setting/getting the = time works as expected (checkds3231.sh): #!/bin/sh DATE=3D`date "+%Y-%m-%d"` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 00:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 01:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 02:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 03:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 04:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 05:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 06:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 07:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 08:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 09:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 10:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 11:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 12:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 13:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 14:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 15:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 16:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 17:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 18:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 19:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 20:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 21:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 22:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date -jf "%Y-%m-%d %H:%M:%S" "+%s" = $DATE" 23:26:14"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` sysctl dev.ds3231.0.unixtime=3D`date "+%s"` > /dev/null 2>&1 date -jf "%s" "+%Y-%m-%d %H:%M:%S" `sysctl -n dev.ds3231.0.unixtime` The sample output here looks good: 2020-07-16 00:26:14 2020-07-16 01:26:14 2020-07-16 02:26:14 2020-07-16 03:26:14 2020-07-16 04:26:14 2020-07-16 05:26:14 2020-07-16 06:26:14 2020-07-16 07:26:14 2020-07-16 08:26:14 2020-07-16 09:26:14 2020-07-16 10:26:14 2020-07-16 11:26:14 2020-07-16 12:26:14 2020-07-16 13:26:14 2020-07-16 14:26:14 2020-07-16 15:26:14 2020-07-16 16:26:14 2020-07-16 17:26:14 2020-07-16 18:26:14 2020-07-16 19:26:14 2020-07-16 20:26:14 2020-07-16 21:26:14 2020-07-16 22:26:14 2020-07-16 23:26:14 2020-07-16 12:32:12 Best regards Rolf=
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?BC3C9537-FC1F-436B-A898-265D3D320271>