6 Linux notes

6.1 General

This section contains Linux-related topics that are specific to Xillinux.

A wider view on Xillybus and Linux can be found in these documents:

6.2 Compilation of the Linux kernel

Due to its size, the full Linux kernel is not included in the Xillinux distribution, but can be downloaded from Github with

$ git clone https://github.com/xillybus/xillinux-kernel.git

For an exact replication of the kernel used with Xillinux-2.0, check out the “xillinux-2.0a” tag. Inform the kernel build environment on the desired cross compiler with something of the form of

$ export CROSS_COMPILE=/path/to/crosscompiler/arm-xilinx-linux-gnueabi-

Then obtain the .config file, that is used for compilation of the kernel which comes with Xillinux-2.0:

$ make ARCH=arm xillinux_defconfig

And then run the compilation of the kernel:

$ make ARCH=arm -j 8 uImage modules LOADADDR=0x8000

In order to build the Device Tree Blobs, the following command can be used, after setting the cross compiler and the .config file as said above:

$ make ARCH=arm dtbs
[ ... ]
  DTC arch/arm/boot/dts/xillinux-microzed.dtb
  DTC arch/arm/boot/dts/xillinux-zedboard.dtb
  DTC arch/arm/boot/dts/xillinux-zybo.dtb
  DTC arch/arm/boot/dts/xillinux-zturn-lite.dtb

The DTB files can be found in arch/arm/boot/dts/, as suggested by the command’s response.

6.3 Compilation of kernel modules

The Xillinux distribution comes with the running kernel’s compilation headers. This is not enough to perform a compilation of the kernel itself, but allows the compilation of kernel modules directly on the platform.

The standard way for compilation of an out-of-tree kernel module is using a Makefile which invokes the kernel’s own build environment, after setting up an environment variable, which tells it to perform compilation of a specific module.

The minimal Makefile for a native compilation (performed by the Zynq processor itself) of a kernel module consisting of a single source file, example.c, is as follows:

ifneq ($(KERNELRELEASE),)
obj-m      := example.o
else
TARGET := $(shell uname -r)
PWD := $(shell pwd)
KDIR := /lib/modules/$(TARGET)/build

default:
      @echo $(TARGET) > module.target
      $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
endif

Note that the name of the module, “example”, is mentioned only in the “obj-m” line. This is the only thing that differs from one Makefile to another.

Using this Makefile typically results in a compilation session as follows (run on the board itself; this is not a cross compilation):

# make
make -C /lib/modules/4.4.30-xillinux-2.0/build SUBDIRS=/root/example modules
make[1]: Entering directory '/usr/src/linux-headers-4.4.30-xillinux-2.0'
 CC [M] /root/example/example.o
 Building modules, stage 2.
 MODPOST 1 modules
 CC     /root/example/example.mod.o
 LD [M] /root/example/example.ko
make[1]: Leaving directory '/usr/src/linux-headers-4.4.30-xillinux-2.0'

6.4 Sound support

6.4.1 General

The Zedboard and Zybo boards support sound recording and playback by virtue of Analog Devices’ ADAU1761 and SSM2603 chipsets, respectively. These are connected to the Zynq device’s logic fabric (PL) pins only.

Except for its obvious functionality, the sound support package also demonstrates how the Xillybus IP core can be used to transport data, as well as to program a chip through SMBus / I2C.

Xillinux supports sound natively by interfacing dedicated Xillybus streams with the most common toolkit for sound in Linux today, Pulseaudio. As a result, virtually any application requiring a sound card will properly use the board’s sound chip as the system’s default input and output.

It’s also possible to turn the Pulseaudio daemon off, and work directly with the Xillybus streams (/dev/xillybus_audio). This presents a simpler programming interface of just opening a device file, at the cost of losing the native functionality of other applications.

Unlike the common approach for Linux sound cards, there is no dedicated kernel driver (e.g. ALSA) for the sound interface, because the Xillybus host driver handles the data transport anyhow. This has no significance, even not to programs expecting to work with /dev/dsp, since Pulseaudio has the capability of faking this interface with the “padsp” utility.

6.4.2 Usage details

By default, sound is played back to the headphones jack (black). On Zedboard, the same output goes to Line Out (green) as well. For recording, only the microphone input (pink) is used, but this can be changed, as described next.

6.4.3 Related boot scripts

There are two tasks related to setting up sound on Zedboard and Zybo: Programming the audio chip and launching the Pulseaudio daemon.

For the first task, two systemd unit files are in place at /etc/systemd/system/:

  • xillinux_sound.service: Launches /usr/local/bin/xillinux-sound when started.

  • xillinux_sound.path: Instructs systemd to wait for /dev/xillybus_smb to appear, and when that happens, start the service just mentioned. Note that this is not based upon udev, but on inotify, which is monitoring /dev.

/usr/local/bin/xillinux-sound identifies which board it runs on, and runs the script /usr/local/bin/zybo_sound_setup.pl or /usr/local/bin/zedboard_sound_setup.pl, as applicable.

The Pulseaudio daemon is started when any user creates its first login session on the system, by virtue of the user service unit file xillinux_pulseaudio.service, which resides in /etc/systemd/user/.

