Userspace application for QEMU custom memory-mapped device

Userspace application for QEMU custom memory-mapped device

This is part 3 of the Linux device driver development post series.

In the previous post the structure of a Linux device driver for the custom memory-mapped peripheral in QEMU was shown.

In this post we will cover the following things

Developing userspace application for designed memory-mapped device

The driver that was developed in the previous post provides interface to our custom memory-mapped peripheral. What remains is to make an application that will interact with the hardware using that driver.

The application should be able to initialize the device and then block until interrupts arrive, when it should capture the value from the DATA register and print it.

Device initialization

In order to initialize the device the application needs to:

  1. turn it on via EN bit;
  2. select desired frequency via FREQ bit;
  3. enable interrupt generation via IEN bit.

Since all of these bits are accessible via implemented sysfs attributes, the application should access this files and perform appropriate writes.

After device is initialized, the application will go into an infinite loop waiting for interrupt to happen.

Interrupt handling (poll)

The title of this subsection might be misleading, since interrupt handling is done in the kernel driver code. However, the device driver only acknowledges the interrupt and clears interrupt flag, so interrupt processing is left to the application code. The notification from device driver to user space is implemented via sysfs_notify function on interrupt sysfs attribute.

In order for user space application to be able to be woken up when interrupt happens we will use poll system call. It will make application thread to block while waiting for notification from device driver. Once interrupt is received, the application will be woken up and continue processing.

As for the processing, the application should read the data register (the processed value provided by the sysfs attribute) and print the value that was read.

Coding ideas

In this case I opted for using C++/CMake implementation presented in github repository.

The low-level access to sysfs attribute files and poll syscall is implemented in the Poller class. This class handles initialization and interrupt notification so the higher level code can only worry about handling of read data.

The Poller class will provide method to do the device initialization. It will also provide a method to start a thread where it uses poll syscall to wait for notification from sysfs attribute interrupt. Once notification is received, Poller will read the data sysfs attribute and print read value.

After Ctrl+c is pressed the application will call method from Poller to disable interrupt generation and turn the device off.

Building application

Using arm-none-linux-gnueabihf

CMake is chosen as the build system. Since we are cross-compiling for ARM architecture, we need to provide the toolchain.cmake file, which describes everything related to cross-compilation toolchain.

An example for arm-none-linux-gnueabihf toolchain is in github repository.

When setting up the build system, we will pass that toolchain file to cmake using -DCMAKE_TOOLCHAIN_PATH. The rest of the process is the standard CMake flow.

mkdir build && cd build
cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchain.cmake ..
make -j

The resulting mmsens-app binary file will be in the build directory.

Using Yocto SDK

Yocto can be used to create and SDK which includes all required development libraries and build tools.

In order to build the SDK, process similar to building image (presented in Yocto posts) with additional parameter of -c populate_sdk.

source setup-environment build_fb
DISTRO=mistra-framebuffer MACHINE=cubieboard bitbake mistra-image -c populate_sdk

The resulting toolchain file will be in build_fb/tmp/deploy/sdk/, the mistra-framebuffer-glibc-x86_64-mistra-image-cortexa8t2hf-neon-cubieboard-toolchain-4.0.sh.

Toolchain and SDK is installed using

./mistra-framebuffer-glibc-x86_64-mistra-image-cortexa8t2hf-neon-cubieboard-toolchain-4.0.sh
Mistra FrameBuffer SDK installer version 4.0
============================================
Enter target directory for SDK (default: /opt/mistra-framebuffer/4.0):
You are about to install the SDK to "/opt/mistra-framebuffer/4.0". Proceed [Y/n]?
Extracting SDK...........................................done
Setting it up...done
SDK has been successfully set up and is ready to be used.
Each time you wish to use the SDK in a new shell session, you need to source the environment setup script e.g.
 $ . /opt/mistra-framebuffer/4.0/environment-setup-cortexa8t2hf-neon-mistra-linux-gnueabi

From our mmsens-app we can initiate the build of the application in the following way

source /opt/mistra-framebuffer/4.0/environment-setup-cortexa8t2hf-neon-mistra-linux-gnueabi
mkdir build && cd build
cmake ..
make -j

There is no need to pass the toolchain file since sourcing environment script already does that for us.

Testing application

If application is built manually, it needs to be copied to the rootfs of the SD card image following part 2 of QEMU Board emulation.

Once application is in root filesystem, it needs to be started using ./mmsens-app (if not in $PATH) or mmsens-app (if in $PATH).

The application will print the read value from the data register, and can be gracefully stopped by pressing Ctrl+c.

./mmsens-app /sys/class/mmsens/mmsens0
Hello World!
Initial 0001
0002
0003
0004
0005
0006
^C
0007

The initial value can be passed as a second argument when invoking the application, like

./mmsens-app /sys/class/mmsens/mmsens0 4660
Hello World!
Initial 1234
1235
1236
^C
1237

The value 4660 is written as 0x1234 in hex notation, so 4660 represents BCD number 1234.

App testing

Summary

In this blog post userspace application development for custom QEMU memory mapped sensor is presented.

The application encapsulates the sysfs files access and can block until interrupt is received so it can process it.

It can be improved with unit tests, as well as more interactive behavior, but it is left for some other time.

Subscribe
If you would like to get information as soon as new content is published, please subscribe to the "MistraSolutions newsletter".