Masaryk University Faculty of Informatics

Graphical Debugger of GPIO Pins

Bachelor’s Thesis

Miloslav Žežulka

Brno, Spring 2018

This is where a copy of the official signed thesis assignment and a copy ofthe Statement of an Author is located in the printed version of the document.

Declaration

Hereby I declare that this paper is my original authorial work, which I have worked out on my own. All sources, references, and literature used or excerpted during elaboration of this work are properly cited and listed in complete reference to the due source.

Miloslav Žežulka

Advisor: Mgr. Marek Grác, Ph.D.

i

Acknowledgements

I would like to thank my advisor Mgr. Marek Grác, Ph.D. for his valuable feedback and comments regarding the thesis. I would also like to thank my technical advisor Ing. Pavel Macík who guided me throughout the whole work.

iii Abstract

The main aim of this thesis is to implement a graphical debugger for single-board computers (SBC) using a called Bulldog. The first section of this work describes hardware interfaces typically present on SBCs with the emphasis on Raspberry Pi. The main part of the thesis is dedicated to the debugger itself, including a graphical demonstra- tion of its functionality. The result is a graphical debugger capable of communicating with devices from the Raspberry Pi family. During the implementation of the debugger, we also discover that the library itself required some major modifications. The application is based on the client-server model. Given the underlying library picked for the debugger, the application is written in and is publicly released via GitHub as an open source project.

iv Keywords

single-board computer, Bulldog, GPIO, I2C, SPI, Raspberry Pi, BCM2835, Java, JNI

v

Contents

1 Introduction 1

2 State of the art 3 2.1 RPi.GPIO ...... 3 2.2 BCM2835 ...... 3 2.3 GPIO utility from WiringPi ...... 3 2.4 i2cdetect, i2cget, i2cset ...... 4

3 Bulldog Library 5 3.1 JNI ...... 6

4 Functions of GPIO Pins 9 4.1 Digital I/O ...... 9 4.1.1 Analog vs. digital signal ...... 9 4.1.2 Accessing GPIO pins ...... 10 4.1.3 Interrupts ...... 16 4.2 I2C ...... 16 4.2.1 Protocol definition ...... 17 4.2.2 I2C data transmission - semantics ...... 17 4.3 SPI ...... 19 4.3.1 SPI data transmission ...... 21 4.4 Other interfaces ...... 23 4.4.1 PWM ...... 23 4.4.2 UART ...... 23 4.4.3 PCM ...... 24

5 Raspberry Pi 25 5.1 Raspberry Pi as a single board computer ...... 25 5.2 Uses ...... 25 5.3 Raspbian ...... 25 5.4 Accessing peripherals ...... 26

6 Debugger 29 6.1 Use cases of the debugger ...... 30 6.2 Protocol ...... 31 6.2.1 Details of the protocol implementation . . . . . 31

vii 6.2.2 Agent ...... 32 6.2.3 Client ...... 33 6.3 Libraries and frameworks used ...... 33 6.4 Networking ...... 34 6.4.1 Java NIO ...... 34 6.5 Usage ...... 36 6.5.1 Initial state of the debugger ...... 36 6.5.2 Connecting to a device ...... 38 6.5.3 Disconnecting from a device ...... 40 6.5.4 Digital I/O request ...... 40 6.5.5 Interrupts ...... 42 6.5.6 I2C request ...... 43 6.5.7 SPI request ...... 44 6.5.8 Agent ...... 45 6.5.9 Testing mode ...... 46

7 Conclusion 47 7.1 Possible improvements ...... 47 7.1.1 Bulldog ...... 47 7.1.2 Debugger ...... 48 7.1.3 Testing ...... 49

A JNI 55

B Sequence diagram of the debugger 59

C Archive 61

viii List of Figures

2.1 Output of gpio readall 4 3.1 JNI Architecture 7 4.1 Signal sampling 10 4.2 Sysfs tree 11 4.3 GPIO pin sysfs structure 12 4.4 I2C timing diagram 17 4.5 I2C protocol diagram 18 4.6 Regular SPI connection 20 4.7 Daisy-chained SPI bus 21 4.8 Schema of SPI data transmission 22 5.1 raspi-config tool 26 5.2 Binary data in procfs 27 6.1 Use case diagram 30 6.2 Blocking and nonblocking I/O 35 6.3 Debugger initial state 36 6.4 The client connected to Raspberry Pi 38 6.5 netstat command 39 6.6 Digital I/O usage 40 6.7 Interrupts in debugger 42 6.8 Prefilled2 I request form 43 6.9 I2C request form 44 6.10 SPI request form 45 6.11 Agent logger output 46

ix

1 Introduction

Single-board computer (SBC) is a fully functional computer embedded on a single board. In comparison with a personal computer, SBC is a computer with all the necessary components (microprocessor, mem- ory, I/O) already present on the board. Furthermore, SBCs usually do not rely on expansion slots for peripheral functions or expansion [33]. By integrating all the components on one board, a smaller overall system can be obtained compared to a conventional PC. This also brings us to one of the most distinguishing characteristics of such com- puters. SBC is usually a very specialized piece of hardware designed and optimized for its one and only purpose. In the past few years, however, SBCs designed for general purpose are becoming increasingly popular1. In the context of this thesis, we will exclusively focus on this SBC type. General purpose SBCs are used as educational tools, development systems, demonstrations and in many other ways. When developing software or hardware for such devices, it is beneficial to have a debug- ging tool which is capable of reading or writing various information from the board, in the most convenient way possible. We will refer to such tool as a graphical debugger. This graphical debugger should be user-friendly2 since it is possible that users might come into contact with an SBC device for their first time. More specifically, the graphical debugger presented in this thesis represents a tool which is capable of providing the user with com- plex information about various hardware components and interfaces present on SBC. It is possible to read and write values on GPIO pins and listen for interrupts on them. Other interfaces available for de- bugging should be at least I2C and SPI3. In general, the debugger retrieves information using general purpose input/output interface, GPIO. This information is then graphically presented to the user.

1. An exhaustive list of such devices can be found in [9] 2. By user-friendly we especially mean the ability to use the debugger without long preparation beforehand. In the ideal implementation, the debugger should be able to run straight out of the box. 3. Both of these interfaces are described in more detail in the chapter "Functions of GPIO Pins".

1 1. Introduction

The goal of my thesis was to implement such debugger using the Bulldog library [7]. This library was not fully functional. One of my other goals was also to look into Bulldog and improve it. The Bulldog library specializes in SBCs which use ARM processors (ARM SBC, ASBC). At the time of writing this thesis, Bulldog can communicate with Raspberry Pi, CubieBoard, and BeagleBoneBlack. Debugger implementation mainly focuses on Raspberry Pi with the potential for extending it for the other two SBCs supported by Bulldog. The debugger consists of two modules: client with graphical user interface and agent. The client is run on the machine from which the device is controlled and monitored over the network. The agent is deployed on the target device. The client can connect to multiple devices at once, whereas the agent is designed for communicating with one client only. The implementation language is Java because this is the primary language used in Bulldog. The resulting outcome of this project is a pair of JAR archives together with a manual describing how to deploy and use the application. This manual is one of the parts of this thesis.

2 2 State of the art

Despite Raspberry Pi being powerful enough to run graphical appli- cations, most of the tools used for debugging are only available via a command-line interface. One of the reasons is compatibility with older Raspberry Pi releases which do not have powerful enough hard- ware to run graphics-based software. List of the most commonly used tools follows.

