DS3231 RTC hwclock for Raspberry Pi and Arduino

I’ve been spending some time with the Maxim Integrated DS3231 “Extremely Accurate I2C Integrated RTC”. Many have recommended it to provide a RTC for an advanced Arduino style board called the Goldilocks, so I looked into putting one of these SOIC16 devices on the board. The bottom line is that the best device price to me is greater than the finished price for a Raspberry Pi compatible module, complete with either a battery or a super capacitor to maintain the time should the main power be lost.

DS3231 RTC Module

The DS3231 also contains an accurate thermometer, used to trim the timing to maintain the +-2ppm accuracy characteristic from 0 to 40 degrees Celcius. The registers for the temperature can be read, and make a useful secondary function for this device.

I purchased some DS3231 modules for my Raspberry Pi devices, and also to test their use as an option for the Goldilocks Analogue. This is to remind myself how the Raspberry Pi needs to be configured to use the DS3231 RTC module.

Arduino

Actually using the DS3231 on the Arduino platform is very easy. Simply, treat it exactly as a DS1307 device. It behaves identically, except it is significantly more accurate.

For the Goldilocks Analogue, the module can simply be plugged into the prepared port, replicating the Raspberry Pi interface.

DS3231 on Goldilocks Analogue

DS3231 on Goldilocks Analogue

The Goldilocks Analogue is now available on Kickstarter.

Configuring for Raspberry Pi

To contain cost the Raspberry Pi doesn’t have a hardware or real time clock capability. A fake RTC is provided which simply stores the time the Raspberry Pi was shut down, and reads this time out when the Raspberry Pi is booting. Obviously this time can be wrong by anything from 10 seconds to a year, depending on how long the Raspberry Pi is left unused.

The DS3231 module is an I2C device that is attached to IO pins 1 through 5 on the Raspberry Pi. The DS3231 can run from either 3V3 or 5V so it can work with both Arduino and Raspberry Pi I2C bus levels.

Sunfounder DS3231 module installed on a Raspberry Pi B+

SunFounder DS3231 module installed on a Raspberry Pi B+

There are several Internet references on how to get the DS3231 working on the Raspberry Pi. But the most concise version is by Drew Keller. Initially I used these to get started, but the method described activates the RTC at the end of the boot sequence, long after the time is really needed to set logging and disk access times correctly. Fortunately, there is another instruction that describes some minor changes to the hwclock.sh script which enables the DS3231 early in the boot sequence, ensuring that we have the correct time when we need it. Unfortunately it describes insertion of the wrong module, and refers to the DS1307 (although this is essentially the same).

So that I don’t forget what to do, here are the instructions again.

Update: Kernel 3.18 breaks some things. This is the fix.

First lets fix something only relevant to those who are running the 3.18+ kernel.

Help, my I2C interface has disappeared. What do I do? Add

dtparam=i2c=on

to your /boot/config.txt and reboot. If you are feeling terse you can omit the “=on”, since that is the default option.

Now we have to edit the hwclock.sh file in /etc/init.d/ to add this function to initialise the RTC. Note that the i2c-bcm2708 module is used.

HCTOSYS_DEVICE=rtc0

init_rtc_device()
{
  [ -e /dev/$HCTOSYS_DEVICE ] && return 0;

  # load i2c and RTC kernel modules
  modprobe i2c-bcm2708
  modprobe rtc-ds1307

  # iterate over every i2c bus as we're supporting Raspberry Pi rev. 1 and 2
  # (different I2C busses on GPIO header!)
  for bus in $(ls -d /sys/bus/i2c/devices/i2c-*);
  do
    echo ds3231 0x68 >> $bus/new_device;
    if [ -e /dev/$HCTOSYS_DEVICE ];
    then
      log_action_msg "RTC found on bus `cat $bus/name`";
      break; # RTC found, bail out of the loop
    else
      echo 0x68 >> $bus/delete_device
    fi
  done
}

Then a bit further down in the start) section add in a call to the initialisation function we’ve just prepared, and also comment out the udev search as it won’t find the DS3231.

case "$1" in
  start)
    # initialise the hardware RTC DS3231
    # this is for the module attached
    init_rtc_device
...
    # As UDEV won't find ds3231, comment this out
    # if [ -d /run/udev ] || [ -d /dev/.udev ]; then
    # return 0
    # fi
...

Then we have to remove the I2C module blacklist entry (by commenting it out) so that it can be loaded on boot. The Raspberry Pi team think that their users won’t use I2C or SPI functions normally, so they’re preemptively disabled.

sudo sed -i 's/blacklist i2c-bcm2708/#blacklist i2c-bcm2708/' /etc/modprobe.d/raspi-blacklist.conf

