IRNAS / PiRA-zero-firmware

Firmware for PiRa Zero board
GNU General Public License v3.0
3 stars 4 forks source link

Fast-boot configuration #12

Open SloMusti opened 6 years ago

SloMusti commented 6 years ago

The goal of the system in configuration where it boots, takes an image with the camera and goes to sleep to achieve that in minimal time of about 8s.

Average power consumption 200mA, 8s duration is about 0.5mAh per boot cycle and thus photo. This allows for about 30000 photos to be taken with 6x 18650 2900mAh battery, assuming no charge.

One example of implementation: https://www.raspberrypi.org/forums/viewtopic.php?f=43&t=80421

SloMusti commented 6 years ago

https://hallard.me/raspberry-pi-read-only/

https://raspberrypi.stackexchange.com/a/39527

SloMusti commented 6 years ago

It may be a good idea that we make the partition /data as in resin that holds all the images, standalone of the system to avoid corruption. Then to make it read-only and go to sleep

SloMusti commented 6 years ago

Separate home partition: https://mike632t.wordpress.com/2014/02/10/resizing-partitions/

SloMusti commented 6 years ago

What investigation I have done with resin: https://github.com/resin-os/resinos/issues/256#issuecomment-347202946

gorankecman commented 6 years ago

Following has been tried:

  1. To disable networking as suggested here: https://raspberrypi.stackexchange.com/questions/38660/what-can-i-remove-from-raspbian-to-boot-faster/39527#39527 but I was not successful.
  2. I have added quiet to /boot/cmdline.txt and that saved ~1.2s of boot time.
  3. I have tried to follow https://hallard.me/raspberry-pi-read-only/ but got some errors for certain commands and it was not successful at the end. System was still in read-write mode.

More time is needed to analyze boot procedure and to see how we can reduce boot time.

gorankecman commented 6 years ago

On my Pi system, output of systemd-analyze and systemd-analyze blame commands:

$ systemd-analyze Startup finished in 2.952s (kernel) + 1min 31.619s (userspace) = 1min 34.571s

$ systemd-analyze blame 10.673s dhcpcd.service 6.631s dev-mmcblk0p2.device 4.979s apt-daily.service 4.910s networking.service 3.822s apt-daily-upgrade.service 3.354s keyboard-setup.service 2.945s dphys-swapfile.service 1.739s systemd-logind.service 1.638s rsyslog.service 1.587s systemd-udev-trigger.service 1.507s triggerhappy.service 1.151s systemd-timesyncd.service 1.146s raspi-config.service 1.140s avahi-daemon.service 1.121s alsa-restore.service 1.104s systemd-udevd.service 1.103s systemd-journald.service 954ms fake-hwclock.service 891ms systemd-fsck-root.service 866ms dev-mqueue.mount 853ms sys-kernel-debug.mount 836ms kmod-static-nodes.service 721ms systemd-modules-load.service 703ms systemd-remount-fs.service 691ms systemd-tmpfiles-setup.service 570ms systemd-fsck@dev-disk-by\x2dpartuuid-db1abe6b\x2d01.service 551ms ssh.service 539ms systemd-update-utmp.service 518ms run-rpc_pipefs.mount 512ms systemd-tmpfiles-setup-dev.service 494ms systemd-journal-flush.service 422ms systemd-sysctl.service 380ms sys-kernel-config.mount 372ms console-setup.service 329ms nfs-config.service 291ms systemd-random-seed.service 291ms plymouth-read-write.service 283ms user@1000.service 256ms plymouth-start.service 164ms boot.mount 162ms systemd-user-sessions.service 145ms rc-local.service 130ms plymouth-quit.service 130ms plymouth-quit-wait.service 117ms systemd-update-utmp-runlevel.service 84ms systemd-tmpfiles-clean.service

gorankecman commented 6 years ago

After adding quiet to /boot/cmdline.txt this is the output of systemd-analyze critical-chain:

graphical.target @1min 31.444s └─multi-user.target @1min 31.444s └─ssh.service @21.366s +571ms └─network.target @21.351s └─dhcpcd.service @11.851s +9.484s └─basic.target @10.539s └─sockets.target @10.538s └─dbus.socket @10.510s └─sysinit.target @10.453s └─systemd-timesyncd.service @9.571s +867ms └─systemd-tmpfiles-setup.service @8.652s +815ms └─local-fs.target @8.553s └─run-user-1000.mount @30.910s └─local-fs-pre.target @5.260s └─keyboard-setup.service @1.482s +3.773s └─systemd-journald.socket @1.373s └─-.mount @1.163s └─system.slice @1.315s └─-.slice @1.163s

gorankecman commented 6 years ago

For the future reference, following steps have to be done in order to create Ethernet Gadget from RaspberryPi Zero:

  1. Download Raspbian Lite image and "burn" it to SD card as usual.
  2. Add empty file ssh without any extension to /boot/ directory.
  3. Change file /boot/config.txt and at the end, add the line dtoverlay=dwc2.
  4. Change file /boot/cmdline.txt and after the word rootwait add modules-load=dwc2,g_ether