2.1 RPi.GPIO

Python library for controlling digital I/O features of pins. What is more, RPi.GPIO [32] can also be used for writing scripts which test other functions available on pins1. However, this library only provides limited functionality when compared to others on this list.

2.2 BCM2835

Named after the chip Raspberry Pi has got embedded in its processor, this library written in C directly accesses chip registers. This makes BCM2835 [8] very powerful2. The BCM2835 library is recommended for more advanced users as it assumes deeper understanding of the interfaces.

2.3 GPIO utility from WiringPi

WiringPi [18] is a pin-based GPIO access library written in C for the BCM2835 chip used in Raspberry Pi3. Apart from the library itself, WiringPi also provides a separate program which in textual form displays information about all avail-

1. Pin capabilities are determined by general purpose input output (GPIO) which itself is discussed in the chapter "Functions of GPIO Pins". 2. Other tools access GPIO functionality indirectly via sysfs which is in detail discussed in the section "Sysfs" of the chapter "Functions of GPIO Pins". 3. Since the initial release of this library in May 2013, it has been extended to also work on newer chips and supports alternative pin functions.

3 2. State of the art able pins. This is very useful when searching for various types of pin addresses (as shown in the illustration below).

Figure 2.1: Output of gpio readall from WiringPi tool collection. Each pin has got up to five addresses it can map to.

2.4 i2cdetect, i2cget, i2cset

Collection of command line tools which make it possible to access an I2C bus4. i2cset [23] reads from this interface, i2cget [22] is capable of writing to it, and i2cdetect [21] returns overall information about the bus, including active devices currently present on it. These tools have a very similar structure of command line arguments, making them efficient to use.

4. I2C is in detail discussed in the section "I2C" of the chapter "Functions of GPIO pins".

4 3 Bulldog Library

Bulldog is a library for ASBC devices mainly written in Java and compatible with Linux only. There are sections of this library which use native C code, one of the reasons being direct work with memory. This is achieved by using (JNI) which we will discuss later. Bulldog is not specific to Raspberry Pi as it also supports Beaglebone Black and Cubieboard. Bulldog is an open-source project hosted on GitHub [7]. The library consists of several modules. Short description of each module follows.

Module Description bulldog-core This is the module that is intended to be used by third parties because it con- tains the public API. For example, this module contains classes which repre- sent a generic pin which can have fea- tures assigned and activated on it. bulldog-devices Object representation of various elec- tronic devices, such as LED, servo mo- tor or actuator. bulldog-linux Linux-based implementation of the bulldog-core facade which depends on bulldog-linux-native module. bulldog-linux-native This module contains low-level code and files related to JNI. bulldog-board-boardname Device specifics are included here, which is for example declaration of GPIO pins and interfaces present on the device.

5 3. Bulldog Library 3.1 JNI

The Bulldog library uses native calls to access the low-level part of its implementation. We will also use Bulldog as an example to explain principles behind JNI. The JNI specification explains that "The JNI is a native program- ming interface. It allows Java code that runs inside a Java Virtual Machine (VM) to interoperate with applications and libraries written in other programming languages, such as C, C++, and assembly." [25] Such libraries are usually called native libraries. Native libraries should be used when there is a compelling reason to do so. Being able to use features of the native language that Java does not have might be one of the reasons1. Bulldog uses JNI to be able to work with memory pointers which in turn make it possible to access specific addresses in memory. That is because Java language hides memory management away from the programmer.

1. The JNI specification also lists other possible situations in which JNI isused:

– The standard Java class library does not support the platform-dependent features needed by the application.

– There is already a library written in another language, and developer wishes to make it accessible to Java code through the JNI. (This was also partly the case with the agent and BCM2835 C library.)

– Implementing small portions of time-critical code in a lower-level language such as assembly.

6 3. Bulldog Library

Figure 3.1: JNI Architecture in the context of the Bulldog library.

As described in the diagram, native code is not directly invoked within the running Java application. Instead, native calls are dis- patched via JVM. Let us analyze how we use JNI in Bulldog. We use a slightly modi- fied version of the NativeTools class. package jni; public class NativeTools {

public static final int OPEN_READ_ONLY= 0x00; public static final int OPEN_WRITE_ONLY= 0x01; public static final int OPEN_READ_WRITE= 0x02; public static native int open(String filename, int flags); public static native int close(int fileDescriptor);

}

As we can see from the source code, we mark a method as native by using the native keyword in the function declaration. To implement native calls in Java, special C source and header files for the given class containing native methods have to be generated. The Java development

7 3. Bulldog Library kit has a dedicated tool called javah designed specifically for this task2. See the Appendix A for the resulting C header and source files. We also used JNI to integrate the BCM2835 library into Bulldog. Reasons for this are discussed in the "Digital I/O" section of the "Func- tions of GPIO Pins" chapter. Together with the tools listed in the previous chapter, Bulldog mainly deals with pins present on an ASBC. These pins are accessed via GPIO. Each pin function will be described in the context of GPIO in the next chapter.

2. On a side note, the javah tool has been removed in Java 10 and its responsibilities have been newly delegated to the Java compiler javac [28]. Nevertheless, the Java version used both in the debugger and Bulldog is 8.

8 4 Functions of GPIO Pins

4.1 Digital I/O

GPIO operates only with digital values of a signal. Therefore, to un- derstand how GPIO works, it is important to explain the differences between an analogue and a digital signal.

4.1.1 Analog vs. digital signal

A signal can be described as a voltage changing over time. This applies both to the analogue and digital type of signal. When describing signals, it is sometimes useful to think of them as functions, whose domain is a set of time instants and range a set of voltage levels for the given time instants. A digital signal can be seen as a function from a finite set of integers, describing time instant, to the set of real numbers, which are the function values (i.e. voltage levels) for the given time instant. This also means that there are time instants for which the function is not defined. In summary, a digital signal can be described as adiscrete function [11]. A special case of a digital signal called a binary signal (sometimes a logic signal) has got only two distinguishable levels. Binary signals are the most commonly used signals in digital electronics for data transmission. Consequently, this also holds true for GPIO. The function describing an analogue signal, on the other hand, is defined at every instant for a given time interval. This function is therefore continuous. Although GPIO pins are limited to hold only digital values, it is also worth mentioning one very common technique in digital processing called sampling. Sampling is a process of reducing an analogue signal to a digital one. This is usually done by measuring the voltage level of an analogue signal after each time period T. This sampling period then determines the sampling frequency f, which can be expressed as f = T−1. We measure this frequency in Hertz.

9 4. Functions of GPIO Pins

Figure 4.1: Illustration of signal sampling: analog (red) signals are sampled to digital (blue) signals. Image taken from [15].

4.1.2 Accessing GPIO pins A GPIO interface on an ASBC consists of generic pins whose func- tionality is mutable at runtime, therefore making this interface very versatile. There are many levels of abstraction and ways to access the GPIO functionality in Raspberry Pi. We describe some of the ways below.

Sysfs As we will learn later in this section, sysfs is a general tool providing access to various peripherals, including GPIO. Let us discuss sysfs in general terms first. Patrick Mochel, the creator of sysfs, sums up sysfs in his paper [39] the following way: "Sysfs is a feature of the Linux 2.6 kernel that allows kernel code to export information to user processes via an in-memory filesystem. The organization of the file system directory hierarchy is strict, and based the internal organization of kernel data structures. The files that are created in the filesystem are (mostly) ASCII files with (usually) one value per file."

