Merge changes Ie6b43814,I6bbcafa9
* changes:
Redo timer math for spurrious events
Add scripts to modify a root filesystem for the vision pi
diff --git a/aos/events/event_loop.h b/aos/events/event_loop.h
index 6047cbc..d0ca196 100644
--- a/aos/events/event_loop.h
+++ b/aos/events/event_loop.h
@@ -344,8 +344,9 @@
protected:
TimerHandler(EventLoop *event_loop, std::function<void()> fn);
- void Call(std::function<monotonic_clock::time_point()> get_time,
- monotonic_clock::time_point event_time);
+ monotonic_clock::time_point Call(
+ std::function<monotonic_clock::time_point()> get_time,
+ monotonic_clock::time_point event_time);
private:
friend class EventLoop;
diff --git a/aos/events/event_loop_tmpl.h b/aos/events/event_loop_tmpl.h
index dfb5a6d..1daf88c 100644
--- a/aos/events/event_loop_tmpl.h
+++ b/aos/events/event_loop_tmpl.h
@@ -100,7 +100,7 @@
return false;
}
-inline void TimerHandler::Call(
+inline monotonic_clock::time_point TimerHandler::Call(
std::function<monotonic_clock::time_point()> get_time,
monotonic_clock::time_point event_time) {
CHECK_NOTNULL(timing_.timer);
@@ -131,6 +131,7 @@
monotonic_end_time - monotonic_start_time)
.count();
timing_.handler_time.Add(handler_latency);
+ return monotonic_start_time;
}
inline void PhasedLoopHandler::Call(
diff --git a/aos/events/shm_event_loop.cc b/aos/events/shm_event_loop.cc
index b3026fa..dad62cd 100644
--- a/aos/events/shm_event_loop.cc
+++ b/aos/events/shm_event_loop.cc
@@ -470,8 +470,14 @@
: TimerHandler(shm_event_loop, std::move(fn)),
shm_event_loop_(shm_event_loop),
event_(this) {
- shm_event_loop_->epoll_.OnReadable(
- timerfd_.fd(), [this]() { shm_event_loop_->HandleEvent(); });
+ shm_event_loop_->epoll_.OnReadable(timerfd_.fd(), [this]() {
+ // The timer may fire spurriously. HandleEvent on the event loop will
+ // call the callback if it is needed. It may also have called it when
+ // processing some other event, and the kernel decided to deliver this
+ // wakeup anyways.
+ timerfd_.Read();
+ shm_event_loop_->HandleEvent();
+ });
}
~TimerHandlerState() {
@@ -480,22 +486,29 @@
}
void HandleEvent() {
- uint64_t elapsed_cycles = timerfd_.Read();
- if (elapsed_cycles == 0u) {
- // We got called before the timer interrupt could happen, but because we
- // are checking the time, we got called on time. Push the timer out by 1
- // cycle.
- elapsed_cycles = 1u;
- timerfd_.SetTime(base_ + repeat_offset_, repeat_offset_);
+ CHECK(!event_.valid());
+ const auto monotonic_now = Call(monotonic_clock::now, base_);
+ if (event_.valid()) {
+ // If someone called Setup inside Call, rescheduling is already taken care
+ // of. Bail.
+ return;
}
- Call(monotonic_clock::now, base_);
+ if (repeat_offset_ == chrono::seconds(0)) {
+ timerfd_.Disable();
+ } else {
+ // Compute how many cycles have elapsed and schedule the next iteration
+ // for the next iteration in the future.
+ const int elapsed_cycles =
+ std::max<int>(0, (monotonic_now - base_ + repeat_offset_ -
+ std::chrono::nanoseconds(1)) /
+ repeat_offset_);
+ base_ += repeat_offset_ * elapsed_cycles;
- base_ += repeat_offset_ * elapsed_cycles;
-
- if (repeat_offset_ != chrono::seconds(0)) {
+ // Update the heap and schedule the timerfd wakeup.
event_.set_event_time(base_);
shm_event_loop_->AddEvent(&event_);
+ timerfd_.SetTime(base_, chrono::seconds(0));
}
}
diff --git a/aos/starter/starter.sh b/aos/starter/starter.sh
index c5af65a..f5b14a5 100755
--- a/aos/starter/starter.sh
+++ b/aos/starter/starter.sh
@@ -1,10 +1,15 @@
#!/bin/bash
-# NI already has a core pattern, so we probably shouldn't change it.
-#echo '/home/driver/tmp/robot_logs/%e-%s-%p-%t.coredump' > /proc/sys/kernel/core_pattern
-ln -s /var/local/natinst/log/FRC_UserProgram.log /tmp/FRC_UserProgram.log
-ROBOT_CODE="/home/admin/robot_code"
+if [[ "$(hostname)" == "roboRIO"* ]]; then
+ ROBOT_CODE="/home/admin/robot_code"
+
+ ln -s /var/local/natinst/log/FRC_UserProgram.log /tmp/FRC_UserProgram.log
+ ln -s /var/local/natinst/log/FRC_UserProgram.log "${ROBOT_CODE}/FRC_UserProgram.log"
+else
+ ROBOT_CODE="${HOME}/robot_code"
+fi
+
cd "${ROBOT_CODE}"
export PATH="${PATH}:${ROBOT_CODE}"
while true; do
diff --git a/y2020/vision/rootfs/README b/y2020/vision/rootfs/README
new file mode 100644
index 0000000..2320774
--- /dev/null
+++ b/y2020/vision/rootfs/README
@@ -0,0 +1,16 @@
+This modifies a stock debian root filesystem to be able to operate as a vision
+pi. It is not trying to be reproducible, but should be good enough for FRC
+purposes.
+
+The default hostname and IP is pi-8971-1, 10.89.71.101.
+ Username pi, password raspberry.
+
+Download 2020-02-13-raspbian-buster-lite.img (or equivalent) and edit
+modify_rootfs.sh to point to it. Run modify_rootfs.sh to build the filesystem
+(you might need to hit return in a spot or two).
+
+After confirming the target device, deploy with
+ dd if=2020-02-13-raspbian-buster-lite.img of=/dev/sdX
+
+From there, log in, sudo to root, and run /root/bin/change_hostname.sh to
+change the hostname to the actual target.
diff --git a/y2020/vision/rootfs/change_hostname.sh b/y2020/vision/rootfs/change_hostname.sh
new file mode 100755
index 0000000..1842504
--- /dev/null
+++ b/y2020/vision/rootfs/change_hostname.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+set -euo pipefail
+
+HOSTNAME="$1"
+
+if [[ ! "${HOSTNAME}" =~ ^pi-[0-9]*-[0-9]$ ]]; then
+ echo "Invalid hostname ${HOSTNAME}, needs to be pi-[team#]-[pi#]"
+ exit 1
+fi
+
+TEAM_NUMBER="$(echo ${HOSTNAME} | sed 's/pi-\(.*\)-.*/\1/')"
+PI_NUMBER="$(echo ${HOSTNAME} | sed 's/pi-.*-\(.*\)/\1/')"
+IP_BASE="$(echo ${TEAM_NUMBER} | sed 's/\(.*\)\(..\)/10.\1.\2/')"
+IP="${IP_BASE}.$(( 100 + ${PI_NUMBER}))"
+
+echo "Changing to team number ${TEAM_NUMBER}, IP ${IP}"
+
+sed -i "s/^static ip_address=.*$/static ip_address=${IP}\/24/" /etc/dhcpcd.conf
+
+sed -i "s/\(127\.0\.1\.1\t\).*$/\1${HOSTNAME}/" /etc/hosts
+
+echo "${HOSTNAME}" > /etc/hostname
+
+if grep /etc/hosts '^10\.[0-9]*\.[0-9]*\.[0-9]*\s*pi-[0-9]*-[0-9] pi[0-9]$' /etc/hosts >/dev/null ;
+then
+ sed -i "s/^10\.[0-9]*\.[0-9]*\(\.[0-9]*\s*pi-\)[0-9]*\(-[0-9] pi[0-9]\)$/${IP_BASE}\1${TEAM_NUMBER}\2/" /etc/hosts
+else
+ for i in {1..6}; do
+ echo -e "${IP_BASE}.$(( i + 100 ))\tpi-${TEAM_NUMBER}-${i} pi${i}" >> /etc/hosts
+ done
+fi
+
+if grep '^10\.[0-9]*\.[0-9]*\.2\s*roborio$' /etc/hosts >/dev/null;
+then
+ sed -i "s/^10\.[0-9]*\.[0-9]*\(\.2\s*roborio\)$/${IP_BASE}\1/" /etc/hosts
+else
+ echo -e "${IP_BASE}.2\troborio" >> /etc/hosts
+fi
+
diff --git a/y2020/vision/rootfs/dhcpcd.conf b/y2020/vision/rootfs/dhcpcd.conf
new file mode 100644
index 0000000..43a54b7
--- /dev/null
+++ b/y2020/vision/rootfs/dhcpcd.conf
@@ -0,0 +1,59 @@
+# A sample configuration for dhcpcd.
+# See dhcpcd.conf(5) for details.
+
+# Allow users of this group to interact with dhcpcd via the control socket.
+#controlgroup wheel
+
+# Inform the DHCP server of our hostname for DDNS.
+hostname
+
+# Use the hardware address of the interface for the Client ID.
+clientid
+# or
+# Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361.
+# Some non-RFC compliant DHCP servers do not reply with this set.
+# In this case, comment out duid and enable clientid above.
+#duid
+
+# Persist interface configuration when dhcpcd exits.
+persistent
+
+# Rapid commit support.
+# Safe to enable by default because it requires the equivalent option set
+# on the server to actually work.
+option rapid_commit
+
+# A list of options to request from the DHCP server.
+option domain_name_servers, domain_name, domain_search, host_name
+option classless_static_routes
+# Respect the network MTU. This is applied to DHCP routes.
+option interface_mtu
+
+# Most distributions have NTP support.
+#option ntp_servers
+
+# A ServerID is required by RFC2131.
+require dhcp_server_identifier
+
+# Generate SLAAC address using the Hardware Address of the interface
+#slaac hwaddr
+# OR generate Stable Private IPv6 Addresses based from the DUID
+slaac private
+
+# Example static IP configuration:
+interface eth0
+static ip_address=10.89.71.102/24
+#static ip6_address=fd51:42f8:caae:d92e::ff/64
+#static routers=192.168.0.1
+#static domain_name_servers=192.168.0.1 8.8.8.8 fd51:42f8:caae:d92e::1
+
+# It is possible to fall back to a static IP if DHCP fails:
+# define static profile
+#profile static_eth0
+#static ip_address=192.168.1.23/24
+#static routers=192.168.1.1
+#static domain_name_servers=192.168.1.1
+
+# fallback to static profile on eth0
+#interface eth0
+#fallback static_eth0
diff --git a/y2020/vision/rootfs/modify_rootfs.sh b/y2020/vision/rootfs/modify_rootfs.sh
new file mode 100755
index 0000000..c472caa
--- /dev/null
+++ b/y2020/vision/rootfs/modify_rootfs.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+set -xe
+
+IMAGE="2020-02-13-raspbian-buster-lite.img"
+PARTITION="2020-02-13-raspbian-buster-lite.img.partition"
+HOSTNAME="pi-8971-1"
+
+function target() {
+ HOME=/root/ USER=root sudo proot -0 -q qemu-arm-static -w / -r "${PARTITION}" "$@"
+}
+
+function user_pi_target() {
+ USER=root sudo proot -0 -q qemu-arm-static -w / -r "${PARTITION}" sudo -h 127.0.0.1 -u pi "$@"
+}
+
+OFFSET="$(fdisk -lu "${IMAGE}" | grep "${IMAGE}2" | awk '{print 512*$2}')"
+mkdir -p "${PARTITION}"
+
+if mount | grep "${PARTITION}" >/dev/null ;
+then
+ echo "Already mounted"
+else
+ echo "Mounting"
+ sudo mount -o loop,offset=${OFFSET} "${IMAGE}" "${PARTITION}"
+fi
+
+sudo cp target_configure.sh "${PARTITION}/tmp/"
+sudo cp dhcpcd.conf "${PARTITION}/tmp/dhcpcd.conf"
+sudo cp change_hostname.sh "${PARTITION}/tmp/change_hostname.sh"
+
+target /bin/mkdir -p /home/pi/.ssh/
+cat ~/.ssh/id_rsa.pub | target tee /home/pi/.ssh/authorized_keys
+
+target /bin/bash /tmp/target_configure.sh
+
+# Run a prompt as root inside the target to poke around and check things.
+target /bin/bash --rcfile /root/.bashrc
+
+sudo umount "${PARTITION}"
+rmdir "${PARTITION}"
diff --git a/y2020/vision/rootfs/target_configure.sh b/y2020/vision/rootfs/target_configure.sh
new file mode 100755
index 0000000..2a072e5
--- /dev/null
+++ b/y2020/vision/rootfs/target_configure.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+set -ex
+
+mkdir -p /root/bin
+
+# Give it a static IP
+cp /tmp/dhcpcd.conf /etc/
+
+# And provide a script to change it.
+cp /tmp/change_hostname.sh /root/bin/
+chmod a+x /root/bin/change_hostname.sh
+
+chown -R pi.pi /home/pi/.ssh
+
+apt-get install -y vim-nox \
+ git \
+ cpufrequtils
+
+echo 'GOVERNOR="performance"' > /etc/default/cpufrequtils
+
+# Add a .bashrc and friends for root.
+if [[ ! -e "/root/.dotfiles" ]]; then
+ cd /root/
+ git clone --separate-git-dir=/root/.dotfiles https://github.com/AustinSchuh/.dotfiles.git tmpdotfiles
+ rsync --recursive --verbose --exclude '.git' tmpdotfiles/ /root/
+ rm -r tmpdotfiles
+ git --git-dir=/root/.dotfiles/ --work-tree=/root/ config --local status.showUntrackedFiles no
+ # Run the vundle installer which installs plugins on the first run of vim.
+ vim -c ":qa!"
+fi
+
+# Add a .bashrc and friends for pi.
+if [[ ! -e "/home/pi/.dotfiles" ]]; then
+ cd /home/pi/
+ su -c "git clone --separate-git-dir=/home/pi/.dotfiles https://github.com/AustinSchuh/.dotfiles.git tmpdotfiles" pi
+ su -c "rsync --recursive --verbose --exclude '.git' tmpdotfiles/ /home/pi/" pi
+ su -c "rm -r tmpdotfiles" pi
+ su -c "git --git-dir=/home/pi/.dotfiles/ --work-tree=/home/pi/ config --local status.showUntrackedFiles no" pi
+ # Run the vundle installer which installs plugins on the first run of vim.
+ su -c "vim -c ':qa!'" pi
+fi
+
+# Make SSH work and not complain about pi being the username and pw still.
+rm -f /etc/profile.d/sshpwd.sh
+rm -f /etc/profile.d/wifi-check.sh
+
+systemctl enable ssh.service
+
+# Default us to pi-8971-1
+/root/bin/change_hostname.sh pi-8971-1