XUP Contest
A ZedBoard / RedPitaya Tango Gateway
Participants :
ZULIC Dino
REYNIER Benjamin
LAFIOSCA Léo
Supervisor :
University :
Université Joseph Fourier, IUT GEII, Grenoble, FRANCE
Team number :
ZYNQ_XIL_16334
Dino, Léo, Benjamin with Jean-Michel in the ESRF control room
youtube:
TANGO @ ESRF
Forewords
Tango control system was elaborated at the ESRF, a large synchrotron radiation facility in Grenoble, France. The ESRF is a large research laboratory (1500 engineers, researchers, ), a kind of giant microscope to explore organic molecules or others and that uses X rays of high energy (6 GeV) issued from an 850 meters circumference accelerator in more than 40 beams lines operating simultaneously. See ww.esrf.eu for more info.
ESRF beam lines
Tango control system is a 100 man/years middleware, which aims at the monitoring 24/7 of more than 200 000 sensors & actuators in the facility. It features among other usage : logging, events driven communication, seamless integration to NI Labview, Matlab, Igor scientific toolboxes or OPC-UA plc, EPICS bus, ...
some Tango GUI and Tools
Tango is set of tools and protocol, with API in C++/Python/Java, free and open source, scalable from large synchrotron to small raspberry pi form factor embedded devices. It has many advantages over competition, either closed and expensive systems (ABB, SIEMENS, …) or even its direct competitor EPICS. It uses an object oriented paradigm to hide device complexity and promotes design reuse.
There are already several hundreds Device Server classes, written in C++, Python or Java, ready to use for the most common devices udes at ESRF, Soleil, Alba, Elletra, Desy, … all free of charges and availables… see : www.tango-controls.org/resources/device-classes/
Tango Bus and ZedBorad / Redpitaya
There is a vivid and growing community of professional software developers (15 synchrotrons or laser research facilities and a growing number of industrial company). see : www.tango-controls.org
Tango team is proud to announce that the new SKA Telescope (square kilometer array telescope featuring antennas spread thoroughly South Africa and Australia) recently adopts Tango as its control system framework. see www.skatelescope.org
Zedboard/Zynq uses case at the ESRF
Fpga are widely used at the ESRF for data high speed acquisition or very specific devices that can not be found COTS, as high precision motors controllers (IcePap), booster power controller, … All devices, either in linac, booster, accelerator, or beam lines experimental hutches are intended to be monitored by Tango and so need their Device Server.
Xilinx Zynq meets perfectly these requirements, offering in one chip the best of 2 worlds : Fpga (for data acquisition) and the ARM cpu dual core hosting linux, and its high level/networking stack, ...
xilinx avnet ZedBoard
OpenEmbedded toolchain
We used Openembedded toolchain to build our dedicated Linux appliance. We find on GitHub all required bitbake recipes except a few : omniorb4, zeromq (old version) and of course Tango. But it was easy to write it from scratch because Tango already uses autoconf as its packaging tools.
OpenEmbedded toolchain
ZedBoard Tango Gateway
The design (vivado)
For now, the design is only a proof of concept, with gpio leds/switch & DAC adau1761, but could easily be improved with features as Analog Device Inc pmods for example ...
zedboard vivado design
generate dts and compile dtb
new vivado edition can generate dts. it was tricky before…
follow guidelines (git device-tree-xlnx and Add the BSP repository in SDK )
select "device-tree-xlnx" from the checked out git area):
SDK Menu: Xilinx Tools > Repositories > New... (<bsp repo>) > OK
gpio dts section :
ps7_gpio_0: gpio@41200000 {
#gpio-cells = <2>;
compatible = "xlnx,xps-gpio-1.00.a";
gpio-controller ;
reg = <0x41200000 0x10000>;
xlnx,all-inputs = <0x0>;
xlnx,all-inputs-2 = <0x1>;
xlnx,all-outputs = <0x1>;
xlnx,all-outputs-2 = <0x0>;
xlnx,dout-default = <0x0000005f>;
xlnx,dout-default-2 = <0x00000000>;
xlnx,gpio-width = <0x8>;
xlnx,gpio2-width = <0x8>;
xlnx,interrupt-present = <0x0>;
xlnx,is-dual = <0x1>;
xlnx,tri-default = <0xFFFFFFFF>;
xlnx,tri-default-2 = <0xFFFFFFFF>;
};
use dtc to compile .dts to .dtb
./tmp/work/zedboard_zynq7-poky-linux-gnueabi/linux-adi/3.18-adi+gite81690980bfbd04227e171cdee79d1d5127d0f79-r0/build/scripts/dtc/dtc -I dts -O dtb -o my.dtb zed.dts
Prepare Linux to boot with OpenEmbedded
NEW : Poky from scratch
Asap on github with submodules
#poky
git clone -b jethro git://git.yoctoproject.org/poky.git
#meta-xilinx
git submodule add -f https://github.com/Xilinx/meta-xilinx.git
now on github
full bitbake recipes available here :
https://github.com/raph38130/poky
It takes some time to bitbake linux kernel and filesystem… (fetching source code from the internet and (cross)compiling all)
bitbake conf repertory
recipes
Tango DS OpenEmbedded recipes
SUMMARY = "tango control system DeviceServer"
LICENSE = "CLOSED"
DEPENDS = "tango omniorb4 zeromq"
SRC_URI = "file://*"
S = "${WORKDIR}/ds-${PV}/../"
EXTRA_OEMAKE = " 'CC=${CC}' 'RANLIB=${RANLIB}' 'AR=${AR}' 'BUILDDIR=${S}' \
'TANGO_HOME=${TMPDIR}/sysroots/zedboard-zynq7/usr' \
'OMNI_HOME=${TMPDIR}/sysroots/zedboard-zynq7/usr' \
'ZMQ_HOME=${TMPDIR}/sysroots/zedboard-zynq7/usr' \
'OUTPUT_DIR=${S}' \
"
do_compile () {
export EmbeddedSystem=1
export TOOLBINDIR=${S}
oe_runmake
}
do_install() {
install -m 0755 -d ${D}${bindir}
install -m 0777 ${S}/ZedGPIO ${D}${bindir}
}
linux kernel config file
Take care to include gpio driver, sysfs, arasan SD support, …
Linux kernel is configured without modules (all bundled in kernel image), and the file system could easily fit in a ram disk (no need for a SD)
Tftpboot the bitbaked linux kernel and file system
we use mainly tftpboot during debug…
copy everything required under tftpboot repertory :
- fpga .bit and tcl configuration script
cp tango/tango.runs/impl_1/system_wrapper.bit /tftpboot/
cp tango/tango.srcs/sources_1/bd/system/ip/system_sys_ps7_1/ps7_init.tcl /tftpboot/
- OpenEmbedded u-boot, kernel, file system, dtb
cp tmp/deploy/images/zedboard-zynq7/* /tftpboot/
start Zynq Soc with xmd fpga debugger
xdisconnect -cable
source /tftpboot/ps7_init.tcl
connect arm hw
ps7_init
fpga -f /tftpboot/system_wrapper.bit
ps7_post_config
dow /tftpboot/u-boot.elf
con
use serial terminal (gtkterm) on /dev/ttyACM0 115200 8 N 1
set ipaddr 192.168.0.33
set serverip 192.168.0.4
tftpboot 0x3A00000 uImage
tftpboot 0x3900000 my.dtb
tftpboot 0x2000000 core-image-minimal-zedboard-zynq7-20150617082527.rootfs.ext4.gz.u-boot
bootm 0x3A00000 0x2000000 0x3900000
tftpboot
tftpboot + (large/permanent) filesystem on SD
gunzip /tftpboot/core-image-minimal-zedboard-zynq7-20150609193015.rootfs.ext4.gz
sudo dd if=/tftpboot/core-image-minimal-zedboard-zynq7-20150609193015.rootfs.ext4 bs=1M of=/dev/sdc1
booting everything from SD
- partition SD memory in 2
mmcblkp1 is fat, contains BOOT.bin, a dtb, uImage.bin
- BOOT.bin
contains hardware design (system_wrapper.bit and fsbl.exe, from vivado/xsdk)
and u-boot.elf
customize u-boot to boot straight from SD (uEnv.txt or edit zynq-common.h)
sdboot = ...
fatload mmc 0 0x0500000 my.dtb
fatload mmc 0 0x0600000 uImage.bin
bootm 0x0600000 - 0x0500000
use bootgen and boot.bif configuration file :
boot.bif
the_ROM_image:
{
[bootloader]/tftpboot/myfsbl.elf
/tftpboot/system_wrapper.bit
/tftpboot/u-boot.elf
}
bootgen -image boot.bif -o boot.bin -w
- the .dtb file (so that linux identifies hardware)
in dts, check bootargs : (rootwait !!!)
bootargs = "console=ttyPS0,115200 rootfstype=ext4 root=/dev/mmcblk0p2 rw rootwait earlyprintk";
use dtc to convert dts->dtb
./tmp/sysroots/x86_64-linux/usr/bin/dtc -I dts -O dtb -o my.dtb zed.dts
- uImage.bin
- mmcblkp2 is ext4, contains linux FS
copy file system with dd
sudo dd bs=1M of=/dev/sdc2 \
if=./tmp/deploy/images/zedboard-zynq7/core-image-minimal-zedboard-zynq7-20151021125933.rootfs.ext4
Booting from qspi flash memory
our solution : no extra hardware required
need BOOT.bin to flash
boot.bif configuration file
the_ROM_image:
the_ROM_image:
{
[bootloader]/tftpboot/myfsbl.elf
/tftpboot/system_wrapper.bit
/tftpboot/u-boot.elf
[offset = 0x0500000]/tftpboot/my.dtb
[offset = 0x0600000]/tftpboot/uImage.bin
[offset = 0x0900000]/tftpboot/core-image-minimal-zedboard-zynq7.ext4.gz.u-boot
}
bootgen -image boot.bif -o boot.bin
take care to adapt sizes/offset to files length
fsbl + system.bit size : 0x4424E1
customize u-boot to qspiboot automatically :
edit zynq-common.h and recompile u-boot
./tmp/work/zedboard_zynq7-poky-linux-gnueabi/u-boot-xlnx/v2014.01-xilinx+gitAUTOINC+2a0536fa48-r0/git/include/configs/zynq-common.h
"qspiboot=echo Booting Linux from QSPI flash to RAM... && " \
"sf probe 0 0 0 && " \
"echo loading dtb && " \
"sf read 0x0500000 0x0500000 0x3000 && " \
"echo loading kernel && " \
"sf read 0x0600000 0x0600000 0x300000 && " \
"echo loading ramdisk && " \
"sf read 0x0900000 0x0900000 0xE00000 && " \
"echo booting linux && " \
"bootm 0x0600000 0x0900000 0x0500000 \0" \
"echo booting linux && " \
"bootm 0x1600000 0x1900000 0x0800000 \0" \
use xsdk | Xilinx Tools | Flash Tool (very slow)
(CAUTION : no success when flashing qspi from u-boot !!!)
A simple GPIO Tango Device Server
DeviceServer Design
this Tango device is rather simple, for demonstration purpose only : it puts on tango bus the Leds and Switches of the Zedboard.
Two set of Tango attributes are defined :
- Leds (8 boolean and UChar) Write only
- Switches(8) Read Only (Uchar)
pogo wizard
generate C++ skeleton
Pogo wizard to generate C++/python/java skeleton of a DeviceServer
gpio access using linux sysfs
gpio N° changes ? look for gpiochip
raw linux access /sys/class/gpio
echo 906 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio1016/direction
root@zedboard-zynq7:~# echo 1 > /sys/class/gpio/gpio1016/value
root@zedboard-zynq7:~# echo 0 > /sys/class/gpio/gpio1016/value
Device Class C++ skeleton
grayed code is generated by Pogo wizard
void ZedGPIO::init_device()
{
DEBUG_STREAM << "ZedGPIO::init_device() create device " << device_name << endl;
/*----- PROTECTED REGION ID(ZedGPIO::init_device_before) ENABLED START -----*/
// Initialization before get_device_property() call
/*----- PROTECTED REGION END -----*/ // ZedGPIO::init_device_before
// No device property to be read from database
attr_Switches_read = new Tango::DevUChar[1];
/*----- PROTECTED REGION ID(ZedGPIO::init_device) ENABLED START -----*/
// Initialize device
char buffer [32];
for (int i=0; i<8; i++)
{
int exp = open("/sys/class/gpio/export", O_WRONLY);
sprintf(buffer, "%d", 1016+i);
write(exp, buffer, 3);
close(exp);
sprintf(buffer,"/sys/class/gpio/gpio%d/direction",1016+i);
int dir = open(buffer, O_WRONLY);
write(dir, "out", 3);
close(dir);
}
for (int i=0; i<8; i++)
{
int exp = open("/sys/class/gpio/export", O_WRONLY);
sprintf(buffer, "%d", 1008+i);
write(exp, buffer, 3);
close(exp);
sprintf(buffer,"/sys/class/gpio/gpio%d/direction",1008+i);
int dir = open(buffer, O_WRONLY);
write(dir, "in", 2);
close(dir);
}
/*----- PROTECTED REGION END -----*/ // ZedGPIO::init_device
}
void ZedGPIO::write_Leds(Tango::WAttribute &attr)
{
DEBUG_STREAM << "ZedGPIO::write_Leds(Tango::WAttribute &attr) entering... " << endl;
// Retrieve write value
Tango::DevUChar w_val;
attr.get_write_value(w_val);
/*----- PROTECTED REGION ID(ZedGPIO::write_Leds) ENABLED START -----*/
DEBUG_STREAM << "ZedGPIO val " << (int) w_val << endl;
char buffer[32];
for (int i=0; i<8; i++)
{
sprintf(buffer,"/sys/class/gpio/gpio%d/value",1016+i);
int gpio = open(buffer, O_WRONLY);
if (((((int) w_val) >> i) & 1) == 1)
write(gpio, "1", 1);
else
write(gpio, "0", 1);
close(gpio);
}
/*----- PROTECTED REGION END -----*/ // ZedGPIO::write_Leds
}
Using ZedGPIOds
testing with Jive tool
export TANGO_HOST=192.168.0.4:10000
ZedGPIO z0 -v4
Jive and AtkPanel : swiss knife of Tango
Remote launch with Starter tool
Starter is a Tango DeviceServer that starts other Devices Servers remotely.
Astor is the Tango tool dedicated to DS admin (support pool of devices, run level, events management, logging …)
Starter and Astor : remote DS administration & event monitoring
Interactive Python / Tango demo
We can use itango (interactive python with Tango wrapper) to easily create customs applications.
tango@raph-VirtualBox0:~$ itango
ITango 8.1.4 -- An interactive Tango client.
Running on top of Python 3.4, IPython 1.2.1 and PyTango 8.1.4
help -> ITango's help system.
object? -> Details about 'object'. ?object also works, ?? prints more.
IPython profile: tango
hint: Try typing: mydev = Device("<tab>
ITango [2]: gpio=Device("rp/zed/0")
ITango [3]: import time
ITango [4]: gpio.leds=gpio.switches
ITango [5]: while True:
time.sleep(0.1)
gpio.leds=gpio.switches
itango k2000
ipython script to play k2000 with leds
while True:
...: for i in range(7,-1,-1):
...: d.leds = 1 << i
...: time.sleep(0.1)
...: for i in range(0,8):
...: d.leds = 1 << i
...: time.sleep(0.1)
...:
k2000 python device server
we could also write a Python K2000 device server
JDraw synoptic
without a single line of code, Jdraw creates your synoptic :
Jdraw tool can build interactive synoptics
here is an example zedgui.jdw
Testing ZedBoardTangoGateway
CAUTION : this is not a stand alone application software and there is a learning curve with TANGO concepts and tools. We provide here only a few guidelines…
download “tangobox” virtual machine and ZedBoard BOOT.bin
to test this project, you need a Tango remote station. Either d ownload a Tango Virtualbox or install debian packages on your linux host.
Download a ready to launch TangoBox (ubuntu 14.04.2) here :
(64 bit OS /VirtualBox required)
flash zedboard with :
debian packages
Tango require a mysql server and root access
sudo apt-get install mysql-server libmysqlclient-dev
grant access to DB tango to your tangobox user
sudo apt-get install tango-db libtango8-dev tango-test
update tools (Jive, Pogo, Astor) from http://www.tango-controls.org/tools/
sudo service tango-db start
itango (python with Tango wrapper) :
sudo apt-get install python3-pytango
database configuration
Tango Database stores devices configurations, properties, connections details, … it is used mainly at device launch. Devices communication are highly optimized, peer to peer,
with Jive Tools | Server wizard
server name : ZedGPIO
instance name : z0
hit next
Start the server on zedboard (before, you need to :
export TANGO_HOST=ipaddr_of_tango_database server:10000 to tell device server where is the tango database)
ZedGPIO z0 -v4
back to Jive
hit next
select ZedGPIO class
declare a device (naming convention is ([tango_network/]facility/class/name)
xilinx/zedgpio/0
DataBase contents
do the same to register Starter instance in zedboard
the screenshot show database contents for our use case.
event subsystem issue
there is an issue the way tango-db starts DataBase on some distributions (affecting events subscription within zeromq layer)
the tangobox ip addr should appear in ORBendPoint (after tcp, before 10000)
ps axww | grep giop
4771 ? Sl 0:00 /usr/lib/tango/DataBaseds 2 -ORBendPoint giop:tcp::10000
either launch it that way :
/usr/lib/tango/DataBaseds 2 -ORBendPoint giop:tcp:192.168.0.16:10000
using tangobox ip addr
or patch /etc/init.d/tango-db do_start() : remove if (localhost) …. and replace
ip=`ifconfig eth0 | awk -F"[: ]+" '/inet addr:/ {print $4}'`
DAEMON_ARGS="2 -ORBendPoint giop:tcp:$ip:$PORT"
now double click in Jive over xilinx/zedgpio/0 and AtKPanel should be launched
try some itango script
or jdraw drawing...
RedPitaya Oscilloscope
rp uses a “smaller” SoC than zedboard : zynq xc7z010clg400 vs xc7z020clg484 but ARM executable code from Zedboard can be reused in Redpitaya (but be carefull with libraries requirements)
RedPitaya open source open-source measurement and control tool
Tango Redpitaya in action
build DeviceServer
bitbake redpitaya
upload to rp
tar czvf ds.tgz usr/lib/libstdc++.* usr/lib/libtango.* usr/lib/libzmq.* usr/lib/libCOS* usr/lib/libomni* usr/lib/liblog4tango.* usr/bin/Redpitaya
scp ds.tgz root@192.168.0.8:
install in rp
ssh redpitaya
cd /
gzip -d /root/ds.tgz
tar xvf ds.tar
launch ds
export TANGO_HOST=192.168.0.3:10000
./Redpitaya 0
(need to register DS with jive the first time)
ds / instance / class / device
thank you for reading !
if you want more information on Tango : www.tango-controls.org
Merci beaucoup à toute l’équipe de l’ESRF et notamment :
Jean Michel Chaize, Antonin Broquet, Andy Goetz
sans lesquels rien n’aurait été possible !