FBTFT shield image build process - notro/fbtft GitHub Wiki

This is the receipe used to build the custom FBTFT image for shields.

The first part is done on the Raspberry Pi itself.

Start with a fresh image: 2014-01-07-wheezy-raspbian

TODO

List of things to fix in the next release.

  • Remove bash_history
sudo rm /media/rootfs/root/.bash_history

Preparation

Expand root file system size.

sudo raspi-config
# Expand Filesystem

Packages

sudo apt-get update && sudo apt-get -y install zip kpartx cmake

Update rpi-update

sudo wget https://raw.github.com/Hexxeh/rpi-update/master/rpi-update -O /usr/bin/rpi-update && sudo chmod +x /usr/bin/rpi-update

Mount Image

Set variables

IMAGE=2014-01-07-wheezy-raspbian
FBTFT=2014-02-03-fbtft

Get and prepare image

cd && scp [email protected]:/home/pi/images/$IMAGE.zip .

unzip $IMAGE.zip && mv $IMAGE.img $IMAGE-$FBTFT.img

Mount image partitions

sudo mkdir -p /media/{bootfs,rootfs}
sudo losetup /dev/loop0 $IMAGE-$FBTFT.img
sudo kpartx -a /dev/loop0
sudo mount /dev/mapper/loop0p1 /media/bootfs
sudo mount /dev/mapper/loop0p2 /media/rootfs

Make changes

Expand filesystem on first boot if /boot/expand_rootfs exists
Don't start raspi-config on the console (doesn't fit small displays)

cat <<EOF | sudo tee /media/bootfs/expand_rootfs
Delete this file to prevent filesystem expansion on first boot
EOF

cat <<EOF | sudo tee /media/rootfs/etc/profile.d/raspi-config.sh
rm -f /etc/profile.d/raspi-config.sh
if [ ! -e /boot/expand_rootfs ]; then
	exit 0
fi
printf "Expanding filesystem...\n\n"
rm -f /boot/expand_rootfs
raspi-config --expand-rootfs
sed -i /etc/inittab \
  -e "s/^#\(.*\)#\s*RPICFG_TO_ENABLE\s*/\1/" \
  -e "/#\s*RPICFG_TO_DISABLE/d"
telinit q
sync
reboot
EOF

Update rpi-update

sudo cp -a /usr/bin/rpi-update /media/rootfs/usr/bin/rpi-update

Set evironment variables for rpi-update

cat <<EOF | sudo tee /media/rootfs/etc/profile.d/rpi-update.sh
export REPO_URI=https://github.com/notro/rpi-firmware
export BRANCH=builtin
EOF

# Let the environment variables pass through when using sudo
cat <<EOF | sudo tee /media/rootfs/etc/sudoers.d/rpi-update
Defaults env_keep += "REPO_URI BRANCH"
EOF
sudo chmod 0440 /media/rootfs/etc/sudoers.d/rpi-update

Install kernel and modules.