If Raspbian Jessie is used, everything should work. If Raspbian Stretch is used, SSH has to be enabled through raspi-config. Connection to RaspberryPi should be possible through SSH (ssh pi@<ipaddress> or ssh pi@raspberrypi.local).

gorankecman commented 6 years ago

We have following conclusions regarding boot time:

Arch Linux - first startup
[alarm@alarmpi ~]$ systemd-analyze 
Startup finished in 13.836s (kernel) + 11.915s (userspace) = 25.752s
[alarm@alarmpi ~]$ systemd-analyze blame
          4.485s dev-mmcblk0p2.device
          2.587s systemd-logind.service
          2.318s systemd-user-sessions.service
          1.814s systemd-tmpfiles-setup.service
          1.673s systemd-resolved.service
          1.526s systemd-update-done.service
          1.385s systemd-journal-flush.service
          1.297s systemd-udev-trigger.service
           951ms systemd-journald.service
           803ms systemd-tmpfiles-setup-dev.service
           693ms systemd-timesyncd.service
           651ms user@1000.service
           626ms sys-kernel-debug.mount
           611ms systemd-update-utmp.service
           582ms ldconfig.service
           544ms systemd-udevd.service
           543ms tmp.mount
           539ms dev-mqueue.mount
           477ms kmod-static-nodes.service
           474ms systemd-remount-fs.service
           419ms systemd-journal-catalog-update.service
           387ms systemd-modules-load.service
           360ms systemd-sysctl.service
           350ms systemd-networkd.service
           312ms sys-kernel-config.mount
           308ms systemd-random-seed.service
           282ms boot.mount
           240ms systemd-sysusers.service
Arch Linux - after reboot
[alarm@alarmpi ~]$ systemd-analyze 
Startup finished in 7.866s (kernel) + 11.931s (userspace) = 19.797s
[alarm@alarmpi ~]$ systemd-analyze blame
          4.650s dev-mmcblk0p2.device
          1.819s systemd-udev-trigger.service
          1.468s ldconfig.service
          1.261s systemd-resolved.service
          1.008s systemd-udevd.service
           954ms systemd-tmpfiles-setup.service
           878ms systemd-update-utmp.service
           839ms user@1000.service
           783ms systemd-timesyncd.service
           764ms sys-kernel-debug.mount
           742ms systemd-logind.service
           737ms systemd-remount-fs.service
           713ms systemd-journal-flush.service
           713ms systemd-journald.service
           698ms kmod-static-nodes.service
           610ms systemd-modules-load.service
           453ms dev-mqueue.mount
           451ms systemd-journal-catalog-update.service
           381ms systemd-networkd.service
           317ms systemd-user-sessions.service
           310ms sys-kernel-config.mount
           306ms systemd-sysusers.service
           262ms systemd-update-done.service
           262ms systemd-tmpfiles-setup-dev.service
           247ms systemd-sysctl.service
           244ms boot.mount
           242ms systemd-random-seed.service
           147ms tmp.mount
Arch Linux - after shutdown
[alarm@alarmpi ~]$ systemd-analyze 
Startup finished in 8.985s (kernel) + 11.314s (userspace) = 20.300s
[alarm@alarmpi ~]$ systemd-analyze blame
          3.975s dev-mmcblk0p2.device
          1.821s systemd-udev-trigger.service
          1.542s systemd-timesyncd.service
           995ms systemd-resolved.service
           977ms systemd-update-utmp.service
           912ms systemd-update-done.service
           824ms systemd-journald.service
           703ms systemd-journal-flush.service
           660ms systemd-user-sessions.service
           649ms user@1000.service
           619ms dev-mqueue.mount
           610ms ldconfig.service
           577ms sys-kernel-debug.mount
           566ms systemd-remount-fs.service
           534ms systemd-tmpfiles-setup.service
           517ms systemd-udevd.service
           464ms systemd-journal-catalog-update.service
           422ms systemd-logind.service
           403ms tmp.mount
           397ms kmod-static-nodes.service
           363ms systemd-sysctl.service
           343ms systemd-modules-load.service
           338ms systemd-tmpfiles-setup-dev.service
           299ms systemd-networkd.service
           279ms systemd-random-seed.service
           265ms sys-kernel-config.mount
           236ms systemd-sysusers.service
           201ms boot.mount

Ethernet gadget Raspbian output:

