12

I have:

  • Raspberry Pi with 2015-05-05-raspbian-wheezy
  • ds1307 attached (it's an Adafruit board, pullup resistors not installed).

How do I:

  • configure drivers
  • make sure the Pi actually uses the RTC time on startup?

I've actually done the first part,as far as I can tell, but no luck with the second. Much of the information out there, including the Adafruit instructions, are obsolete due to this: https://www.raspberrypi.org/forums/viewtopic.php?t=97314

So, first step: you enable the I2c and drivers in raspi-config, add dtoverlay=i2c-rtc,ds1307 to the end of /boot/config.txt, and you've got drivers, and hwclock works for me now, apparently (can't run i2cdetect, more on that later).

You now need to remove fake-hwclock and set up so that it actually reads the rtc at startup. I've been trying to follow this advice - which is largely in agreement with other things I've seen, and is very recent - https://www.raspberrypi.org/forums/viewtopic.php?p=842661#p842661

(that is for a different RTC, but I'm only following the second part about removing fake-hwclock and so forth).

But no luck, and the 'lines to be commented out' there don't exist on my pi. My pi comes up with Jan 1 1970 00:00 and hwclock -r says the RTC is corrupted. Even if I have not powered off since setting the RTC and rebooting the pi, so it seems it must have been corrupted by the startup.

I've also not been able to run i2cdetect at all. It complains that the devices /dev/i2c(something) don't exist - and indeed they don't...


Interim Update

OK, I've established that:

  • the corruption is only of the time/date info. If I use i2cset to fill the nvram with a pattern, that information is not modified on reboot, but the year goes to 0x66
  • If I remove the ,ds1307 from the line dtoverlay=i2c-rtc,ds1307 in config.txt, then the system comes up without corrupting the RTC! Which supports the idea that the driver itself is corrupting the data. I've looked at the driver code, and it goes through the time and changes things it doesn't like (e.g. it changes 12 hr to 24 hour format). So, perhaps the problem is that the driver is installed at a time when the I2C port is not actually ready to work (perhaps due to clocks not being ready ?)
  • If I do this after startup: sudo sh -c 'echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device' it causes the rtc_ds1307 driver to load, and the /dev/rtc0 to appear. And the time is still OK. And so that can be used as basis of how to mod the init scripts
  • One more fun detail: if I use hwclock -s in a script right after writing to /sys/..../new_device, it fails. There needs to be a sleep 0.5 or something between.

So it seems I now have a system that can be shut down, and started up, and will have the correct time - I'll write this up properly soon.

13

3 Answers 3

9

Here is how I made it work.

Almost everything here needs to be done as super-user, so use 'sudo bash' or put sudo in front of everything (if not already shown).

The following basic steps are needed:

  • Arrange for the 'i2c' drivers to be present if not already;
  • there is an additional driver for rtc_ds1307
  • remove fake-hwclock. This is a subsystem which will normally be used when you don't have a network to supply the time; it saves the system time in a file when the system is shut down, and loads it from the same file at startup. So the time isn't right, but at least it doesn't go back to zero ( 1 Jan 1970 ) each time you restart. With the RTC installed, the time will start off reasonably correct even without the network.
  • arrange for the system to read the time from the RTC at startup.

Please note that this is for the image 2015-05-05-raspian-wheezy, on a rev 2.0 'Pi 1', and a ds1307 rtc attached to the expansion connecter. Some or much of it should apply to other situations (but probably not to older raspian). It is possible that the problem with the RTC being corrupted is specific to the ds1307 driver, so it could be simpler for other chips. And that problem may get fixed at some future release.

Also, these instructions are written for the model 2 PCB, where the I2C bus #1 is in use. If you have a rev1 PCB (which doesn't have the 8-pin 'P5' connector close to P1) you will be attaching the RTC to I2C bus #0. So, whenever you see /i2c-1/ in the below, use /i2c-0/ instead.

First, run raspi-config, and under 'advanced options', you will find a setting to enable the I2C and loading of I2C drivers. Enable them.

Now, you can in principle, add a line to the bottom of /boot/config.txt: dtoverlay=i2c-rtc,ds1307, which will load the ds1307 drive; but - as several have found - the loading of the driver will corrupt the contents of the clock, defeating its purpose. I have no idea why, but I looked at the driver source, and found that on startup, it reads the clock and then, if it finds things it doesn't like (such as a 12-hour format instead of 24), it 'corrects' those settings with writes. So, I suspect what may be happening is that the driver load too soon after the I2C has started, and perhaps the clocks aren't set up properly or something, and the communications is corrupted. In any case, that doesn't work with the configuration I have, and so we will cause the driver to be loaded later.

At this point, you can reboot, and using lsmod | grep i2c you should see the i2c_bcm2708 driver loaded (as asked for in raspi-config).

Next, run this command:

echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device

or (if not already superuser):

sudo sh -c 'echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device'

(sudo echo won't work since the > is what needs to be superuser).

This should cause the rtc_ds1307 driver to load, and will create a device /dev/rtc0. You should now be able to run hwclock:

sudo hwclock -r

...This displays the time from the RTC. It may well generate an error because your clock is not initialized properly yet. In any case, we will now set it.

(1) make sure the system clock is set using date. If you are on a network, it should be set already; if not, get out your phone, or your pocket timepiece, and try something like

sudo date -s '18 nov 2015 22:20:24'

when you have the system time set properly -- being careful to get it right for the time zone -- you can do

sudo hwclock -w

which copies it to the RTC.

And then the hwclock -r should work, and show the time in the RTC, and you should see it advancing if you read it more than once.

Wed 18 Nov 2015 22:48:41 EST  -0.181329 seconds
Wed 18 Nov 2015 22:48:53 EST  -0.013721 seconds

Note: the clock value is stored relative to the UTC time zone, but it's displayed in local time.

Next step: remove fake-hwclock. First disable it, and make sure the hwclock.sh is enabled:

sudo update-rc.d hwclock.sh enable
sudo update-rc.d fake-hwclock remove

sudo apt-get remove fake-hwclock
sudo rm /etc/cron.hourly/fake-hwclock
sudo rm /etc/init.d/fake-hwclock

hwclock.sh won't do anything at startup - it detects the presence of udev and assumes udev has done the startup work - but it does do something useful, which is to cause the system time to be written to the RTC at powerup. So, when you do connect to a network, the Pi time will sync to the network, and your RTC drift will get corrected when you shut down.

One thing left - we need to arrange to read the RTC at power-up, so the system time will be set. udev has a thing in it which tries to do that, but which will fail, or be bypassed, because the RTC driver is not loaded.

The way I've set this up, is to add these four lines at the top of /etc/rc.local (right at the top, below the comments):

echo 'setting up RTC'
echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
sleep 0.5
hwclock -s

This will ensure that the driver is loaded, and the system time set from the hardware clock, each time the system starts. The 'sleep 0.5' is there because I found that the hwclock command won't work without it - the action triggered by writing to /sys/class/i2c-adapter/i2c-1/new_device (including making /dev/rtc0 exist) apparently takes a bit of time (probably well under 0.5 sec).

And that's it. I'm not really happy with this use of /etc/rc.local - I'd rather have it set up much earlier, since a lot of stuff happens before rc.local is executed and it would be much better to have the clock set before those things run. But it's working for me. I'll update this answer if I find a better way.

References https://www.raspberrypi.org/forums/viewtopic.php?t=97314 https://www.raspberrypi.org/forums/viewtopic.php?p=842661 https://www.raspberrypi.org/forums/viewtopic.php?t=85683 https://www.raspberrypi.org/blog/upcoming-board-revision/

4
  • 1
    I had a RTC on order, and had been reading RTC posts. This is one of the few on this site that mentions RTC. My RTC arrived, I added dtoverlay=i2c-rtc,ds3231 to config.txt on latest Raspbian (Jessie). Everything seems to work OK. No special config required. Admittedly this is a different chip (although the data sheet looks very much the same, apart from the on chip Xtal and it runs from 3.3V). PS hwclock needs sudo
    – Milliways
    Dec 14, 2015 at 4:05
  • 1
    @Milliways /etc/rc.local runs as root. I don't recall if the ds3231 uses the same driver, and I don't know what causes the corruption anyway, just that it happens when the driver loads. Also, as I mentioned in a comment above, I suspect that some of these issues may be due to race conditions during init (e.g. the rtc driver may load before the i2c is set up properly), and may be considerably affected by the speed of the SD card. When I first ran Jessie it was on a class 4 card, and it was seriously broken; strange errors, and it ignored shutdown. Was fine on a class 10
    – greggo
    Dec 14, 2015 at 14:36
  • @Milliways but yes, I'd strongly recommend going with the ds3231, it runs on 3.3v, it's much more accurate. If it also saves you from these hassles, that's a huge bonus.
    – greggo
    Dec 14, 2015 at 14:39
  • > "but it does do something useful, which is to cause the system time to be written to the RTC at powerup" - do you mean power down?
    – OldTinfoil
    Oct 25, 2020 at 15:08
2

Supplementary Answer - Troubleshooting with I2C tools

While trying to make it work I found it helpful to use i2c-tools to look at the RTC, and you will find many references to this in other discussions. I had added some information to the question on what I found with it; I've moved it to this answer in case it is useful.

You will need I2C enabled (raspi-config) and the i2c-dev module loaded - you can force this with a sudo modprobe i2c-dev. i2c-dev is not needed to make the RTC work, but it is needed to use i2c-tools.

You can install i2c-tools using sudo apt-get install i2c-tools , if 'i2cdetect' is not present.

If you have a Rev. 1 PCB: Change i2cdetect -y 1 to i2cdetect -y 0, and change all the 1 0x68 to 0 0x68 in the i2cdump commands.

You can do i2cdetect -y 1

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --

... the '68' shows that a device responded at address 0x68 to being addressed on the I2C bus. If you have loaded the rtc_ds1307 driver, it will show up as 'UU' since it's reserved by the driver.

The command i2cdump -y -f -r 0-6 1 0x68 c can be used to dump the first 7 registers of the ds1307 which contain the time (the '-f' is needed only if you have the rtc driver installed; it overrides the reservation).

Below is what happens after powerup, when the RTC is corrupted due to the loading of the driver by dtoverlay=i2c-rtc,ds307.

hwclock -r initially reports that the clock setting is corrupt, and indeed the year is '66'.

pi@raspberrypi ~ $ sudo hwclock -r
hwclock: The Hardware Clock registers contain values that are either invalid (e.g. 50th day of month) or beyond the range we can handle (e.g. Year 2095).
pi@raspberrypi ~ $ sudo i2cdump -y -f -r 0-6 1 0x68 c
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 50 04 00 05 01 01 66                               P?.???f         
pi@raspberrypi ~ $ sudo i2cdump -y -f -r 0-6 1 0x68 c
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 52 04 00 05 01 01 66                               R?.???f         
pi@raspberrypi ~ $ sudo hwclock -w
pi@raspberrypi ~ $ sudo i2cdump -y -f -r 0-6 1 0x68 c
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 35 09 01 03 17 11 15                               5??????         
pi@raspberrypi ~ $ sudo i2cdump -y -f -r 0-6 1 0x68 c
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 37 09 01 03 17 11 15                               7??????         
pi@raspberrypi ~ $ sudo hwclock -r
Tue 17 Nov 2015 01:09:42 UTC  -0.384866 seconds
pi@raspberrypi ~ $ sudo i2cdump -y -f -r 0-6 1 0x68 c
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 46 09 01 03 17 11 15                               F??????         

The seven numbers from i2cdump are: [ sec min hrs day-of-week day month year], all in bcd, so the last time is 17-nov-2015, 01:09:46 UTC.

The 'corrupted' time is 1-jan-66, and I've seen others who have reported that same value showing up.

2

I had a similar issue on two Raspberry Pi 2 Model B with Arch Linux, one with a TinyRTC (with the ds1307) and another with a capacitor RTC (with the ds3231).

Running NTPD as daemon corrupted both RTC's date and set it to 2066/01/01.

#hwclock --debug
hwclock from util-linux 2.27
Using the /dev interface to the clock.
Last drift adjustment done at 1420070400 seconds after 1969
Last calibration done at 1420070400 seconds after 1969
Hardware clock is on UTC time
Assuming hardware clock is kept in UTC time.
Waiting for clock tick...
/dev/rtc does not have interrupt functions. Waiting in loop for time from /dev/rtc to change
...got clock tick
Time read from Hardware Clock: 2066/01/01 00:01:12
Invalid values in hardware clock: 2066/01/01 00:01:12
Time since last adjustment is -1420070400 seconds
Calculated Hardware Clock drift is 0.000000 seconds
hwclock: The Hardware Clock registers contain values that are either invalid (e.g. 50th day of month) or beyond the range we can handle (e.g. Year 2095).

The setup

I added in /boot/config.txt

dtparam=i2c_arm=on
dtoverlay=i2c-rtc,ds1307

or

dtparam=i2c_arm=on
dtoverlay=i2c-rtc,ds3231

I added in /etc/modules-load.d/raspberrypi.conf

i2c-bcm2708
i2c-dev

I disabled systemd-timesyncd

# timedatectl set-ntp false

I installed NTP

# pacman -S ntp

How it solved it

I found that by starting a single instance of the NTPD before starting the service updates the system time and does not set the RTC but if I start the NTPD service after that it updates the RTC date without corrupting it.

I thought there is a permission issue. The default group is audio.

# ls -l /dev/rtc0
crw-rw---- 1 root audio 254, 0 Jan  1  1970 /dev/rtc0

I created /etc/udev/40-rtc-permissions.rules to test it

KERNEL=="rtc0", GROUP="ntp", MODE="0666"

but it did not help so I deleted it.

I also had to update the system date at startup as it is not done automatically.

I added to the /etc/ntpd.service file

ExecStartPre=-/usr/bin/hwclock -s
ExecStartPre=/usr/bin/ntpd -gq

and enabled the NTPD service

# systemctl enable ntpd

and the date updates and does not corrupt during boot.

I did not find out what causes the NTPD daemon to corrupt the RTC if started first and would appreciate if someone improves on my solution but this works for me.

1
  • Thanks for the post. I've been fighting this on Raspberry Pi 3 all day, and your post finally put the last missing pieces together. I'm running Fedberry for the OS, and trying to set up the unit as an IPA server (why? Because Free IPA at 10watts - tastes great, less filling!) Now I've got a working IPA server that can survive power failures without manual intervention. I'm using the ds1307 rtc, and had run into some of the same issues when troubleshooting the clock you had identified. The worst was the corruption of the RTC memory on boot. I'm not sure if the dtparam=i2c_arm=on was the trick o
    – user45253
    Apr 19, 2016 at 23:01

Not the answer you're looking for? Browse other questions tagged or ask your own question.