10 4. Functions of GPIO Pins

This article also provides a useful mapping between the kernel and userspace:

Internal (kernel) External (userspace, sysfs) Kernel objects Directories Object attributes Regular files Object relationships Symbolic links

The kernel object of main interest is mapped in sysfs as a class. Mochel describes a class as "directory [that] contains representations of every device class that is registered with the kernel. A device class describes a functional type of device." Indeed, a class contains various devices such as bcm2835-gpiomem, gpio, i2c-adapter, i2c-dev, mem, spidev or spi_master which can be used to manipulate their respective hardware interfaces.

Figure 4.2: The first level of the sysfs tree hierarchy on Raspberry Pi2 running the Raspbian Linux distribution.

11 4. Functions of GPIO Pins

For the purpose of this thesis, the best way to demonstrate this structure is to show it on a GPIO pin using the /sys/class/gpio kernel object:

Figure 4.3: Structure of a pin in sysfs with the GPIO address 18.

Now that we know what the principle behind sysfs is, it should be relatively easy to demonstrate how GPIO interface is accessed through this file system1. GPIO pins are not present in sysfs by default; they have to be exported using the /sys/class/gpio/export utility.

#!/bin/bash echo “18” > /sys/class/gpio/export echo “out” > /sys/class/gpio/gpio18/direction echo “1” > /sys/class/gpio/gpio18/value cat /sys/class/gpio/gpio18/value

Listing 1: Example of writing using sysfs. Using /sys/class/gpio/export utility, we export pin with GPIO address 18 to userspace. We then define pin as output. Once the pin function is set to output, wecan then set a logic level of pin, in this case to high. The last command will now output "1" to the standard output.

1. Important note: sysfs is included in the Linux kernel by default. However, it must be mounted to be accessible for any process.

12 4. Functions of GPIO Pins

#!/bin/bash echo “18” > /sys/class/gpio/export echo “in” > /sys/class/gpio/gpio18/direction cat /sys/class/gpio/gpio18/value

Listing 2: Example of reading from a pin in sysfs. Again, we export the same pin to userspace and then define it as input. From the sysfs filesys- tem perspective, this means that we cannot write to file /sys/class/gpi- o/gpio18/value but still can read from /sys/class/gpio/gpio18/value.

Accessing hardware peripherals via sysfs is generally a good idea. However, sysfs is not sufficient for working with advanced pin features. One of them is selecting alternative pin functions, which is crucially important for the debugger. Digital input and output was formerly implemented using sysfs in Bulldog but to remove the deficiency mentioned above, we work directly with the BCM2835 chip registers to also enable switching to alternative pin functions.

Direct access to pins via BCM2835 registers This is the least abstract but the most powerful way to work with pins. The library used in code excerpts is BCM2835 1.52 [8] which was also integrated into Bulldog.

#define PIN RPI_GPIO_P1_12

bcm2835_init(); bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_OUTP); bcm2835_gpio_write(PIN, HIGH); bcm2835_close();

Listing 3: This code excerpt shows the idea behind writing to a GPIO pin. Again, we are working with a pin with GPIO address 18 as in the sysfs example above2.

13 4. Functions of GPIO Pins

To understand better what is exactly happening in this code, let us describe what is the responsibility of each function.

bcm2835_init Map physical memory to the userspace virtual memory3, making it accessible for an agent process. This also means we must allocate new memory. bcm2835_close then deallocates this memory.

bcm2835_gpio_fsel Take care of selecting the pin mode. Pin mode is selected by writing a given value to a GPFSEL register. 4.

bcm2835_gpio_write Set the given value to a pin with the ad- dress specified in the first function argument. Do not make anyas- sumptions whether the appropriate mode has been set, it is the pro- grammer’s responsibility to call these functions beforehand.

#define PIN RPI_GPIO_P1_12

bcm2835_init(); bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_INPT); bcm2835_gpio_set_pud(PIN, BCM2835_GPIO_PUD_UP); uint8_t value= bcm2835_gpio_lev(PIN); bcm2835_close();

Listing 4: Working with pins as inputs is quite different from outputs at the register level; we must call different functions. Description of these functions can be found below.

bcm2835_gpio_set_pud If a GPIO input pin is not connected to a voltage supply, it will ’float’. In other words, the value that is

2. BCM2835 does not use GPIO addresses; physical pin location is used instead, hence 12 used in the macro. 3. More specifically, map parts of physical memory which are related to peripher- als. 4. Information about all GPIO relevant registers and mode mappings for all GPIO pins can be found in [6, ch. 6]

14 4. Functions of GPIO Pins

read in is undefined. To get around this, a pull-up or a pull-down resistor is used. This way, the pin has got a default value which is deterministic. The responsibility of this function is to use one of the resistors mentioned above. This is done by writing to a GPPUD register [6, p. 100]. The default value is then overridden only by a stronger force (when a button connected to the pin is pressed, for example).

bcm2835_gpio_lev This function reads from a GPLEVn register, where the logic value of the pin is stored.

15 4. Functions of GPIO Pins

4.1.3 Interrupts When we refer to interrupts on pins, we mean interrupts from the client perspective. As we will learn, changes on GPIO pin values are in Bulldog (and therefore also in the debugger agent) in fact implemented using polling but the client receives those changes asynchronously. We can approach interrupts on GPIO pins in two different ways: polling5 for /sys/class/gpio/gpioX/value file or GPIO registers (such as GPREN, GPFEN, GPHEN or GPLEN [6, p. 90]). We will mainly speak about the first option since this is the one used in Bulldog.

Sysfs value files with epoll The idea behind this approach is to poll for changes in the /sys/class/gpi- o/gpioX/value file using epoll. Epoll is a Linux kernel system call which is available on any device running the Linux kernel by default. The GPIO section in the sysfs kernel documentation [17] states that the only content this file can have is either "1" or "0", making this approach quite robust and predictable. The direct disadvantage to this approach, no matter what the implementation is, is the dependency on the Linux kernel. On the other hand, the sysfs approach turns out to be less error-prone, as there is only one file per pin to look out for. What is more, working with sysfs does not require superuser privileges.

4.2 I2C

I2C (Inter-Integrated Circuit) is a multi-slave, multi-master serial in- terface developed by Phillips Semiconductors (now NXP Semiconduc- tors) [41]. The interface uses two bi-directional bus lines, a serial data line (SDA) and a serial clock line (SCL). Devices on the I2C bus are software addressable by a unique address and accessed this way by one or more masters. As I2C is a multi-master interface, more than one master can operate on I2C simultaneously, although some devices such as Raspberry Pi usually operate only with one master at a time.

5. Polling in this context means repeatedly checking for a value change in the appro- priate file or register. Time period between those checks would then be determined by some heuristic, e.g. the average time it takes for value to change.

16 4. Functions of GPIO Pins

4.2.1 Protocol definition

All transactions begin with a start bit and are terminated by a stop bit6. The I2C bus specification defines2 anI C message the following way [41, ch. 3]:

Figure 4.4: I2C timing diagram. Image taken from [12].

1. Data transfer is initiated with a START bit (S) signaled by SDA being pulled low while SCL stays high. 2. SDA sets the first data bit level while keeping SCL low. 3. The data is sampled (received) when SCL rises for the first bit (B1). 4. This process repeats, SDA transitioning while SCL is low, and the data being read while SCL is high, i.e. . 5. A STOP bit (P), terminating data transfer, is signaled when SDA is pulled high while SCL is high.