pi@raspberrypi:~ $ systemd-analyze 
Startup finished in 1.680s (kernel) + 21.676s (userspace) = 23.357s
pi@raspberrypi:~ $ systemd-analyze blame
         11.750s dhcpcd.service
          2.019s keyboard-setup.service
          1.951s networking.service
          1.744s systemd-modules-load.service
          1.170s kbd.service
          1.006s systemd-logind.service
           994ms dphys-swapfile.service
           991ms console-setup.service
           878ms alsa-restore.service
           759ms systemd-journal-flush.service
           734ms systemd-fsck-root.service
           674ms triggerhappy.service
           636ms systemd-setup-dgram-qlen.service
           608ms fake-hwclock.service
           591ms raspi-config.service
           562ms avahi-daemon.service
           545ms systemd-fsck@dev-disk-by\x2dpartuuid-2691b8e1\x2d01.service
           479ms dev-mqueue.mount
           468ms systemd-udev-trigger.service
           438ms ntp.service
           365ms systemd-tmpfiles-setup.service
           342ms sys-kernel-debug.mount
           303ms kmod-static-nodes.service
           291ms plymouth-read-write.service
           269ms systemd-remount-fs.service
           247ms plymouth-start.service
           246ms rsyslog.service
           204ms sys-kernel-config.mount
           173ms rc-local.service
           149ms systemd-tmpfiles-setup-dev.service
           135ms plymouth-quit-wait.service
           133ms systemd-update-utmp.service
           116ms systemd-user-sessions.service
           109ms systemd-udevd.service
            99ms plymouth-quit.service
            96ms udev-finish.service
            83ms systemd-random-seed.service
            76ms systemd-sysctl.service
            70ms boot.mount
            68ms systemd-update-utmp-runlevel.service
gorankecman commented 6 years ago

For the future reference, in order to enable console output, UART should be enabled:

gorankecman commented 6 years ago

After disabling following services:

dhcpcd.service
networking.service
keyboard-setup.service

we have reduced boot time to:

pi@raspberrypi:~ $ systemd-analyze 
Startup finished in 864ms (kernel) + 8.123s (userspace) = 8.987s

Service is disabled by executing following commands:

sudo systemctl stop <service_name>
sudo systemctl disable <service_name>

Additionally, quiet is added to /boot/cmdline.txt.

gorankecman commented 6 years ago

Next step is to execute the script to take a photo with the camera at startup and to mark the time. For this, we need to figure out how to startup Pi without the need to type the password.

gorankecman commented 6 years ago

For documentation purposes: In order to measure time since login to the first image made, we need to boot Pi without entering login credentials. Since we are currently accessing console through UART, we need to change startup service /lib/systemd/system/serial-getty@.service Find line: ExecStart=-/sbin/agetty --keep-baud 115200,38400,9600 %I $TERM and modify it to: ExecStart=-/sbin/agetty --autologin pi --keep-baud 115200,38400,9600 %I $TERM

This will prevent Pi from asking for login credentials.

gorankecman commented 6 years ago

For documentation purposes: With new init system used - systemd, we needed a way how to execute scripts at startup. In order to do that, we need to create, enable and start service which will be executed during the boot procedure. First, we need to create file /lib/systemd/system/cameratest.service. This file should contain following (for bash script):

[Unit]
Description=Camera Test Service
After=multi-user.target

[Service]
Type=idle
ExecStart=/bin/bash /home/pi/test_script.sh

[Install]
WantedBy=multi-user.target

All the paths in the service and script should be absolute paths. Then, we need to start and enable the service by executing following commands:

sudo systemctl daemon-reload
sudo systemctl enable cameratest.service
sudo systemctl start cameratest.service

After reboot, the system should execute test_script.sh. In order to measure the time needed to take the first photo, we can create bash script as follows:

#!/bin/bash

raspistill -o /home/pi/startup_image.jpg
systemd-analyze > /home/pi/log.txt
cat /proc/uptime >> /home/pi/log.txt
gorankecman commented 6 years ago

According to the latest log, startup lasts 9.789s and the first photo is captured after 16.13s.

pi@raspberrypi:~$ cat log.txt
Startup finished in 863ms (kernel) + 8.925s (userspace) = 9.789s
16.13 4.23

Next step is to execute shutdown after taking the photo and to measure how much time we need from the startup until the system shuts down.

gorankecman commented 6 years ago

After testing with shutdown included in the script following results are acquired:

Startup finished in 864ms (kernel) + 8.903s (userspace) = 9.768s
16.10 4.24 //16.10s is up time since startup until taking the photo is finished.

From the waveform attached, shutdown time can be derived to be ~6s. shutdown

gorankecman commented 6 years ago

For documentation purposes: In case when the network is not available and gpio utility is not installed by default, we can use direct writing to files in order to control GPIO pins. First we have to execute following commands to set which GPIO pin we want to use (in this case GPIO 16) and which direction that pin should be (output in this case):

sudo echo "16" > /sys/class/gpio/export
sudo echo "out" > /sys/class/gpio/gpio16/direction

Then we can write to this GPIO by executing following commands:

sudo echo "1" > /sys/class/gpio/gpio16/value
sudo echo "0" > /sys/class/gpio/gpio16/value

More info available here.