[Unit] Description=BubbleCam: seed system clock from DS3231 hardware RTC # Must run before anything time-dependent (sensors, lumen dusk/dawn calc, # watchdog staleness checks) -- without this, a cold boot with no network # would come up with a garbage system clock (no NTP available in the field). DefaultDependencies=no After=dev-rtc0.device Before=basic.target # Deliberately NOT Wants=dev-rtc0.device: that makes systemd *wait* for the # device unit, and since this unit is Before=basic.target, the entire boot # (NetworkManager included) queues behind it -- observed as an ~80s stall # before the network came up. The bounded ExecStartPre poll below gives the # RTC a fair chance to appear without ever holding the boot hostage. JobTimeoutSec=30 # This is a boot-time oneshot with no running process -- there is nothing # to stop, and a stop job on a Before=basic.target unit stalls until it # times out, which silently takes the rest of a `systemctl stop # 'bubblecam-*'` transaction down with it (observed: the e-paper service # stayed running, still holding the camera). RefuseManualStop=yes [Service] Type=oneshot # Poll for the device rather than depending on it: up to ~10s, then give up # and continue booting regardless. ExecStartPre=/bin/sh -c 'for i in $(seq 1 20); do [ -e /dev/rtc0 ] && exit 0; sleep 0.5; done; exit 0' # -s = set the system clock from the hardware RTC. Requires the kernel # rtc-ds1307 driver to be bound via config.txt's `dtoverlay=i2c-rtc,ds3231` # (see boot/firmware/config.txt.bubblecam-append) so /dev/rtc0 exists. # Leading "-": a missing/failed RTC must not fail the unit or stall boot -- # the system clock then just falls back to whatever the OS has. ExecStart=-/sbin/hwclock -s TimeoutStartSec=20 RemainAfterExit=yes [Install] WantedBy=basic.target