Challenge

When developing firmware we have to deploy it very often to the test system. U-Boot typically is loaded from an SD card. So we end up juggling the SD card to and fro a lot. And this manual handling does not allow for automation.

Solution

The Tizen SDWire is a board that is inserted like an SD card into the test system. The SD card itself is mounted on the board. Via an USB interface the SD card can be disconnected from the test system, updated, and reconnected to the test system.

For switching the test system on and off a relay board (e.g. the Waveshare RPi relay board) can be used.

Test setup

Details

SDWire

The software to control the SDWire is available at https://git.tizen.org/cgit/tools/testlab/sd-mux/. The board can be connected to the test system with

sd-mux-ctrl -v 0 -td

and conncected to the controlling system with

sd-mux-ctrl -v 0 -ts

To allow a non-root user to access the board we can use a udev rule, e.g. in file /etc/udev/rules.d/60-sd-mux-ctrl.rules:

SUBSYSTEM=="usb", ATTR{idVendor}=="04e8", ATTR{idProduct}=="6001", GROUP="sd-mux-ctrl", MODE="660"

This rule grants access to all members of group sd-mux-ctrl. A second rule can be used to allow the group to access raw drive /dev/sda:

SUBSYSTEM=="block", KERNEL=="sda", GROUP="sd-mux-ctrl"

Relay Board

The Waveshare relay board can be controlled via the GPIOs of a Raspberry Pi. For the Raspberry Pi 3 Model B Plus Rev 1.3 the relevant GPIOs are 484, 478, and 479. We can use a small script to allow members of piwsrb to control the board via the command line easily:

#!/bin/sh
# SPDX-License-Identifier: BSD-2-Clause
#
# Copyright 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>

set -e

grep 'Raspberry Pi 3 Model B+' /proc/device-tree/model > /dev/null ||
grep 'Raspberry Pi 3 Model B Plus Rev 1.3' /proc/device-tree/model \
> /dev/null || (echo 'Unsupported device' && false)

export_gpio() {
        for i in 484 478 479
        do
                echo $i > /sys/class/gpio/export || true
                echo 1 > /sys/class/gpio/gpio$i/active_low
                echo out > /sys/class/gpio/gpio$i/direction
                echo 0 > /sys/class/gpio/gpio$i/value
                chown root:piwsrb /sys/class/gpio/gpio$i/value
                chmod 664 /sys/class/gpio/gpio$i/value
        done
}

unexport_gpio() {
        for i in 484 478 479
        do
                echo $i > /sys/class/gpio/unexport
        done
}

status_gpio() {
        n=1
        for i in 484 478 479
        do
                echo -n "Relay $n: "
                cat /sys/class/gpio/gpio$i/value
                n=$((n+1))
        done
}

usage() {
        echo Control WaveShare RPi Relay Board
        echo Usage:
        echo relay-card export   - enable GPIOs
        echo relay-card unexport - disable GPIOs
        echo relay-card off      - switch relay 1 off
        echo relay-card on       - switch relay 1 on
        echo relay-card reset    - switch relay 2 on for 1 second
        echo relay-card status   - display relay status
}

main() {
        case "$1" in
        export)
                export_gpio
                ;;
        unexport)
                unexport_gpio
                ;;
        on)
                echo 1 > /sys/class/gpio/gpio484/value
                ;;
        off)
                echo 0 > /sys/class/gpio/gpio484/value
                ;;
        reset)
                echo 0 > /sys/class/gpio/gpio484/value
                sleep 3
                echo 1 > /sys/class/gpio/gpio484/value
                ;;
        status)
                status_gpio
                ;;
        *)
                usage
                exit 1;
                ;;
        esac
}

A systemd service (file /etc/systemd/system/relay-card.service) can be used for automatically exporting the GPIOs.

# SPDX-License-Identifier: BSD-2-Clause
#
# Copyright 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>

[Unit]
Description=Waveshare RPi Relay/Expansion Board

[Service]
Type=oneshot
ExecStart=/usr/bin/relay-card export
RemainAfterExit=true

ExecStop=/usr/bin/relay-card unexport

[Install]
WantedBy=multi-user.target