4.2.2 I2C data transmission - semantics

We use the least significant bit of the first of anI2C message to tell which operation (read or write) we want to be executed (see the diagram below). We also have to take into consideration the direction of the data being sent. That is, if the read operation is selected, a slave device sends data to a master. When the write operation is selected, data is sent from a master to a slave.

6. An I2C bus can also be in the idle state when no messages are currently being sent over the bus.

17 4. Functions of GPIO Pins

The first byte of the message is always the address of theslave master communicates with, followed by an arbitrary number of data bytes7. The diagram below uses 7-bit slave addressing. It is worth men- tioning that 10-bit addressing is also possible8.

Figure 4.5: I2C protocol diagram.

7. Although no other semantics is defined in the2 I C protocol, the first data byte is sometimes used by the slave as an address of its internal register to read or write to. 8. Instead of the first byte, we use the first two of the message to specify the slave address.

18 4. Functions of GPIO Pins 4.3 SPI

SPI is built on a master-slave architecture, developed by Motorola. The number of lines in SPI is not fixed as it depends on how many chip select lines an SPI bus has. Despite that being said, an SPI bus always consists of the following logic signals:

• SCLK: Serial Clock (output from master),

• MOSI: Master Output Slave Input, or Master Out Slave In (data output from master),

• MISO: Master Input Slave Output, or Master In Slave Out (data output from slave),

• SS: Slave Select (active low, output from master).

One master device can communicate with one or more devices at a time. There are two ways master and slaves can be connected: regular and another called daisy-chained bus.

19 4. Functions of GPIO Pins

Figure 4.6: Regular SPI connection, which is also used in Raspberry Pi. Master communicates with the slave with index i directly via SSi line. Therefore, slaves do not need to communicate with each other. Image taken from [40].

20 4. Functions of GPIO Pins

Figure 4.7: Daisy-chained SPI bus. Slaves are interconnected among each other (by using MISO and MOSI lines) in circle so that they can receive messages from master and send messages back to master via this chain. Image taken from [10].

4.3.1 SPI data transmission

Let us presume that the used connection scheme is the regular one, i.e. master has got designated SS lines for each slave. An SPI transaction is then defined as follows9 [30, ch. 8]:

9. It was immensely difficult to find any reliable source for the SPI bus specification. Therefore, we have to rely on other sources such as data sheets of devices which use SPI to infer the protocol definition. What is more, the "SPI bus is broadly accepted because it has little or no patent issues. This is partly because Motorola, its creator, provides no specification or central support. Those applying SPI can create hardware and software solutions without patent issues, but also without support or definition of supporting protocols." [37]

21 4. Functions of GPIO Pins

Figure 4.8: Schema of SPI data transmission. Image taken from [36].

1. A master initiates a transfer by pulling the SS signal of the desired slave low. 2. Once the SS signal is low, data is sent via MISO and/or MOSI lines. 3. The data transmission follows, LSB first, as long as the SS signal is being kept low. 4. Once the SS signal is pulled low, the transfer ends.

22 4. Functions of GPIO Pins 4.4 Other interfaces

Digital I/O (together with interrupts), I2C and SPI are all used in the debugger. However, there are also other alternative functions available on these pins which will be briefly described.

4.4.1 PWM Pulse-width modulation is a way of digitally encoding analogue signal levels. A PWM signal is still digital, current supply is either fully on or fully off. The analogue information is encoded using a series of onand off periods. The longer the current supply is switched on, thehigher the total power supplied to the load.

4.4.2 UART UART stands for Universal asynchronous receiver/transmitter. It is used for serial asynchronous transmission of data. UART can be con- figured by choosing the baud rate, parity, number of data bitsand number of start bits. UART uses two data lines for sending and re- ceiving data, which enables devices to transmit and receive data in full-duplex mode. UART can be used as a way to interface with other ASBCs which support this protocol [42].

23 4. Functions of GPIO Pins

4.4.3 PCM The most common technique to change an analogue signal to digital data. PCM works in three phases [11, p. 121]:

• The analogue signal is sampled10,

• The sampled signal is quantized11,

• The quantized values are encoded as streams of bits.

PCM is used in Raspberry Pi for audio related processing.

Now that we know what hardware interfaces are generally present on ASBCs, let us describe aspects specific to Raspberry Pi.

10. We already described the process of sampling in the chapter about digital I/O. 11. Quantizing is a process of dividing each measured value into one of L suitable VMAX −VMIN "pockets", each of size L , where VMAX is the maximum value and VMIN the lowest.

24 5 Raspberry Pi

5.1 Raspberry Pi as a single board computer

Raspberry Pi is a series of devices, albeit very similar to each other. One of the largest differences is hardware available, ranging from the minimalistic Raspberry Pi Zero to the most equipped Raspberry Pi 3 Model B (as of 2018). The underlying processor architecture is either ARMv6 or ARMv7. Chips used are BCM2835/6/7, depending on the specific device.

5.2 Uses

Raspberry Pi was founded and is developed by the Raspberry Pi Foun- dation (Foundation). From the Foundation’s memorandum [38], we can learn its intentions with Raspberry Pi: "Raspberry Pi Foundation was established in 2008 as a UK-based charity with the purpose to fur- ther the advancement of education of adults and children, particularly in the field of computers, computer science, and related subjects." The initial intentions with Raspberry Pi have been exceeded by use in commercial projects or as prototypes [1, 2, 19, 31, 35].

5.3 Raspbian

Although there are no strict limitations on which to use, Raspbian is currently promoted by the Foundation as the main operating system for Raspberry Pi. This Linux distribution is based on Debian and is optimized for the Raspberry Pi hardware. One of the reasons why Raspbian might be beneficial to use to- gether with Raspberry Pi is the support for both headless and graphi- cal configuration of the device. raspi-config, graphical configuration tool packaged with Raspbian, is a good example of this. raspi-config makes it possible to disable or en- able hardware interfaces on Raspberry Pi through a ncurses dialogue.

25 5. Raspberry Pi

Figure 5.1: raspi-config tool.

As for the headless configuration, Raspbian also reads from the config.txt file located in the boot partition. This serves as a convenient way to set up the system even before the first boot-up.

5.4 Accessing peripherals

We need to know the peripheral base address to access all the periph- erals. This address is specific to each BCM chip as we show below:

Chip Name Version name Peripheral base address BCM2835 Model A/B/B+, Zero 0x2000 0000 BCM2836 2 Model B 0x3F00 0000 BCM2837 2 Model B 0x3F00 0000

Table 5.1: Differences between BCM2835/6/7 including physical pe- ripheral base addresses [6], [20].

26 5. Raspberry Pi

Therefore, this address cannot be determined at compile time as the debugger supports all the Raspberry Pi versions. The BCM2835 library retrieves this information from a device tree available in the /proc file system, specifically from a binary file with the absolute path /proc/device-tree/soc/ranges. Then, four bytes are read from this file with an offset of four bytes and this quartet is considered to be the physical base memory address.

Figure 5.2: Binary data contained in /proc/device-tree/soc/ranges. The address of concern is highlighted in black.

27 5. Raspberry Pi