Since Xillinux auto-logins the root user on the serial console as well as the screen console, Pulseaudio is started soon after the system’s boot is completed.

Running Pulseaudio as root is not a recommended on a multi-user computer, but since Xillinux runs with root as the default user, this is the least problematic option.

The service should be disabled if direct access to /dev/xillybus_audio is needed, with e.g.

# systemctl --global disable xillinux_pulseaudio
Removed symlink /etc/systemd/user/default.target.wants/
xillinux_pulseaudio.service.

zybo_sound_setup.pl and zedboard_sound_setup.pl are Perl scripts, which set up the audio chip’s registers for proper operation. They are fairly straightforward, even for programmers who are not familiar with Perl. The script uses the /dev/xillybus_smbus device file to initiate transactions on the chip’s I2C bus.

zedboard_sound_setup.pl can be edited to achieve a different setup of the audio chip. In particular, if the Line In input is the desired source for recording, the lines

write_i2c(0x400a, 0x0b, 0x08);
write_i2c(0x400c, 0x0b, 0x08);

should be replaced with

write_i2c(0x400a, 0x01, 0x05);
write_i2c(0x400c, 0x01, 0x05);

In a similar manner, zybo_sound_setup.pl can be edited, replacing

write_i2c(0x04, 0x14);

with

write_i2c(0x04, 0x10);

to use Line In for recording.

6.4.4 Accessing /dev/xillybus_audio directly

/dev/xillybus_audio can be written to directly for playback, or read from for recording. The sample format is 32 bit per audio sample, divided into two 16-bit signed integers in little Endian format. The most significant word corresponds to the left channel.

The sampling rate is fixed at 48000 Hz.

A Windows WAV file with this sampling rate is likely to play correctly if written directly to /dev/xillybus_audio (the header will be played back as well for about 1 ms) e.g. with

# cat song.wav > /dev/xillybus_audio

If the response is

-bash: /dev/xillybus_audio: Device or resource busy

it’s likely that another process is having the device file open for write, possibly the Pulseaudio daemon. There is no problem having the device file opened for read by one process and for write by another.

6.4.5 Pulseaudio details

Pulseaudio interacts with the /dev/xillybus_audio device file through a couple of dedicated Pulseaudio modules, module-file-sink and module-file-source. Their sources can be found in Xillinux’ file system at /usr/src/xillinux/pulseaudio/.

These modules are slight modifications of standard Pulseaudio modules for using UNIX pipes as data sinks and sources (module-pipe-sink and module-pipe-source).

The modules are automatically loaded when Pulseaudio starts, by virtue of the two following lines in /etc/pulse/default.pa:

load-module module-file-sink file=/dev/xillybus_audio rate=48000
load-module module-file-source file=/dev/xillybus_audio rate=48000

These modules are selected as the system’s sound interface automatically, as there are no other alternatives.

6.5 The OLED utility (Zedboard only)

By default, Xillinux starts an activity meter utility during boot, displaying approximate CPU usage percentage and an indication of the I/O rate on the SD flash disk.

The CPU percentage is based upon /proc/stat, where all time not spent idle is considered used CPU time.

An estimation of the SDIO traffic is made based upon the rate at which interrupts are sent to the respective driver. There is no known figure for a full utilization of this resource. Rather, the utility displays 100% for an interrupt rate that appears to be maximal, according to previous measurements.

To display the graphical output on the board’s OLED, the bitmap is sent to /dev/zed_oled, which is created by Digilent’s driver. It’s worth to mention that this driver sends SPI data to the OLED device with a bit-banging mechanism, toggling the clock and data in software. Hence there is a slight CPU consumption sending 512 bytes this way several times per second, but the impact to the overall system performance is minimal.

To change the parameters of this utility, edit /usr/local/bin/start_zedboard_oled, which boils down to the following command:

/usr/local/bin/zedboard_oled /proc/irq/$irqnum/spurious 4 800

The application, zedboard_oled, takes three arguments:

  • The /proc file to monitor for SDIO-related interrupts. $irqnum is the IRQ number of the mmc0 device.

  • The rate at which the OLED display is updated, in times per second.

  • What is considered to be 100% of the SDIO interrupt rate, in interrupts per second. The current figure was found by trial and error.

To prevent this utility from being launched during boot:

# systemctl disable zedboard_oled.path
Removed symlink /etc/systemd/system/paths.target.wants/zedboard_oled.path.

6.6 Other notes

  • Even though there have been changes in the Linux GPIO driver since kernel 3.12, the same GPIO driver as Xillinux-1.3 is used in Xillinux-2.0, retaining the behavior and numbering of Xillinux-1.3.

    In order to use the new GPIO driver, alter the device tree entry with compatible = “xlnx,ps7-gpio-1.00.a”, so it says “xlnx,zynq-gpio-1.0”.

  • The Quad SPI flash is accessed by the Linux kernel with one bit wide bus, even though the driver supports a quad bit interface. The relevant device tree entry can be changed for enabling the quad bit interface. This is not the default setting to allow the same device tree to be used with kernel 3.12 (i.e. Xillinux-1.3).