sudo rm -rf /media/rootfs/lib/modules/*
sudo BRANCH=builtin UPDATE_SELF=0 ROOT_PATH=/media/rootfs BOOT_PATH=/media/bootfs WORK_PATH=~/rpi-firmware REPO_URI=https://github.com/notro/rpi-firmware rpi-update

# /boot/.firmware_revision and /root/.rpi-firmware/bootcode.bin is needed to determine if a update is needed
sudo mkdir /media/rootfs/root/.rpi-firmware && sudo touch /media/rootfs/root/.rpi-firmware/bootcode.bin

sudo rm -rf /media/bootfs.bak /media/rootfs/lib/modules.bak

Install fbcp

cd && git clone https://github.com/tasanakorn/rpi-fbcp
mkdir -p rpi-fbcp/build && cd rpi-fbcp/build
cmake .. && make
sudo install fbcp /media/rootfs/usr/local/bin/fbcp

fbcp service

sudo nano /media/rootfs/etc/init.d/fbcp

content

#!/bin/sh
### BEGIN INIT INFO
# Provides:          fbcp
# Required-Start:    $local_fs $remote_fs
# Required-Stop:     $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Framebuffer copy daemon fb0->fb1
### END INIT INFO

# Author: Noralf Tronnes <[email protected]>

PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="Framebuffer copy daemon"
NAME=fbcp
DAEMON=/usr/local/bin/fbcp
DAEMON_ARGS=""
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

# Exit if the package is not installed
[ -x $DAEMON ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
. /lib/lsb/init-functions

#
# Function that starts the daemon/service
#
do_start()
{
        # Return
        #   0 if daemon has been started
        #   1 if daemon was already running
        #   2 if daemon could not be started
        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
                || return 1
        start-stop-daemon --start --quiet --background --make-pidfile --pidfile $PIDFILE --exec $DAEMON -- \
                $DAEMON_ARGS \
                || return 2
}

#
# Function that stops the daemon/service
#
do_stop()
{
        # Return
        #   0 if daemon has been stopped
        #   1 if daemon was already stopped
        #   2 if daemon could not be stopped
        #   other if a failure occurred
        start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
        RETVAL="$?"
        [ "$RETVAL" = 2 ] && return 2
        rm -f $PIDFILE
        return "$RETVAL"
}

case "$1" in
  start)
    [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME"
    do_start
    case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
  ;;
  stop)
        [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
        do_stop
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  status)
       status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
       ;;
  restart|reload|force-reload)
        log_daemon_msg "Restarting $DESC" "$NAME"
        do_stop
        case "$?" in
          0|1)
                do_start
                case "$?" in
                        0) log_end_msg 0 ;;
                        1) log_end_msg 1 ;; # Old process is still running
                        *) log_end_msg 1 ;; # Failed to start
                esac
                ;;
          *)
                # Failed to stop
                log_end_msg 1
                ;;
        esac
        ;;
  *)
        echo "Usage: $SCRIPTNAME {start|stop|status|restart|reload|force-reload}" >&2
        exit 3
        ;;
esac

:

Make script executable

sudo chmod +x /media/rootfs/etc/init.d/fbcp

Add gpio utility

cd && git clone git://git.drogon.net/wiringPi
cd wiringPi

cd wiringPi && make && sudo make install
cd ../devLib && make && sudo make install
cd ../gpio && make && sudo make install

DESTDIR=/media/rootfs
PREFIX=/usr/local
cd ..
cd wiringPi && sudo make DESTDIR=${DESTDIR} PREFIX=${PREFIX} install
cd ../devLib && sudo make DESTDIR=${DESTDIR} PREFIX=${PREFIX} install
cd ../gpio && sudo make DESTDIR=${DESTDIR} PREFIX=${PREFIX} install

sudo ldconfig -r /media/rootfs

Install xinput_calibrator

sudo apt-get -y install autoconf libx11-dev libxext-dev libxi-dev x11proto-input-dev
cd && git clone https://github.com/tias/xinput_calibrator
cd xinput_calibrator
# First run fails: configure.ac:34: error: possibly undefined macro: AC_PROG_LIBTOOL
./autogen.sh -h
./autogen.sh --prefix=/media/rootfs && make && sudo make install

Install packages

sudo chroot /media/rootfs
mount -t proc none /proc/ && mount -t sysfs none /sys/ 

apt-get update && apt-get -y install \
tslib libts-bin evtest \
xinput \
python-pip
# Ignore this: Can not write log, openpty() failed (/dev/pts not mounted?)

# Disable this package as it contains a kernel, and thus removes the FBTFT drivers
apt-mark hold raspberrypi-bootloader

# clean up
apt-get clean && apt-get autoremove 
rm -rf /tmp/*

umount /proc && umount /sys
exit 

Fix X windows issue

sudo nano /media/rootfs/usr/share/X11/xorg.conf.d/99-fbturbo.conf

disable fbdev option

#        Option          "fbdev" "/dev/fb0"

Let startx by default come up on /dev/fb1

cat <<EOF | sudo tee /media/rootfs/etc/profile.d/startx_fb1.sh
export FRAMEBUFFER=/dev/fb1
EOF

cat <<EOF | sudo tee /media/rootfs/etc/sudoers.d/startx
Defaults env_keep += "FRAMEBUFFER"
EOF
sudo chmod 0440 /media/rootfs/etc/sudoers.d/startx

Add udev symlink rule: /dev/input/touchscreen

cat <<EOF | sudo tee /media/rootfs/etc/udev/rules.d/95-ads7846.rules
SUBSYSTEM=="input", KERNEL=="event[0-9]*", ATTRS{name}=="ADS7846*", SYMLINK+="input/touchscreen"
EOF

Set tslib environment variables

cat <<EOF | sudo tee /media/rootfs/etc/profile.d/tslib.sh
export TSLIB_TSDEVICE=/dev/input/touchscreen
export TSLIB_FBDEVICE=/dev/fb1
EOF

cat <<EOF | sudo tee /media/rootfs/etc/sudoers.d/tslib
Defaults env_keep += "TSLIB_TSDEVICE TSLIB_FBDEVICE"
EOF
sudo chmod 0440 /media/rootfs/etc/sudoers.d/tslib

Set SDL environment variables

cat <<EOF | sudo tee /media/rootfs/etc/profile.d/sdl.sh
export SDL_VIDEODRIVER=fbcon
export SDL_FBDEV=/dev/fb1
export SDL_MOUSEDRV=TSLIB
export SDL_MOUSEDEV=/dev/input/touchscreen
EOF

cat <<EOF | sudo tee /media/rootfs/etc/sudoers.d/sdl
Defaults env_keep += "SDL_VIDEODRIVER SDL_FBDEV SDL_MOUSEDRV SDL_MOUSEDEV"
EOF
sudo chmod 0440 /media/rootfs/etc/sudoers.d/sdl

Touch calibration startup script (X windows)

sudo wget -O /media/rootfs/etc/X11/Xsession.d/xinput_calibrator_pointercal https://raw.github.com/tias/xinput_calibrator/master/scripts/xinput_calibrator_pointercal.sh

cat <<EOF | sudo tee -a /media/rootfs/etc/xdg/lxsession/LXDE/autostart
sudo /bin/sh /etc/X11/Xsession.d/xinput_calibrator_pointercal
EOF

Unmount image and push it

Unmount partitions

sudo umount /media/bootfs
sudo umount /media/rootfs
sudo kpartx -d /dev/loop0
sudo losetup -d /dev/loop0

Push the image to a faster machine

cd && scp $IMAGE-$FBTFT.img [email protected]:/home/pi/images

Make customized images for shields

This is done on a faster machine

Prepare

cd ~/images
mkdir -p {bootfs,rootfs}

Build the various images

sudo ./stage2 <image produced further up>

Script: stage2

#!/bin/bash

set -e

function mount_image {
	losetup /dev/loop0 $1
	kpartx -a /dev/loop0
	mount /dev/mapper/loop0p1 bootfs
	mount /dev/mapper/loop0p2 rootfs
}


function umount_image {
	umount bootfs
	umount rootfs
	kpartx -d /dev/loop0
	losetup -d /dev/loop0
}

# make_image SRC SHIELD KCMD MOD
function make_image {
	echo
	echo
	echo Shield: $2
	echo Source: $1
	dst=$(basename $1 .img)-$2.img
	echo Destination: $dst
	echo Add to kernel command line: $3
	echo Add to /etc/modules: $4

	echo Copy image
	sudo -u pi cp -v $1 $dst

	echo Mount image
	mount_image $dst

	curr=$(cat bootfs/cmdline.txt)
	echo "${curr} ${3}" > bootfs/cmdline.txt

	echo -e $4 >> rootfs/etc/modules

	echo umount image
	umount_image

	echo Zip up image
	sudo -u pi zip -v $(basename $dst .img).zip $dst
#	rm $dst
}


SRC=$1

make_image $SRC \
	builtin \
	"fbtft_device.name=list fbtft_device.rotate=0 fbtft_device.debug=0 fbtft_device.verbose=0" \
	""

# DMA doesn't with RPi-Display because fbtft_write_spi_emulate_9() doesn't support DMA
make_image $SRC \
	RPi-Display \
	"fbtft_device.name=mi0283qt-9a fbtft_device.rotate=270 fbtft_device.gpios=reset:23,led:18 fbtft_device.debug=0 fbtft_device.verbose=0 fbcon=map:10 fbcon=font:ProFont6x11 logo.nologo" \
	"ads7846_device swap_xy=1 model=7846 cs=1 speed=2000000 gpio_pendown=25 pressure_max=255 x_plate_ohms=60"

make_image $SRC \
	hy28a \
	"fbtft.dma fbtft_device.name=hy28a fbtft_device.rotate=270 fbtft_device.speed=48000000 fbtft_device.fps=50 fbtft_device.debug=0 fbtft_device.verbose=0 fbcon=map:10 fbcon=font:ProFont6x11 logo.nologo" \
	"ads7846_device swap_xy=1 gpio_pendown=17 x_plate_ohms=100 pressure_max=255"

make_image $SRC \
	hy28b \
	"fbtft.dma fbtft_device.name=hy28b fbtft_device.rotate=90 fbtft_device.speed=48000000 fbtft_device.fps=50 fbtft_device.debug=0 fbtft_device.verbose=0 fbcon=map:10 fbcon=font:ProFont6x11 logo.nologo" \
	"ads7846_device swap_xy=1 gpio_pendown=17 x_plate_ohms=100 pressure_max=255"

make_image $SRC \
	tinylcd35 \
	"fbtft.dma fbtft_device.name=tinylcd35 fbtft_device.rotate=270 fbtft_device.speed=48000000 fbtft_device.fps=50 fbtft_device.debug=0 fbtft_device.verbose=0 fbcon=map:10 fbcon=font:ProFont6x11 logo.nologo" \
	"gpio_mouse_device pulldown polarity=0 up=17 down=22 left=27 right=23 bleft=4"

piwik