I have seen many tutorials about connecting real time clock hardware on Orange Pi and Raspberry Pi.
What i didn't like was removing of fake-hwclock service, because I want that RTC works when it is connected, and fake-hwclock when RTC is not connected.
Therefore, I changed /sbin/fake-hwclock script to work in this way.
So, here is how to do this, tested on OrangePi+2E, Armbian Ubuntu legacy kernel:
Purchase cheap DS3231 module on eBay (cca. $1) like this one:
Edit /sbin/fake-hwclock and place this code in it:
Spoiler
!/bin/sh
#
# script: /sbin/fake-hwclock
# Changed by I.S. to use RTC if it is connected
#
#
# Trivial script to load/save current contents of the kernel clock
# from/to a file. Helpful as a *bootstrap* clock on machines where
# there isn't a useful RTC driver (e.g. on development boards). Using
# NTP is still recommended on these machines to get to real time sync
# once more of the system is up and running.
#
# Copyright 2012 Steve McIntyre <93sam@debian.org>
#
# License: GPLv2, see COPYING
# Config variables
# RTC is attached on bus...
i2c_bus=0
eeprom_address="57"
rtc_address="68"
# Orange PI +2e have RTC, so our device will be:
rtc_device="rtc1"
# fake-hwclock is using cron.hourly to periodically save system clock
cronfile="/etc/cron.hourly/fake-hwclock"
# If you want to periodically synchronize rtc with system time, change this to true
update_rtc_periodically=false
# End of config variables
# I don't know are all needed programs in PATH,
# therefore I'll declare all mine
echo="/bin/echo"
i2cdetect="/usr/sbin/i2cdetect"
grep="/bin/grep"
awk="/usr/bin/awk"
ln="/bin/ln"
hwclock="/sbin/hwclock"
readlink="/bin/readlink"
progs="$echo $i2cdetect $grep $awk $ln $hwclock $readlink"
check_external_progs(){
not_found=""
prog=""
for prog in ${progs}
do
if [ ! -e "$prog" ]; then
not_found=$prog" "$not_found
echo "Required program not found: $prog"
fi
done
if [ "$not_found"x = ""x ] ; then
progs_ok=true
else
progs_ok=false
fi
unset not_found
unset prog
}
recreate_cronjob() {
if [ ! -e "$1" ]; then
cat << 'EOF' > "$1"
#!/bin/sh
#
# Simple cron script - save the current clock periodically in case of
# a power failure or other crash
if (command -v fake-hwclock >/dev/null 2>&1) ; then
fake-hwclock save
fi
EOF
fi
}
is_rtc_connected(){
check_external_progs
if $progs_ok; then
list=$($i2cdetect -y "$i2c_bus")
rtc=$(echo "$list" | $grep "60:" | $awk '{print $10}')
eeprom=$(echo "$list" | $grep "50:" | $awk '{print $9}')
if [ "$eeprom" -eq "$eeprom_address" ]; then
case $rtc in
"UU")
t="/dev/$rtc_device"
r=$($readlink -f /dev/rtc)
if [ "$r"="$t" ]; then
$echo "true"
else
$ln -sf /dev/$rtc_device /dev/rtc >/dev/null 2>&1
if [ "$r"="$t" ]; then
$echo "true"
else
$echo "false"
fi
fi;;
$rtc_address)
$echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-0/new_device
sleep 5
$ln -sf /dev/$rtc_device /dev/rtc >/dev/null 2>&1
t="/dev/$rtc_device"
r=$($readlink -f /dev/rtc)
if [ "$r"="$t" ]; then
$echo "true"
else
$echo "false"
fi;;
*)
$echo "false";;
esac
else
$echo "false"
fi
else
$echo "false"
fi
}
# Is RTC installed?
rtc_installed=$(is_rtc_connected)
if $rtc_installed; then
# We dont need periodically saving
rm -f "$cronfile" >/dev/null 2>&1
else
# Restore periodically saving
recreate_cronjob "$cronfile"
fi
if [ "$FILE"x = ""x ] ; then
FILE=/etc/fake-hwclock.data
fi
COMMAND=$1
if [ "$COMMAND"x = ""x ] ; then
COMMAND="save"
fi
FORCE=false
if [ "$2"x = "force"x ] ; then
FORCE=true
fi
case $COMMAND in
save)
if $rtc_installed; then
#$echo "RTC save"
$hwclock -w
if $update_rtc_periodically; then
$echo "cronjob restore"
recreate_cronjob "$cronfile"
fi
else
if [ -e $FILE ] ; then
SAVED="$(cat $FILE)"
SAVED_SEC=$(date -u -d "$SAVED" '+%s')
NOW_SEC=$(date -u '+%s')
if $FORCE || [ $NOW_SEC -ge $SAVED_SEC ] ; then
date -u '+%Y-%m-%d %H:%M:%S' > $FILE
else
echo "Current system time: $(date -u '+%Y-%m-%d %H:%M:%S')"
echo "fake-hwclock saved clock information is in the future: $SAVED"
echo "To force the saved system clock backwards anyway, use \"force\""
fi
else
date -u '+%Y-%m-%d %H:%M:%S' > $FILE
fi
fi
;;
load)
if $rtc_installed; then
#$echo "RTC load"
$hwclock -s
else
if [ -e $FILE ] ; then
SAVED="$(cat $FILE)"
SAVED_SEC=$(date -u -d "$SAVED" '+%s')
NOW_SEC=$(date -u '+%s')
if $FORCE || [ $NOW_SEC -le $SAVED_SEC ] ; then
date -u -s "$SAVED"
else
echo "Current system time: $(date -u '+%Y-%m-%d %H:%M:%S')"
echo "fake-hwclock saved clock information is in the past: $SAVED"
echo "To set system time to this saved clock anyway, use \"force\""
fi
else
echo "Unable to read saved clock information: $FILE does not exist"
fi
fi
;;
*)
echo $0: Unknown command $COMMAND
exit 1
;;
esac
Reboot.
Now you should have right system time backed up by RTC.
You can post now and register later.
If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.
Question
IgorS
I have seen many tutorials about connecting real time clock hardware on Orange Pi and Raspberry Pi.
What i didn't like was removing of fake-hwclock service, because I want that RTC works when it is connected, and fake-hwclock when RTC is not connected.
Therefore, I changed /sbin/fake-hwclock script to work in this way.
So, here is how to do this, tested on OrangePi+2E, Armbian Ubuntu legacy kernel:
Purchase cheap DS3231 module on eBay (cca. $1) like this one:
http://www.ebay.com/itm/DS3231-AT24C32-IIC-Modul-High-Precision-Real-Time-Clock-Module-Arduino-New-/292041844936?hash=item43ff0ce8c8:g:d80AAOSwdGFYtsFP
Put battery in module.
Shutdown and powerof OPi and connect module:
Orange (i2c0 bus) RTC module (DS3231 RTC + 24C32 eeprom) 1 3.3V 2 VCC 3 PA12 (TWI0_SDA/DI_RX/PA_EINT12) 3 SDA 5 PA11 (TWI0_SCK/DI_TX/PA_EINT11) 4 SCL 9 GND 1 GND
Power up OPi
Install i2c-tools.
sudo apt install i2c-tools
Type command:
i2cdetect -y 0
You should see:
0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
This means that module is connected properly and that we have DS3231 on address 0x68 and eeprom 24C32 on address 0x57.
Type:
sudo echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-0/new_device i2cdetect -y 0
You should see:
0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
This means that system is now using our RTC. Also, now should exist new device /dev/rtc1
Be sure that your system time is right, and type:
sudo hwclock -w -f /dev/rtc1
Now our RTC must have right time. Check with:
sudo hwclock -r -f /dev/rtc1
If everithing was ok, copy /sbin/fake-hwclock to bacup (just in case)
sudo cp ~/programming/sh/fake_hwclock/sbin/fake-hwclock /sbin/fake-hwclock
Edit /sbin/fake-hwclock and place this code in it:
!/bin/sh # # script: /sbin/fake-hwclock # Changed by I.S. to use RTC if it is connected # # # Trivial script to load/save current contents of the kernel clock # from/to a file. Helpful as a *bootstrap* clock on machines where # there isn't a useful RTC driver (e.g. on development boards). Using # NTP is still recommended on these machines to get to real time sync # once more of the system is up and running. # # Copyright 2012 Steve McIntyre <93sam@debian.org> # # License: GPLv2, see COPYING # Config variables # RTC is attached on bus... i2c_bus=0 eeprom_address="57" rtc_address="68" # Orange PI +2e have RTC, so our device will be: rtc_device="rtc1" # fake-hwclock is using cron.hourly to periodically save system clock cronfile="/etc/cron.hourly/fake-hwclock" # If you want to periodically synchronize rtc with system time, change this to true update_rtc_periodically=false # End of config variables # I don't know are all needed programs in PATH, # therefore I'll declare all mine echo="/bin/echo" i2cdetect="/usr/sbin/i2cdetect" grep="/bin/grep" awk="/usr/bin/awk" ln="/bin/ln" hwclock="/sbin/hwclock" readlink="/bin/readlink" progs="$echo $i2cdetect $grep $awk $ln $hwclock $readlink" check_external_progs(){ not_found="" prog="" for prog in ${progs} do if [ ! -e "$prog" ]; then not_found=$prog" "$not_found echo "Required program not found: $prog" fi done if [ "$not_found"x = ""x ] ; then progs_ok=true else progs_ok=false fi unset not_found unset prog } recreate_cronjob() { if [ ! -e "$1" ]; then cat << 'EOF' > "$1" #!/bin/sh # # Simple cron script - save the current clock periodically in case of # a power failure or other crash if (command -v fake-hwclock >/dev/null 2>&1) ; then fake-hwclock save fi EOF fi } is_rtc_connected(){ check_external_progs if $progs_ok; then list=$($i2cdetect -y "$i2c_bus") rtc=$(echo "$list" | $grep "60:" | $awk '{print $10}') eeprom=$(echo "$list" | $grep "50:" | $awk '{print $9}') if [ "$eeprom" -eq "$eeprom_address" ]; then case $rtc in "UU") t="/dev/$rtc_device" r=$($readlink -f /dev/rtc) if [ "$r"="$t" ]; then $echo "true" else $ln -sf /dev/$rtc_device /dev/rtc >/dev/null 2>&1 if [ "$r"="$t" ]; then $echo "true" else $echo "false" fi fi;; $rtc_address) $echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-0/new_device sleep 5 $ln -sf /dev/$rtc_device /dev/rtc >/dev/null 2>&1 t="/dev/$rtc_device" r=$($readlink -f /dev/rtc) if [ "$r"="$t" ]; then $echo "true" else $echo "false" fi;; *) $echo "false";; esac else $echo "false" fi else $echo "false" fi } # Is RTC installed? rtc_installed=$(is_rtc_connected) if $rtc_installed; then # We dont need periodically saving rm -f "$cronfile" >/dev/null 2>&1 else # Restore periodically saving recreate_cronjob "$cronfile" fi if [ "$FILE"x = ""x ] ; then FILE=/etc/fake-hwclock.data fi COMMAND=$1 if [ "$COMMAND"x = ""x ] ; then COMMAND="save" fi FORCE=false if [ "$2"x = "force"x ] ; then FORCE=true fi case $COMMAND in save) if $rtc_installed; then #$echo "RTC save" $hwclock -w if $update_rtc_periodically; then $echo "cronjob restore" recreate_cronjob "$cronfile" fi else if [ -e $FILE ] ; then SAVED="$(cat $FILE)" SAVED_SEC=$(date -u -d "$SAVED" '+%s') NOW_SEC=$(date -u '+%s') if $FORCE || [ $NOW_SEC -ge $SAVED_SEC ] ; then date -u '+%Y-%m-%d %H:%M:%S' > $FILE else echo "Current system time: $(date -u '+%Y-%m-%d %H:%M:%S')" echo "fake-hwclock saved clock information is in the future: $SAVED" echo "To force the saved system clock backwards anyway, use \"force\"" fi else date -u '+%Y-%m-%d %H:%M:%S' > $FILE fi fi ;; load) if $rtc_installed; then #$echo "RTC load" $hwclock -s else if [ -e $FILE ] ; then SAVED="$(cat $FILE)" SAVED_SEC=$(date -u -d "$SAVED" '+%s') NOW_SEC=$(date -u '+%s') if $FORCE || [ $NOW_SEC -le $SAVED_SEC ] ; then date -u -s "$SAVED" else echo "Current system time: $(date -u '+%Y-%m-%d %H:%M:%S')" echo "fake-hwclock saved clock information is in the past: $SAVED" echo "To set system time to this saved clock anyway, use \"force\"" fi else echo "Unable to read saved clock information: $FILE does not exist" fi fi ;; *) echo $0: Unknown command $COMMAND exit 1 ;; esac
Reboot.
Now you should have right system time backed up by RTC.
added Spoiler
Link to comment
Share on other sites
40 answers to this question
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.