The final thing left is to remove the fake hardware clock function by typing this command from the shell.

sudo update-rc.d fake-hwclock remove

The reboot the Raspberry Pi and check that you can see the /etc/rtc0 and that the hwclock function returns a valid time. By studying the boot log messages relating to the RTC can also be seen. Check that you’re getting no errors. You should see something like this.

[ 10.631809] rtc-ds1307 1-0068: rtc core: registered ds3231 as rtc0
[ 10.650126] i2c i2c-1: new_device: Instantiated device ds3231 at 0x68

SATA on UDOO

My SSD and eSATA caddy have arrived. So now we plug it all in and off we go.

Some testing on my amd64 Ubuntu Linux Machine, for comparison with the uSD cards used for the UDOO currently.

The SanDisk Black uSD card behaves in the amd64 machine, just as it did in the UDOO previously.
SanDisk_BlackSD_4GB

Now we test the SanDisk Extreme ii SSD, connected via USB3.0.
SanDisk_Extreme2_USB3

Quite a difference.
If we can get close to this performance in the UDOO, then it will be worth the money spent.

UDOO and SSD Preparation

The guide available on elinux describes all of the steps required for booting the UDOO from the SATA drive.

First prepare a small uSD card to be the boot drive. Format it with one ext3 partition, and install the u-boot bootloader as usual.

sudo dd if=u-boot-q.imx of=/dev/<MICROSD_DEVICE> bs=512 seek=2

This is sufficient to get the UDOO to boot.

Now prepare the SSD, by formatting it in the same way you formatted the uSD previously. I’m now adding an additional linux-swap partition about 2GB in size. Although there are warnings about using SSD for swap, if you’re using a full desktop on your UDOO, your browser won’t respect the memory limitation and you’ll create worse problems.

Although the 8MB free space is not currently used in the SATA SSD, because u-boot is contained on the uSD. My guess is that at some time soon the UDOO team will get the u-boot loadable on the SATA drive, and then this space will be needed.

Once the SSD is prepared, then the fastest way to replicate your already created environment is to copy disk to disk.