Knowing peripherals base address itself, however, is not suffi- cient for the agent to access peripherals. BCM2835 chip manual states that "The peripheral addresses specified in this document are bus ad- dresses. Software directly accessing peripherals must translate these addresses into physical or virtual addresses..." Method of how this is done in BCM2835 library follows. I/O peripherals are either available from physical memory which is kernel-only accessible or from virtual memory mapping (starting from 0xF200 0000 which is common for all BCM chips) which again falls into the address range only designated for the kernel. The BCM2835 library uses peripheral addresses available in the physical memory. To be able to point to this memory in a user space process, the BCM2835 library does the following steps:

1. Using the fopen function from the , open /de- v/mem, which is a file which provides access to physical memory, and retrieves file descriptor. If the user ID of the calling process (i.e. the debugger agent) is not equal to zero, open /dev/gpiomem instead1. This is because /dev/mem is readable only by root, the owner of this file, or any user belonging to the kmem group2. 2. Together with the knowledge of physical peripheral base ad- dress used as an offset for /dev/(gpio)mem, use descriptor from 1. to retrieve mapping to virtual memory using mmap. This system call maps files into memory and returns a pointer to the mapped area in the virtual address space (if mmap was successful in doing so, that is). 3. Use the memory pointer retrieved from 2 to derive base ad- dresses for all peripherals used in the library.

1. /dev/gpiomem is a restricted version of /dev/mem, and, as the name of the file suggests, permits only access to GPIO peripherals of the device. At the time of writing this thesis, no similar files were publicly available for I2C or SPI. 2. Nevertheless, having any regular user belonging to this group would obviously be a nontrivial security threat as the user would be able to read any part of the physical memory.

28 6 Debugger

In this chapter, we will discuss the result of this thesis which is the application itself. Debugger architecture is based on the client-server model where the agent acts as a server and the client side is represented by a graph- ical interface (see Appendix B for detailed information). Furthermore, the agent only passively replies back to client requests. An exception to this rule are messages about value changes generated on GPIO pins that are sent asynchronously. To access all supported interfaces on Raspberry Pi, the agent side must be run under superuser privileges, as will be explained later, so there is very little to be done concerning the security of the debugger for the time being. Despite that being said, the agent is still capable of running in a re- stricted mode that does not require superuser privileges, which only enables access to interrupt and digital I/O features of pins. However, it is possible that in the future, other interfaces could also be available for a regular user, making it unnecessary to run the agent under supe- ruser privileges altogether. We discuss this security issue more in the chapter "Possible improvements of the debugger and Bulldog".

29 6. Debugger 6.1 Use cases of the debugger

The following diagram depicts all the possible use cases available in the application.

Figure 6.1: Use case diagram of the debugger.

30 6. Debugger

Use case Description send an I/O request Read or write a value of digital signal for a specific GPIO pin. interact with I2C Read a sequence of N bytes from given slave or write a sequence of N bytes to an I2C de- vice present on a specified slave address. The agent then sends an appropriate response which is displayed inside the client. interact with SPI Write or read a sequence of N bytes from/to selected chip index. The agent then sends an appropriate response which is displayed inside the client. manage GPIO pin Register or remove interrupt listener for interrupts a specific GPIO pin on the agent side. The agent then generates messages for the client whenever interrupt on the pin has been gen- erated; interrupts are edge-triggered and it is possible to specify for which values to listen for: falling, rising or both. manage device con- Add new device using its IP address or host- nections name and from the collection of existing de- vices, connect or disconnect to it.

Table 6.1: Description of debugger use cases.

6.2 Protocol

To enable communication between the agent and the client, we de- signed a protocol specifically for this purpose.

6.2.1 Details of the protocol implementation String objects are directly sent over the network, i.e. no serialization is done upon these objects as a java.lang.String object is already repre- sented as a byte array, which makes further serialization redundant. This byte array is then received on the other side and parsed. If the

31 6. Debugger received message on the agent side is not valid according to the proto- col, a message informing about this parse error is still sent back to the client. The same is done from the other direction except the client does not send error messages back to the agent and logs protocol violations instead.

6.2.2 Agent A valid agent message is one of the following:

INIT:[BOARD_TYPE], GPIO:[PIN_NUMBER]:[HIGH|LOW], SPI:[BYTE_IN_HEX]*, SPI:WRITE_REQUEST_OK, I2C:[BYTE_IN_HEX]*, [INTR_STOPPED|INTR_STARTED|INTR_GENERATED] :[PIN_NAME]:[INTR_TYPE]:[TIME], [ILLEGAL_REQUEST]

where an [X] literal is an abstract representation of the token in the protocol definition which is then substituted by an appropriate sequence, i.e. an instance of I2C:[BYTE_IN_HEX]* is I2C:FF. The first message from the agent is considered to be the initializa- tion message. The client receives this message and shows the appro- priate interface to the user based on this message.

32 6. Debugger

6.2.3 Client The client sends messages to the agent when the user submits a request via the graphical interface. Response from the agent is then parsed and the graphical interface is then appropriately updated with new information. A valid client message is one of the following:

GPIO:READ:[PIN_NAME], GPIO:WRITE:[PIN_NAME], I2C:READ:[SLAVE_ADDRESS_HEX]:[LEN], I2C:WRITE:[SLAVE_ADDRESS_HEX]:[BYTE_IN_HEX]*, I2C:WRITE_READ:[SLAVE_ADDRESS_HEX]:[LEN]:[BYTE_IN_HEX]*, SPI:READ:[CHIP_INDEX]:[BYTE_IN_HEX]*, SPI:WRITE:[CHIP_INDEX]:[BYTE_IN_HEX]*, SPI:WRITE_READ:[CHIP_INDEX]:[BYTE_IN_HEX]*, GPIO:INTR_[STOP|START]:[PIN_NAME + '' + INTERRUPT_TYPE].

Messages containing the WRITE_READ sequence are added for convenience so that the user can sequentially write and read back with only one request1.

6.3 Libraries and frameworks used

No implementation of the graphical debugger existed before this work and therefore that is why we had to build it from the very beginning. However, this does not imply that no third-party libraries were used. Indeed, we tried to use as many suitable libraries as possible to avoid rewriting already existing code.

1. We can also obviously sent two consecutive messages based on only one user request but it makes sense to view it as just one request also on the protocol level as it is more efficient this way.

33 6. Debugger

The following list is an overview of libraries used in the debugger.

Library name Used for XStream [3] library for XML (de)serialization, used for saving user data, such as already entered IP addresses, submitted I2C and SPI requests Slf4j [34] logging facade Log4j [29] Slf4j implementation AssertJ [5] testing Java non-blocking I/O set of APIs used for networking in the (NIO) [16] debugger JavaFX [27] GUI platform

6.4 Networking

The client and the agent communicate over the network. We used non-blocking approach for the networking as some of the messages are sent asynchronously. This feature is present in Java NIO. A short overview of Java NIO follows.

6.4.1 Java NIO

In the standard Java, API dealing with the network is available. Non- blocking I/O (NIO) [16] is an extension to this. What NIO brings to Java networking is that it enables a programmer to write a non- blocking networking layer of the application. We use this feature also in the debugger.

34 6. Debugger

Figure 6.2: Blocking and nonblocking I/O. Images taken from [26].

Notice that the data storage is different, too. Blocking operations use Stream objects, whereas non-blocking operations use Buffer ob- jects. Buffers represent a form of containers where data are stored and sometime in the future are read via a Channel object. In blocking operations, data are always directly read from a Stream object, which includes actively waiting for new input - in other words, the operation is blocking.

