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"