cd /media
sudo cp -rp UDOO_SDroot/* UDOO_SSDroot
sudo cp -rp UDOO_SDhome/* UDOO_SSDhome
sync; sync

One final thing is to change the references in the /etc/fstab from

/dev/mmcblk0p1 to /dev/sda1 for /
/dev/mmcblk0p2 to /dev/sda2 for /home
/dev/mmcblk0p3 to /dev/sda3 for swap

Now, plug the SSD caddy into the UDOO, and put the uSD in its slot.

First boot

When first booting the UDOO, interrupt the auto boot process and enter the commands noted in the elinux instructions.
Open a serial terminal to your PC with a baud of 115200 8n1. Reset the UDOO and press any key over serial terminal when prompted to cancel the autoboot. If you miss the prompt, you can press reset on the UDOO.

setenv bootdev "sata init; sata dev 0; ext2load sata 0"
setenv root root=/dev/sda1
saveenv
boot

And the UDOO should boot as normal, but from the eSATA drive.

Note that there can be errors with eSATA / USB3.0 casings. I initially chose one which uses the Prolific PL2773, which implements the attachment as a USB Bulk-Only Mass Storage Class. Unfortunately this storage class doesn’t have the capability to pass TRIM commands.

But, although the attachment for the SSD doesn’t have TRIM capability, the SSD reports that it does have this capability, via eSATA, and this confuses the Kernel.

Errors are caused by the Kernel calling for TRIM on the swap space during the boot process.

How to fix this? Well the simplest way is to throw away the disk casing and connect the SSD drive directly. So, this is what I did. The disk performance also increases markedly too!

UDOO SSD speed testing

The UDOO SATA port doesn’t achieve quite the same throughput as the amd64 desktop does over USB3. But the speed increase over the uSD card is significant, and is very noticeable in use. Worth doing, in any case.
SanDisk_Extreme2_eSATA

After removing the SSD drive from the housing, and driving it directly, the performance increase can be seen. The average read rate has doubled to over 110MB/s and the access time has decreased by a third making it about the same speed as on the amd64 desktop.

In practice the desktop feels even smoother. Great result!
Screenshot from 2013-11-18 23:08:14

UDOO Ubuntu 12.04 Guide

Recently, my Quad core UDOO board arrived in the post. Initially, I tried the two provided uSD cards, with Ubuntu 11.10 and Android 4.2.2. I was a little disappointed that the Android version didn’t seem to work out of the box, but probably I did something wrong. What was more disappointing was that the provided Ubuntu operating system Ubuntu 11.10, is already past End of Life. Releasing a brand new device with an EOL operating system; I’m not sure what the UDOO team (or actually Freescale) are thinking.

Image

Ok, so It is time to go my own way to get something that will remain viable for the long term. I use Ubuntu 12.04 LTS on my machines that aren’t running debian. So it is natural that I’d try the same Ubuntu Precise LTS solution, which is supported through to 2017, on my UDOO board too.

A bit of searching found Dave Cheney, who has written about installing Precise on his UDOO quad. However, Dave assumes that there is a working UDOO Linaro system from which to derive the result. I didn’t have that starting point, so I needed to find a solution from the uSD card inserted into my amd64 (Intel) machine, and build from a chroot armhf on amd64 solution. Fortunately, there are some references for how to take this path too.

Following this initial process, there are quite a few steps to get to a desktop GUI from the very simple Ubuntu core file system starting point, none of which are documented clearly. So, knowing that I’d need to take this path again (after I break something) it is time to write the steps down.

Get all the pieces of code necessary

From the UDOO Downloads page, get the latest versions of U-boot, Kernel, and Kernel Modules, relevant for your UDOO. Either the Quad versions or the Dual versions.

From the Ubuntu Core page, download the ubuntu-core-xx.xx.xx-core-armhf.tar.gz latest version that is there when you read this. At the time of writing it is 12.04.3. I’m led to believe that any recent version of Ubuntu Core would also work (see comments). There’s plenty of opportunity to experiment.

Prepare the uSD Card

Use the largest uSD card that you can find. Also, get the fastest one available at a reasonable price. I have now loaded the system on to a Sandisk Ultra uSD card, and compared the speeds to a Sandisk “Black” card. It is worth getting a “faster” uSD Card for the operating system, but perhaps not especially the “fastest”. The Black card’s performance is quite variable, and particularly the Average Access time ranges from 1.4ms up to 3ms, whereas the Ultra card’s Average Access time is consistently 0.9ms to 1.0ms after repeated testing. The other parameters seem consistently similar.

Black (Class 4 ) Minimum 19.5Mb/s Maximum 22.4Mb/s Average 21.0Mb/s Access 1.5ms
Ultra (Class 10) Minimum 19.6Mb/s Maximum 22.5Mb/s Average 21.0Mb/s Access 0.9ms

I have done some testing with a SATA SSD to compare it with these uSD Cards. If you can use a SSD as the root disk, then you’ll have a much more responsive experience.

Extreme ii SSD Minimum 81.6Mb/s Maximum 124.3Mb/s Average 110.4Mb/s Access 0.2ms

The elinux wiki has instructions for creating a bootable uSD card for UDOO. These are easy to follow, so I’ll not repeat all the details here. Using GParted I only left 8 MByte space before the start of the primary partition, and I labelled it “UDOO”. I also split the card in half, creating a secondary partition for the /home partition. This may take some time to complete, if your uSD is slow…

Image

Image

Before mounting the newly created filesystems, install the U-boot file into the first 8 MByte of the uSD card. Be sure to pick the descriptor for the root of the card (not the first partition). For me <MICROSD_DEVICE> is /dev/sdg.

Be very sure you’ re using the correct device; using the wrong device identifier will result in the loss of all data on the Hard Drive of the host PC used as you will overwrite the MBR.

sudo dd if=u-boot-q.imx of=/dev/&lt;MICROSD_DEVICE&gt; bs=512 seek=2

Create the Filesystem

Mount the just-created root partition on the uSD card. It will appear at /media/UDOO if you chose the same label as suggested. Then extract the tar.gz file containing the file system onto the uSD card with the following command, where <NAME_OF_TAR_FS> is the Ubuntu Core file downloaded previously.

sudo tar -xzvpf &lt;NAME_OF_TAR_FS&gt; -C /media/UDOO/

First, extract the Kernel Modules to the same current folder, and then copy the Kernel file and the Kernel Modules to the uSD.

sudo cp -p uImage /media/UDOO/boot
sudo cp -rp lib/modules/* /media/UDOO/lib/modules/

So, now the uSD card is complete, and the new Precise UDOO should boot.

But wait,… there’s more. The Ubuntu Core is absolutely the minimum required to get started. There’s not even a user defined, so if we want to log into the new system we have to do a little more to get ourselves started.

Chroot from amd64 into armhf

To be able to execute armhf commands from an amd64 platform we need to use qemu. So for that to work we need to make sure we’ve got qemu installed on the host platform. Check using dpkg.

dpkg -l qemu-user-static

Have your SD Card mounted on your Linux PC and go to your Ubuntu Core folder:

cd /media/UDOO

Copy the qemu for arm file:

sudo cp /usr/bin/qemu-arm-static usr/bin/

Make sure you have your network settings properly configured:

sudo mv etc/resolv.conf etc/resolv.conf.saved
sudo cp /etc/resolv.conf etc/resolv.conf

Then, mount sys, proc and dev:

for m in `echo 'sys dev proc'`; do sudo mount /$m ./$m -o bind; done

Finally, chroot into the target filesystem:

sudo LC_ALL=C chroot . /bin/bash

You are now in your ‘chroot’ which means you can run commands as if you were on your target ARM device.

Using the ‘chroot’

The first step is to verify the network connection is fine. You can run:

apt-get update

You are now ready to install any new package in your Ubuntu Core Filesystem using APT tools.

In the armhf ‘chroot’

Now we can do some commands to make the UDOO environment more complete.

apt-get update
apt-get install apt-utils whiptail language-pack-en-base
dpkg-reconfigure tzdata
apt-get upgrade
apt-get install sudo vim-tiny less net-tools openssh-server wpasupplicant isc-dhcp-client ntp #(and any other packages you want)

Adding a user

Out of the Ubuntu Core box, there is no user defined. so we have to add at least “SOMEUSER” to enable us to log into the system.

adduser SOMEUSER
adduser SOMEUSER adm
adduser SOMEUSER sudo

Fixing the Console

The UDOO serial port (the uUSB connector closest to the corner of the board) operates at 115200 baud, but by default the Ubuntu Core image is not configured to take over on /dev/console at the correct baud. The simplest solution to fix this is to copy the tty1 configuration to the console configuration, and then adjust to the correct baud rate.

cp /etc/init/tty1.conf /etc/init/console.conf
vi /etc/init/console.conf

change the last line to

exec /sbin/getty -8 115200 console

Enabling the Ethernet

The wired Ethernet port is not automatically enabled. Edit the interfaces file and add two lines.

vi /etc/network/interfaces

auto eth0
iface eth0 inet dhcp

Other Niceties

Obtain the Ubuntu universe packages. The /etc/apt/sources.list file has most of the sources commented out. These comments should be removed, before installing a GUI.

vi /etc/apt/sources.list

Leaving the ‘chroot’

If you want to get out of the ‘chroot’ just type:

exit

Un-mount the target filesystem: Make sure you stay at the UDOO root point /media/UDOO/ and run the following commands. Go back to the original network settings. And the qemu can be removed too.

for m in `echo 'sys dev proc'`; do sudo umount ./$m; done
sudo mv etc/resolv.conf.saved etc/resolv.conf
sudo rm usr/bin/qemu-arm-static
sync; sync

Booting into UDOO Precise LTS

Insert the new UDOO Precise LTS file system uSD into the appropriate place, and then start up the serial console to watch the system boot. The serial port uUSB connector is the one closest to the RESET button, and should be connected at 115200 baud 8n1. It will appear on an amd64 Ubuntu machine as /dev/ttyUSB0.

UDOO uSD

When the system is booted the hdmi interfaced terminal should work successfully too. Use the login details you created above to log in, and profit!

Building the Desktop

From this point it is possible to install the GUI of choice. I have tried with LXDE, but given this is a Quad Core device, it may well run well with the standard Unity Desktop.

Installing LXDE or Unity (the standard Ubuntu desktop) can be done once you’re logged into the UDOO board, by either of these commands.

sudo apt-get install lxde-desktop
# OR
sudo apt-get install ubuntu-desktop

Once you have rebooted into your new desktop, it is useful to move the home directories over to the second partition that was prepared. The full desktop environments identify the second uSD partition and mount it automatically as /media/home.

sudo cp -rp /home/* /media/home

Edit the /etc/fstab file to get the partition to mount at /home, and reboot.

One thing missing (in a short amount of testing) is the firmware for the WiFi device. The best place to find the latest firmware-ralink is in the debian Sid repository. It is the same file for all architectures.

sudo dpkg -i firmware-ralink_0.43_all.deb

Final Thoughts

Compared to the Raspberry Pi the UDOO environment certainly runs very hot. The large heat sink on the UDOO is very necessary, whereby the Raspberry Pi doesn’t even need a heatsink. I guess that Freescale has packed a lot more (4x more?) into the same space that Broadcom used for its design, and that consumes more energy. Certainly, the lack of a GPU driver module and user space tools for the display, forcing software rendering doesn’t help. Hopefully Freescale will get their act together soon and Open Source the Vivante GC2000 driver code, or at least the hardware definitions to allow the Etnaviv team to progress quickly.

Neither Raspberry Pi nor UDOO are capable of being battery powered devices, which makes them pretty useless for any Internet of Things sensor project, IHMO. So, I’m not sure what kind of applications they’re really trying to address? Doesn’t matter, they’re still pretty cool devices and I’m going to be using the UDOO often.