35 6. Debugger 6.5 Usage

This section explains how to use the debugger. Each use case will be demonstrated on screenshots taken from the graphical client, the last section shows example output from the agent logger. We intentionally skip client logger output as it is primarily used for debugging of the application itself.

6.5.1 Initial state of the debugger

Figure 6.3: Client with five devices present in the "History" branch, one of which (with hostname eth_raspi) is selected for connection.

To be able to communicate with a given device, one must first specify the hostname he wishes to connect to. The hostname can also be an IP

36 6. Debugger

address. Adding a new device is achieved by typing such hostname into the text field in the right upper corner of this main window and pressing the submit button next to it. No assumption is made whether the passed string is a correct IP address or an alias. Instead, the client tries to resolve the IP address, like so:

private DeviceValueObject getNewDeviceFromUser(){ try { InetAddress inetAddr = InetAddress.getByName(ipAddress.getText()); return new DeviceValueObject(inetAddr); } catch (UnknownHostException ex){ LOGGER.debug("Invalid IP address"); LOGGER.error(ex.getMessage()); ControllerUtils.showErrorDialog("Unknown hostname."); } return null; }

This also implies that the client does not know whether the host is reachable at the moment. If the hostname is successfully resolved, a node is then added to the history branch of the device tree, located on the right-hand side of the split pane. This node is then used for connecting to the device and is persistently stored for later use.

37 6. Debugger

6.5.2 Connecting to a device

Figure 6.4: The client connected to Raspberry Pi.

From the "History" branch of the devices tree, the user selects the device he wishes to connect to and presses the "Connect" button. Two conditions have to be met to successfully connect to a device. Firstly, the desired host must be reachable by the client and secondly, the agent must be already running on the remote machine. In other words, the second condition is violated if a client port specific to the agent is not active and listening on the remote host, resulting in connection rejection on the agent side. Therefore, network errors are recognized even before the two sides begin exchanging protocol messages.

38 6. Debugger

Figure 6.5: Selection of netstat -nplt output with the agent running, which is, in this case, listening on port 8088. The other selected socket on port 12345 is the server socket.

39 6. Debugger

6.5.3 Disconnecting from a device

The user double clicks on one of the active nodes in the device tree or clicks the "Disconnect" button in the upper toolbar while selecting one of the active nodes. However, this only includes deliberate disconnect action from the client side. The client also automatically disconnects from the agent if the connection is lost or the user wants to shut down the client completely, forcing it to close all active connections established during the client session.

6.5.4 Digital I/O request

Figure 6.6: GPIO tab with GPIO2 read as low and GPIO3 read as high.

40 6. Debugger

The debugger is also capable of controlling the logic level on GPIO pins. In the graphical interface, this is achieved using buttons, each representing a pin present on the device. Each button label holds as its value a GPIO number of the given pin. To read from a pin, read mode must be activated using the radio button group in the GPIO tab. Then, the user clicks the button repre- senting the pin he wishes to read from. In the picture above, there are all three possible colours the button background can have - red for low, green for high digital value and grey (or any other default colour) for the pin which has not been used in the client session yet. To write to a pin, write mode must be activated. This mode toggles the digital voltage level the pin currently has. Nevertheless, this does not imply that the value presented in the client will always toggle to the different state as one might deduce. The reason for this is that pins are not being actively scanned, so the client only shows the last known value, not current digital voltage levels of pins. For more responsive scanning of pin values, interrupts are used instead.

41 6. Debugger

6.5.5 Interrupts As implied in the previous section, we use interrupts to actively scan for a change in a pin value. The user registers a new interrupt listener. This consists in selecting the event which user wants to register a lis- tener for and the pin itself. For events, there are three options available: rising edge, falling edge or both.

Figure 6.7: Interrupt table with two interrupt listeners, one of which is active. We can also see that the listener has caught five interrupts.

Please note that the time of the interrupt being received is the system time of the operating system the agent is running on. Raspberry Pi’s system time from the illustration above was intentionally modified so that it is visible that the time of adding listener does not have to necessarily correspond with the time any interrupt was received at.

42 6. Debugger

6.5.6 I2C request To realize an I2C request in the client, one of the following must be specified together with a hexadecimal slave address: • length representing the number of bytes to read for read re- quests • a non-empty byte array for write requests or write and read requests Desired data and mode specification can be either filled in man- ually or selected from the history of requests, which fill in the data automatically for the user instead (but still allow him to modify them). This is shown in the picture below.

Figure 6.8: Prefilled I2C request form.

43 6. Debugger

Responses received from the agent are then processed by the client and inserted into the table with information about when it was re- ceived and the body of the response itself, as shown below.

Figure 6.9: I2C table with two agent responses in the table.

6.5.7 SPI request

SPI requests are a bit more unified than I2C in that the byte array must be always supplied when communicating with this interfaces. See the SPI protocol definition for more information.

44 6. Debugger

Figure 6.10: SPI tab with two responses.

Alternatively, the debugger is capable of combined sequential write and read request in both I2C and SPI.

6.5.8 Agent The agent is deployed as a single JAR file2 and runs in an infinite loop until interrupted. The agent then waits for incoming connection requests and after connection to the client is established, it sends an initial message about itself. No graphical interface is present on the agent side, the activity of the agent is only logged for later use.

2. Issuing the command java -jar path/to/agent.jar should be therefore suf- ficient for deployment of the agent.

45 6. Debugger

Figure 6.11: Example of a logger output of the agent. This excerpt shows the start of the agent, its first connection to a client, two GPIO (read and write) requests and then disconnection from the client.

6.5.9 Testing mode The agent is primarily developed for Raspberry Pi devices but for convenience, it is also able to run on any machine with the JRE installed. When the agent is deployed on a device which does not have a BCM chip on it, the agent runs in the testing mode. As the name implies, this mode is to be primarily used for debugger testing. When we run the agent in this mode, protocol messages sent back to the client are populated with random data while still preserving the agreed-upon protocol.

46 7 Conclusion

The goal of this thesis was accomplished. The debugger is capable of controlling all interfaces listed in the thesis assignment. The project is open source, licensed under the MIT license and is publicly available together with all sources on GitHub [13], [14]. We were also able to improve the Bulldog library which was not capable of switching to alternative pin functions. Where possible, dependency on sysfs was removed to make this library less dependent on the Linux kernel. Implementing GPIO interrupts proved to be the most problematic part of the debugger. The debugger is capable of monitoring interrupts, but the usage is vastly limited. By limited we mean the frequency at which we can still process incoming interrupts.

7.1 Possible improvements

7.1.1 Bulldog

Bulldog modifications brought a new side effect - it must be run under root privileges to access all interfaces. Superuser privileges should be used only when it is necessary to do so. For digital I/O, there is a des- ignated file /dev/gpiomem [4] which does not require such privileges and is used by the low-level library. In the end, all interfaces should be accessed in Bulldog using this (or similar) file. It would be ideal for Bulldog to have no dependency on sysfs whatsoever - this would require implementation for each new device which would be added, but register approach would cause Bulldog (and any ASBC for that matter) to be much more powerful because the library would exploit the full range of functionality of the device. Last but not least, the low-level library which was integrated into Bulldog is an almost one-to-one copy of the original. This means that most of the code which actually changes the state of interfaces is the C portion of Bulldog. The solution to this would be to port as much of the low-level code into Java as possible. One of the benefits this would bring is easier Bulldog testability.

