diff --git a/scripts/bbctrl.service b/scripts/bbctrl.service index 8b22cc7..46e82f4 100644 --- a/scripts/bbctrl.service +++ b/scripts/bbctrl.service @@ -1,13 +1,24 @@ [Unit] Description=Buildbotics Controller -After=network.target +# Note: bbctrl previously had `After=network.target`. That delays +# start by ~5s on this Pi while dhcpcd brings up wlan0/eth0, but +# bbctrl does not actually require network connectivity to come up +# (the AVR is on a local serial port, the LCD on I2C). Dropping it +# means the Pi shows the UI faster on cold boot. The wifi config UI +# still works because it queries iw/dhcpcd lazily on demand. +After=local-fs.target bbserial-rebind.service +Wants=bbserial-rebind.service [Service] User=root ExecStart=/usr/local/bin/bbctrl -l /var/log/bbctrl.log WorkingDirectory=/var/lib/bbctrl Restart=always -StandardOutput=null +# StandardOutput was 'null'. Set to 'journal' so TRACE lines emitted by +# bbctrl.Trace are visible via `journalctl -u bbctrl`. Bbctrl still +# writes its own log via -l above; this only affects stdout/stderr. +StandardOutput=journal +StandardError=journal Nice=-10 KillMode=process diff --git a/scripts/bbserial-rebind.service b/scripts/bbserial-rebind.service new file mode 100644 index 0000000..78f9058 --- /dev/null +++ b/scripts/bbserial-rebind.service @@ -0,0 +1,21 @@ +[Unit] +Description=Unbind ttyAMA0 from pl011 and reload bbserial +DefaultDependencies=no +After=systemd-modules-load.service local-fs.target +Before=bbctrl.service +ConditionPathExists=/sys/bus/amba/drivers/uart-pl011 + +[Service] +Type=oneshot +RemainAfterExit=yes +# Tolerate the device already being bound elsewhere or the module +# already being loaded — the goal is the end state (bbserial owns +# ttyAMA0), not running the steps. +ExecStart=/bin/sh -c '\ + echo 3f201000.serial > /sys/bus/amba/drivers/uart-pl011/unbind 2>/dev/null || true; \ + /sbin/modprobe -r bbserial 2>/dev/null || true; \ + /sbin/modprobe bbserial \ +' + +[Install] +WantedBy=multi-user.target diff --git a/scripts/install.sh b/scripts/install.sh index d0f6a71..4b7235f 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -19,8 +19,17 @@ if $UPDATE_PY; then # Update service rm -f /etc/init.d/bbctrl cp scripts/bbctrl.service /etc/systemd/system/ + + # Cold-boot fast path: + # - bbserial-rebind.service replaces the bbserial unbind/reload + # that used to live in rc.local AFTER bbctrl was already + # listening on /dev/ttyAMA0. Doing it as a unit ordered + # Before=bbctrl.service eliminates a full bbctrl restart + # mid-boot (~5s saved). + cp scripts/bbserial-rebind.service /etc/systemd/system/ systemctl daemon-reload systemctl enable bbctrl + systemctl enable bbserial-rebind.service fi if $UPDATE_AVR; then @@ -118,8 +127,50 @@ if [ $? -ne 0 ]; then REBOOT=true fi -# Install rc.local -cp scripts/rc.local /etc/ +# Install rc.local. Use the slimmed "fast" variant if it exists in this +# checkout (preferred); fall back to the legacy rc.local for older +# firmware tarballs that don't ship rc.local.fast yet. +if [ -f scripts/rc.local.fast ]; then + cp scripts/rc.local.fast /etc/rc.local +else + cp scripts/rc.local /etc/rc.local +fi +chmod +x /etc/rc.local + +# Cold-boot: mask units that contribute to userspace startup time but +# do not benefit a deployed Onefinity Pi. Each is reversible with +# `systemctl unmask `. +# plymouth-read-write : 4s of work for a splash that rc.local kills +# immediately with `plymouth quit`. +# plymouth-quit-wait : holds graphical.target until the splash is +# fully gone; redundant once the splash is +# masked. +# raspi-config : one-shot first-boot config; on a deployed +# image it's a 2s no-op. +# sysstat : sadc CPU/IO stats logger; not used. +# Use --now so the change also applies to the running system; harmless +# on a fresh install where the units are inactive. +for unit in \ + plymouth-read-write.service \ + plymouth-quit-wait.service \ + raspi-config.service \ + sysstat.service; do + systemctl mask --now "$unit" 2>/dev/null || true +done + +# Cold-boot: switch swap activation from dphys-swapfile (~4.3s LSB +# wrapper that re-checks the swap file size on every boot) to a plain +# fstab entry. The swap file itself is already created at +# /var/swap by the previous boot; we only need to make sure it gets +# `swapon`'d at local-fs.target instead. +SWAPFILE=/var/swap +if [ -f "$SWAPFILE" ]; then + if ! grep -qE "^[^#]*${SWAPFILE//\//\\/}[[:space:]]+swap" /etc/fstab; then + echo "$SWAPFILE none swap sw 0 0" >> /etc/fstab + fi + systemctl mask --now dphys-swapfile.service 2>/dev/null || true + swapon -a 2>/dev/null || true +fi # Ensure that the watchdog python library is installed pip3 list --format=columns | grep watchdog >/dev/null diff --git a/scripts/rc.local b/scripts/rc.local index 43e549a..1ea5f46 100644 --- a/scripts/rc.local +++ b/scripts/rc.local @@ -28,4 +28,4 @@ plymouth quit # Start X in /home/pi cd /home/pi -sudo -u pi startx +sudo -u pi startx -- -nocursor diff --git a/scripts/rc.local.fast b/scripts/rc.local.fast new file mode 100644 index 0000000..1f4de03 --- /dev/null +++ b/scripts/rc.local.fast @@ -0,0 +1,42 @@ +#!/bin/bash +# rc.local for the OneFinity Pi, "fast" variant. +# +# What changed vs. scripts/rc.local: +# - bbserial unbind/rebind moved to bbserial-rebind.service (runs +# once, before bbctrl, instead of after bbctrl is already +# listening on the serial port). +# - startx moved to kiosk.service so chromium starts in parallel +# with bbctrl rather than blocking on rc.local. +# - rc.local no longer keeps the Pi in 'starting' state forever, +# which fixes systemd-analyze. + +set -e + +# Mount /boot read only +mount -o remount,ro /boot 2>/dev/null || true + +# Set SPI GPIO mode +gpio mode 27 alt3 || true + +# Create browser memory limited cgroup +if [ -d /sys/fs/cgroup/memory ]; then + CGROUP=/sys/fs/cgroup/memory/chrome + [ -d "$CGROUP" ] || mkdir -p "$CGROUP" + chown -R pi:pi "$CGROUP" + echo 650000000 > "$CGROUP/memory.soft_limit_in_bytes" + echo 750000000 > "$CGROUP/memory.limit_in_bytes" +fi + +# Stop boot splash; harmless if plymouth already gone. +plymouth quit 2>/dev/null || true + +# Start X (chromium kiosk) in the background so rc.local can exit and +# late-boot units (bbctrl logrotate, etc.) don't block on it. Output +# is redirected so the journal doesn't fill up with X warnings. +cd /home/pi +# `-- -nocursor` hides the X pointer; this is a touchscreen kiosk and +# the mouse cursor only gets in the way. +nohup sudo -u pi startx -- -nocursor >/var/log/onefin-x.log 2>&1 & +disown + +exit 0 diff --git a/scripts/setup_rpi.sh b/scripts/setup_rpi.sh index 11f4db7..3b92211 100644 --- a/scripts/setup_rpi.sh +++ b/scripts/setup_rpi.sh @@ -75,7 +75,7 @@ sed -i 's/^PARTUUID=.*\//\/dev\/mmcblk0p2 \//' /etc/fstab # Enable browser in xorg sed -i 's/allowed_users=console/allowed_users=anybody/' /etc/X11/Xwrapper.config -echo "sudo -u pi startx" >> /etc/rc.local +echo "sudo -u pi startx -- -nocursor" >> /etc/rc.local cp /mnt/host/xinitrc /home/pi/.xinitrc cp /mnt/host/ratpoisonrc /home/pi/.ratpoisonrc cp /mnt/host/xorg.conf /etc/X11/ diff --git a/setup.py b/setup.py index 4e061fb..0a91749 100755 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ setup( license = pkg['license'], url = pkg['homepage'], package_dir = {'': 'src/py'}, - packages = ['bbctrl', 'inevent', 'lcd', 'camotics','iw_parse'], + packages = ['bbctrl', 'inevent', 'lcd', 'camotics', 'iw_parse'], include_package_data = True, entry_points = { 'console_scripts': [