Adding an External Real-time Clock Module For the Beaglebone Black
The post provides rough steps for integrating a real-time clock (RTC) module with a Beaglebone Black (BBB) for the purposes of accurate date and time retention over power cycles.
- Beaglebone Black (BBB) Single Board Computer (SBC) Revision C
- Ethernet cable
- Micro-USB to USB-A cable for power
- Adafruit DS3231 Precision RTC Breakout Kit
- 1 CR1220 3V cell battery
- Dupont wire connector kit
- Crimper tool
- Soldering iron and solder
A table with information about the BBB used in this setup:
|Board||Beaglebone Black (BBB) Single-board Computer (SBC)|
|Operating System||Debian Linux with TI BSP, Linux 5.10.145-ti-rt-r55 #1bullseye SMP PREEMPT_RT|
|Processor||TI Sitara AM3358BZCZ100 ARM Cortex-8 @ 1GHz|
|# of cores||1|
|On-board Storage||4GB embedded multi-media card (eMMC, disabled via uBoot at this time)|
|Expansion||SDCard memory card slot, currently running the OS from 128GB card|
I desired for the BBB to always have current date and time across power cycle events. As I searched for solutions on the internet I came across forum and forum basically pointing to the integration and use of a real-time clock module. Further searching led me to the Adafruit website and their tutorial using the DS1307 Precision RTC Breakout Board product. I ordered the DS3231 unit from their online store for $17.50 on February 16th, $24.91 with tax and shipping tacked on. The unit arrived at my doorstep about 4 days later.
The Adafruit DS3231 Precision RTC Breakout kit comes with the DS3231 chip already soldered onto the PCB with pin-outs labeled. The kit also includes a single-row 8-pin 2.54mm male header that must be soldered onto the board. The first thing I did after removing the kit from its packaging was to insert the 3V CR1220 cell battery into the underside slot on the board. Next, I soldered the 8-pin header onto the board.
I used a Dupont connector kit, a 24 AWG wire kit, and the crimper tool to create a jumper cable for connecting the RTC module with the BBB. The red wire is for input voltage (Vin), black wire for ground (GND), blue wire for the I2C serial clock (SCL), and yellow wire for the I2C serial data (SDA).
The BBB was connected to the network via Ethernet and was receiving power at 5V and 500mA via the micro-USB to USB-A cable.
I needed to modify my pin setup script on the BBB to set pins 19 and 20 on header P9 from CAN RX and TX respectively; to I2C SCL and SDA; respectively. I tunneled into the BBB via SSH and made the changes to the custom setup script located in the home directory. Once that was done, I rebooted the system and checked the status of the systemd service associated with running the script at boot up and verified successful operation.
Now I was ready to connect up the hardware. First step was to remove power from the BBB. Next, I connected the female housing end of the jumper cable to the first four pins on the RTC module’s male header pins; red to pin 1 (Vin), black to pin 2 (GND), yellow to pin 3 (SDA), and blue to pin 4 (SCL). I then inserted the male end of each wire into the predetermined pin slot on the BBB’s P9 header; red to pin 7 (+5V SYS), black to pin 1 (DGND), blue to pin 19 (I2C SCL), and yellow to pin 20 (I2C SDA). With connections in place, I reapplied power to the BBB and allowed time for boot-up.
The following are roughly the steps I took to configure the system on the BBB to use the RTC module. Most steps were taken from the previously referenced Adafruit tutorial. However, I had to do some things different and posting the steps here serves as documentation for myself that I can easily refer to later (and by virtue of the internet others can reference this also).
Perform the following steps:
(1.) Tunnel into the BBB via ssh.
(2.) Install the ntpdate and i2ctools packages if they are not installed on the system using the system’s package manager (apt on my debian-based system):
sudo apt install nptdate i2ctools
The i2cdetect utility is a part of the i2ctools package and will be used to find the address of the RTC module on an I2C bus. The utility’s help documentation as installed and viewed on my system:
Error: Unsupported option "--help"! Usage: i2cdetect [-y] [-a] [-q|-r] I2CBUS [FIRST LAST] i2cdetect -F I2CBUS i2cdetect -l I2CBUS is an integer or an I2C bus name If provided, FIRST and LAST limit the probing range.
The ntpdate utility allows us to update the date and time on the system by connecting to Network Time Protocol (NTP) servers on the web. The utility’s help documentation as installed and viewed on my system was not helpful, so I refer you to documentation here.
(3.) Use the i2cdetect utility to find the address of the RTC module on the I2C bus. I found the module on I2C bus 2 on my system:
i2cdetect -y -r 2
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: -- -- -- -- -- -- -- --
(4.) Write the device number and address to the I2C node on the system which matches the bus number where the RTC module was found (I had to login as root to perform this):
sudo su echo ds3231 0x68 > /sys/class/i2c-adapter/i2c-2/new_device
(5.) Get the date and time from the RTC module and make note of the output:
hwclock -r -f /dev/rtc1
Most likely the output is junk i.e. some default date and time that is not correct. For the Debian-based system running on my hardware, the /dev/rtc1 is reserved for an external clock. The hwclock utility allows one to get and set properties of the system’s hardware (HW) clocks. The help documentation as viewed on my system:
Usage: hwclock [function] [option...] Time clocks utility. Functions: -r, --show display the RTC time --get display drift corrected RTC time --set set the RTC according to --date -s, --hctosys set the system time from the RTC -w, --systohc set the RTC from the system time --systz send timescale configurations to the kernel -a, --adjust adjust the RTC to account for systematic drift --predict predict the drifted RTC time according to --date Options: -u, --utc the RTC timescale is UTC -l, --localtime the RTC timescale is Local -f, --rtc <file> use an alternate file to /dev/rtc0 --directisa use the ISA bus instead of /dev/rtc0 access --date <time> date/time input for --set and --predict --delay <sec> delay used when set new RTC time --update-drift update the RTC drift factor --noadjfile do not use /etc/adjtime --adjfile <file> use an alternate file to /etc/adjtime --test dry run; implies --verbose -v, --verbose display more details -h, --help display this help -V, --version display version For more details see hwclock(8).
(6.) Update the system’s date and time via the NTP servers:
ntpdate -b -s -u pool.ntp.org
(7.) Write the up-to-date date and time information into the external RTC module:
hwclock -w -f /dev/rtc1
Using systemd for Time Setup Automation on Boot Up
I followed the steps from the Adafruit tutorial to create a service to update the system date and time from the RTC module shortly after the BBB boots up with some modifications.
(1.) The Bash script:
#!/bin/bash sleep 15 echo ds3231 0x68 /sys/class/ic2-adapter/i2c-2/new_device hwclock -s -f /dev/rtc1 hwclock -w
(2.) Setting the permissions on the script:
sudo chmod 755 rtc_init.sh
(3.) A systemd unit file was created in the /etc/systemd/system directory to call the Bash script as a part of a service to update the system date and time shortly after boot up:
[Unit] Description=DS3231 RTC Service [Service] Type=simple User=root Group=root ExecStart=/bin/bash /home/debian/rtc_init.sh SyslogIdentifier=rtc_ds3231 [Install] WantedBy=multi-user.target
(4.) Setting permissions on the unit file, enabling the service, and rebooting the BBB:
sudo chmod 777 rtc-ds3231.service sudo systemctl enable rtc-ds3231.service sudo reboot