47 7. Conclusion

Generally, it is not possible to invoke system calls directly from Java, which also applies to epoll. Native calls using JNI must be used instead. However, using JNI usually makes the library harder to read and increases the library complexity. We can use Java Native Access (JNA) to reach better readability and maintainability of the library. More specifically, "JNA provides Java programs easy access to native shared libraries without writing anything but Java code - no JNI or native code is required. This functionality is comparable to Windows’ Platform/Invoke and Python’s ctypes. JNA allows you to call directly into native functions using natural Java method invocation. The Java call looks just like the call does in native code. Most of the calls require no special handling or configu- ration; no boilerplate or generated code is required." [24] Epoll calls could be rewritten to call JNA instead of JNI as they are supported in JNA. The GPIO interrupt API could be also rewritten from scratch. In- stead of using sysfs, Bulldog would use GPIO registers directly in- stead1.

7.1.2 Debugger The debugger is only capable of communicating with Raspberry Pi. Bulldog has already means of communicating with BeagleboneBlack and CubieBoard, so those two might be the most logical candidates for next ASBCs to be added to the debugger. Using graphical interface is very beneficial and efficient for many users, but for situations with very restricted system resources (on the client side, that is), it might also be useful to develop a command line interface. Command line arguments would match those defined in the protocol and, in the end, the same request string would be sent over the network to the agent.

1. This would require considerably more research and time than the sysfs alter- native, as there has not been much work done in this field in general. BCM2835 manual [6, p. 96] suggests the following: "GPIO Event Detect Status Registers (GPEDSn) The GPIO peripheral has three dedicated interrupt lines. Each GPIO bank can generate an independent interrupt. The third line generates a single interrupt whenever any bit is set." In other words, we would have to write an interrupt handler. Therefore, this approach would deal with interrupts on the hardware level and would always be chip specific. 48 7. Conclusion

7.1.3 Testing Writing unit tests for the agent proved to be quite challenging, as most of the functionality of the agent is directly related to hardware, i.e. hard-to-reproduce components in tests. One of the most crucial characteristics of tests is that they must be reproducible and deter- ministic. Therefore, we have to extensively use hardware component mocking. Because of this, test results might not reflect what can really happen at runtime as hardware components are not guaranteed to work in a predictable manner2. Nevertheless, both the agent and client include tests which verify the correctness of protocol messages.

2. This might include inconsistent response time of the hardware, for example.

49

Bibliography

[1] Permatasari, Okky, Masruroh, Siti Ummi, and Arini. “A pro- totype of child monitoring system using motion and authen- tication with Raspberry Pi”. In: 2016 4th International Confer- ence on Cyber and IT Service Management, Cyber and IT Service Management, International Conference on (2016), pp. 1–6. issn: ed- seee.IEEEConferenc. doi: 10.1109/CITSM.2016.7577516. [2] Tayeb, Shahab, Pirouz, Matin, and Latifi, Shahram. “A Raspberry- Pi Prototype of Smart Transportation”. In: 2017 25th International Conference on Systems Engineering (ICSEng), Systems Engineering (ICSEng), 2017 25th International Conference on, ICSENG (2017), pp. 176–182. issn: edseee.IEEEConferenc. doi: 10.1109/ICSEng. 2017.25. [3] Walnes, Joe. About XStream. GitHub, 2004-2018. url: http://x- stream.github.io/ (visited on 04/25/2018). [4] Elwell, Phil. Add /dev/gpiomem device for rootless user GPIO access. Pull request and discussion for kernel source tree repository for Rasp- berry Pi. GitHub, 2015. url: https://github.com/raspberrypi/ linux/pull/1112 (visited on 04/25/2018). [5] Costigliola, Joel. AssertJ. Fluent assertions for java. GitHub, 2013- 2018. url: http://joel- costigliola.github.io/assertj/ index.html (visited on 04/25/2018). [6] Broadcom Corporation. BCM2835 ARM Peripherals. Raspberry Pi Foundation, 2012. url: https://www.raspberrypi.org/app/ uploads/2012/02/BCM2835-ARM-Peripherals.pdf (visited on 04/25/2018). [7] Jaroš, Miroslav et al. Bulldog. Java GPIO Library for BeagleBoneBlack, Raspberry Pi and CubieBoard. GitHub, c2014-2018. url: https : //github.com/SilverThings/bulldog (visited on 04/25/2018). [8] McCauley, Mike. C library for Broadcom BCM 2835 as used in Rasp- berry Pi. AirSpayce, 2017. url: http://www.airspayce.com/ mikem/bcm2835/index.html (visited on 04/25/2018). [9] Wikipedia contributors. Comparison of single-board computers. Wikipedia, The Free Encyclopedia, 2018. url: https://en.wikipedia.org/ wiki/Comparison_of_single- board_computers (visited on 04/25/2018).

51 BIBLIOGRAPHY

[10] Burnett, Colin M.L. Daisy-chained SPI bus: master and cooperative slaves. Wikipedia, The Free Encyclopedia, 2006. url: https:// upload . wikimedia . org / wikipedia / commons / thumb / 9 / 97 / SPI_three_slaves_daisy_chained.svg/363px-SPI_three_ slaves_daisy_chained.svg.png (visited on 04/25/2018). [11] Forouzan, Behrouz A. and Fegan, Sophia Chung. Data communi- cations and networking. 4th ed. New York: McGraw-Hill Higher Education, c2007. isbn: 00-729-6775-7. [12] Floryan, Marcin. Data transfer sequence. Wikipedia, The Free En- cyclopedia, 2007. url: https://upload.wikimedia.org/wikipedia/ commons/thumb/6/64/I2C_data_transfer.svg/840px-I2C_ data_transfer.svg.png (visited on 04/25/2018). [13] Žežulka, Miloslav and Macík, Pavel. Debugger Agent. GitHub, 2017-2018. url: https://github.com/zezulka/GpioDebuggerAgent (visited on 04/25/2018). [14] Žežulka, Miloslav. Debugger Client. GitHub, 2017-2018. url: https: //github.com/zezulka/GpioDebuggerClient (visited on 04/25/2018). [15] Nipun. Difference Between Analog And Digital Signals. Pediaa.Com, c2015. url: http://pediaa.com/wp-content/uploads/2015/ 08/Difference-Between-Analog-and-Digital-Signals-A2D_ 2_bit_vs_3_bit.jpg (visited on 04/25/2018). [16] Oracle. Documentation for java.nio package. Oracle, c1993-2018. url: https://docs.oracle.com/javase/7/docs/api/java/ nio/package-summary.html (visited on 04/25/2018). [17] Linux Kernel Organization. GPIO Sysfs Interface for Userspace. Linux Kernel Organization, 2013-2018. url: https://www.kernel. org/doc/Documentation/gpio/sysfs.txt (visited on 04/25/2018). [18] Henderson, Gordon. GPIO Utility. Wiring Pi, c2018. url: http: //wiringpi.com/the-gpio-utility/ (visited on 04/25/2018). [19] Susana, Ernia and Tjahjadi, Hendrana. “Handheld pulse oxime- ter based on single board computer raspberry Pi B +”. In: 2017 15th International Conference on Quality in Research (QiR): Interna- tional Symposium on Electrical and Computer Engineering, Quality in Research (QiR) (2017), pp. 141–145. issn: edseee.IEEEConferenc. doi: 10.1109/QIR.2017.8168470. [20] Ultibo. Hardware units. BCM2835, BCM2836, BCM2837. Ultibo, 2018. url: https://ultibo.org/wiki/Unit_BCM2835 (visited on 04/25/2018).

52 BIBLIOGRAPHY

[21] Jarno, Aurelien. I2cdetect. Linux man page. Cyberverse, 2018. url: https://linux.die.net/man/8/i2cdetect (visited on 04/25/2018). [22] Delvare, Jean. I2cget. Linux man page. Cyberverse, 2018. url: https: //linux.die.net/man/8/i2cget (visited on 04/25/2018). [23] Maze, David Z. I2cset. Linux man page. Cyberverse, 2018. url: https://linux.die.net/man/8/i2cset (visited on 04/25/2018). [24] Doubrovkine, Daniel et al. Java Native Access (JNA). GitHub, 1998- 2018. url: https://github.com/java- native- access/jna (visited on 04/25/2018). [25] Oracle. Java Native Interface Overview. Oracle, c1993-2018. url: https : / / docs . oracle . com / javase / 7 / docs / technotes / guides/jni/spec/intro.html#wp725 (visited on 04/25/2018). [26] Jenkov, Jakob. Java NIO vs. IO. Jenkov Aps, 2014. url: http:// tutorials.jenkov.com/java-nio/nio-vs-io.html (visited on 04/25/2018). [27] Oracle. Java Platform, Standard Edition (Java SE) 8. Client Technolo- gies. Oracle, c2016. url: https://docs.oracle.com/javase/8/ javase-clienttechnologies.htm (visited on 04/25/2018). [28] Gibbons, Jonathan. JEP 313: Remove the Native-Header Generation Tool (javah). Oracle, 2017. url: http://openjdk.java.net/jeps/ 313. [29] The Apache Software Foundation. Log4j - Apache Log4j 2. The Apache Software Foundation, c1999-2018. url: https://logging. apache.org/log4j/2.x/ (visited on 04/25/2018). [30] Freescale Semiconductor. M68HC11E Family. data sheet. Freescale Semiconductor, 2005. url: https://www.nxp.com/docs/en/ data-sheet/M68HC11E.pdf (visited on 04/25/2018). [31] Deckert, Thomas, Rauchwerk, Dave, and Huber, Gustavo. OTTO. The Hackable GIF Camera. Kickstarter, c2018. url: https://www. kickstarter . com / projects / 1598272670 / meet - otto - the - hackable-gif-camera (visited on 04/25/2018). [32] Croston, Ben. Rpi.gpio 0.6.3. A Module To Control Raspberry Pi Gpio Channels. Python Software Foundation, 2018. url: https: //pypi.python.org/pypi/RPi.GPIO (visited on 04/25/2018). [33] Wikipedia contributors. Single-board computer. Wikipedia, The Free Encyclopedia, 2018. url: https://en.wikipedia.org/ wiki/Single-board_computer (visited on 04/25/2018).

53 BIBLIOGRAPHY

[34] QOS.sh. SLF4J documentation page. QOS.sh, c2004-2017. url: https: //www.slf4j.org/docs.html (visited on 04/25/2018). [35] Five Ninjas. Slice. A media player and more by Five Ninjas. Kick- starter, c2018. url: https://www.kickstarter.com/projects/ fiveninjas / slice - a - media - player - and - more (visited on 04/25/2018). [36] Rajewski, Justin. SPI. Embedded Micro, 2017. url: https:// cdn.shopify.com/s/files/1/2702/8766/files/spi.png?v= 1515690432 (visited on 04/25/2018). [37] stevenvh. SPI specifications. Stack Exchange Inc, 2012. url: https: //electronics.stackexchange.com/questions/30096/spi- specifications/30098#30098 (visited on 04/25/2018). [38] Foundation, Raspberry Pi. Strategy 2016 - 2018. Raspberry Pi Foundation, 2016. url: https://static.raspberrypi.org/ files/about/RaspberryPiFoundationStrategy2016- 18.pdf (visited on 05/01/2018). [39] Mochel, Patrick. Sysfs Filesystem. Linux Kernel Organisation, 2005. url: https : / / www . kernel . org / pub / linux / kernel / people/mochel/doc/papers/ols-2005/mochel.pdf (visited on 04/25/2018). [40] Burnett, Colin M.L. Typical SPI bus: master and three independent slaves. Wikipedia, The Free Encyclopedia, 2006. url: https://en. wikipedia.org/wiki/Serial_Peripheral_Interface_Bus# /media/File:SPI_three_slaves.svg (visited on 04/25/2018). [41] NXP Semiconductors. UM10204. I²C-bus specification and user manual. NXP Semiconductors, 2014. url: https://www.nxp.com/ docs/en/user-guide/UM10204.pdf (visited on 04/25/2018). [42] Cypress Semiconductor Corporation. Universal Asynchronous Re- ceiver Transmitter (UART). Cypress Semiconductor Corporation, 2010. url: http://www.cypress.com/file/132486/download (visited on 04/25/2018).

54 55 A. JNI A JNI

/* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class jni_NativeTools */

#ifndef _Included_jni_NativeTools #define _Included_jni_NativeTools #ifdef __cplusplus extern "C"{ #endif #undef jni_NativeTools_OPEN_READ_ONLY #define jni_NativeTools_OPEN_READ_ONLY 0L #undef jni_NativeTools_OPEN_WRITE_ONLY #define jni_NativeTools_OPEN_WRITE_ONLY 1L #undef jni_NativeTools_OPEN_READ_WRITE #define jni_NativeTools_OPEN_READ_WRITE 2L

/* * Class: jni_NativeTools * Method: open * Signature: (Ljava/lang/String;I)I */ JNIEXPORT jint JNICALL Java_jni_NativeTools_open (JNIEnv*, jclass, jstring, jint);

/* * Class: jni_NativeTools * Method: close * Signature: (I)I */ JNIEXPORT jint JNICALL Java_jni_NativeTools_close (JNIEnv*, jclass, jint);

#ifdef __cplusplus } #endif 56#endif

Listing 5: C header file for the NativeTools class. A. JNI

#include #include #include #include #include "jni_NativeTools.h"

/* * Class: jni_NativeTools * Method: open * Signature: (Ljava/lang/String;I)I */ JNIEXPORT jint JNICALL Java_jni_NativeTools_open (JNIEnv* env, jclass clazz, jstring path, jint flags) { char fileName[256]; int len=(*env)->GetStringLength(env, path), fd=0;

(*env)->GetStringUTFRegion(env, path,0, len, fileName); fd= open(fileName, flags); if (fd ==-1){ perror(fileName); }

return fd; }

/* * Class: jni_NativeTools * Method: close * Signature: (I)I */ JNIEXPORT jint JNICALL Java_jni_NativeTools_close (JNIEnv* env, jclass clazz, jint fd) { return close(fd); }

Listing 6: C source file for the NativeTools class.

57

B Sequence diagram of the debugger

Figure B.1: Sequence diagram of the debugger. This diagram only describes synchronous communication.

59

C Archive

The attached archive contains relevant files to the agent and the client which both consist of:

• source code (together with graphics in the case of the client)

• JAR file located in a build directory

• license

• README.md containing installation instructions

Apart from the agent and the client, there is also the source code of the modified Bulldog library used in the agent.

61