Embedded Linux Conference 2014, Bootlin participation

San JoséOne of the most important conference of the Embedded Linux community will take place at the end of this month in California: the Embedded Linux Conference will be held in San Jose from April, 29th to May, 1st, co-located with the Android Builders Summit. The schedule for both of these events has been published, and it is full of interesting talks on a wide range of embedded topics.

As usual, Bootlin will participate to this conference, but this participation will be the most important ever:

If you are interested in embedded Linux, we highly advise you to attend this conference. And if you are interested in business or recruiting opportunities with Bootlin, it will also be the perfect time to meet us!

Linux 3.14 released, Bootlin contributions inside!

Linus Torvalds has just released the 3.14 version of the Linux kernel. As usual, it incorporates a large number of changes, for which a good summary is available on the KernelNewbies site.

This time around, Bootlin is the 19th company contributing to this kernel release, by number of patches, right between Cisco and Renesas. Six of our engineers have contributed to this release: Maxime Ripard, Alexandre Belloni, Ezequiel Garcia, Grégory Clement, Michael Opdenacker and Thomas Petazzoni. In total, they have contributed 121 patches to this kernel release.

  • By far, the largest number of patches are related to the addition of NAND support for the Armada 370 and Armada XP processors. This required a significant effort, done by Ezequiel Garcia, to re-use the existing pxa3xx_nand driver and extend it to cover the specificities of the Armada 370/XP NAND controller. And these specificities were quite complicated, involving a large number of changes to the driver, which all had to also be validated on existing PXA3xx hardware to not introduce any regression.
  • Support for high speed timers on various Allwinner SOCs has been added by Maxime Ripard.
  • Support for the Allwinner reset controller has been implemented by Maxime Ripard.
  • SMP support for the Allwinner A31 SOC was added by Maxime Ripard.
  • A number of small fixes and improvements were made to the AT91 pinctrl driver and the pinctrl subsystem by Alexandre Belloni.
  • Michael Opdenacker continued his quest to finally get rid of the IRQF_DISABLED flag.
  • A number of fixes and improvements were made by Grégory Clement and Thomas Petazzoni on various Armada 370/XP drivers: fix for the I2C controller on certain early Armada XP revisions, fixes to make the Armada 370/XP network driver usable as a module, etc.

In detail, our contributions were:

Updated version of our kernel driver development course: Device Tree, BeagleBone Black, Wii Nunchuk, and more!

BeagleBone Black connected to the Wii Nunchuk over I2C
In the last few years, the practical labs of our Embedded Linux kernel and driver development training were based on the ARMv5 Calao USB-A9263 platform, and covering the ARM kernel support as it was a few years ago. While we do regularly update our training session materials, with all the changes that occurred in the ARM kernel world over the last two years, it was time to make more radical changes to this training course. This update is now available since last month, and we’ve already successfully given several sessions of this updated course.

The major improvements and updates are:

  • All the practical labs are now done on the highly popular ARMv7 based BeagleBone Black, which offers much more expansion capabilities than the Calao USB-A9263 platform we were using. This also means that participants to our public training sessions keep the BeagleBone Black with them after the session!
  • All the course materials and practical labs were updated to cover and use the Device Tree mechanism. We also for example cover how to configure pin muxing on the BeagleBone Black through the Device Tree.
  • The training course is now centered around the development of two device drivers:
    1. A driver for the Wii Nunchuk. This device is connected over I2C to the BeagleBone Black, and we detail, step by step, how to write a driver that communicates over I2C with the device and then exposes the device functionalities to userspace through the input kernel subsystem.
    2. A minimal driver for the OMAP UART, which we use to illustrate how to interface with memory-mapped devices: mapping I/O registers, accessing them, handling interrupts, putting processes to sleep and waking them up, etc. We expose some minimal functionality of the device to userspace through the misc kernel subsystem. This subsystem is useful to expose the functionalities of non-standard types of devices, such as custom devices implemented inside FPGAs.

And as usual, all the training materials are freely available, under a Creative Commons license, so you can study in detail the contents of the training session. It is also worth mentioning that this training session is taught by Bootlin engineers having practical and visible experience in kernel development, as can be seen in the contributions we made in the latest kernel releases: 3.9, 3.10, 3.11 and 3.12.

For details about cost and registration, see our Training cost and registration page.

Bootlin at the ARM Kernel Summit, the Embedded Linux Conference and the Buildroot Developers Meeting

Late october will be a busy moment for all the embedded Linux developers meeting in Edinburgh, UK. The Linux Foundation is organizing a number of conferences here, including the Embedded Linux Conference Europe (October 24-25) and LinuxCon Europe (October 21-23), and many co-located other events.

Bootlin will be present at several of these events:

  • First, three Bootlin engineers will be present at the ARM kernel summit on October 22nd and 23rd. The ARM kernel summit is an invitation-only conference, organized in relation with the Linux Kernel Summit. Gregory Clement, Maxime Ripard and Thomas Petazzoni, engineers at Bootlin have been invited due to their participation to the ARM support in the kernel, mainly on Allwinner SOCs for Maxime and on Marvell SOCs for Gregory and Thomas. Being present at this event is an excellent opportunity to be part of the discussion that shapes the future of ARM support in Linux, and strengthen our relations with other members of this growing community.
  • Then, the entire technical team of Bootlin will attend the Embedded Linux Conference, on October 24th and 25th. Several talks will also be given by Bootlin engineers:
    • On Thursday, 24th October at 11:40 AM, Thomas Petazzoni will give a talk titled Device Tree for dummies!, which will give an introduction to the Device Tree on ARM: what it is, how it is compiled, how it used by the kernel, how Device Tree bindings are defined, how drivers are affected by the Device Tree, etc.
    • At the same time in another room, Michael Opdenacker will lead a Bird of a Feather session dedicated to Small Businesses in the embedded Linux world. Exchanging experiences, networking with other companies working in the same field, etc.
    • Still on Thursday, at 3 PM, Gregory Clement will give a talk on the Linux kernel Common Clock Framework, which will be an updated version of the talk he gave at ELC earlier this year.
    • On Friday, 25th October at 9:30 AM, Thomas Petazzoni will be part of the keynote panel session dedicated to a discussion on Embedded Linux build systems together with Tim Bird (Sony Mobile), Ross Burton (Intel), and Karim Yaghmour (Opersys), the panel being moderated by Jeff Osier-Mixon (Intel).
  • On Saturday 26th and Sunday 27th October, the Buildroot community is organizing its traditional Developers Meeting, to which Thomas Petazzoni will participate. Some of the core Buildroot developers will join for two days of discussion and work to improve this embedded Linux build system.

As you can see, this will be a very interesting and busy week, and we’re all looking forward to meeting more embedded Linux developers and learning about the latest technologies in this field.

Bootlin the top #18 contributor to the 3.11 kernel

The 3.11 Linux kernel has now been released by Linus Torvalds, and as usual as thousands of patches coming from a large number of companies and contributors. For this release, Bootlin has contributed a total of 128 patches (yes, exactly 2^7), which makes Bootlin the 18th contributor in the list of companies contributing to the kernel, according to http://www.remword.com/kps_result/3.11_whole.html, before Broadcom and Cisco, and after ARM and Oracle. It is also the first time that six different engineers from Bootlin contribute code to the Linux kernel in a single release!

As usual, most of our contributions were centered around support for the Marvell Armada 370 and XP SOCs, the Allwinner SOCs and the Crystalfontz i.MX28 platforms:

  • Added support for the PCIe controllers of the Armada 370 and Armada XP platforms, and used it for the already supported Kirkwood platform. Supporting PCIe has been a very long process, which got started in December 2012, required long discussions with various kernel maintainers and multiple iterations of the patch series. Armada 370/XP was the first ARM platform to add Device Tree based PCIe support, and therefore this required many discussions to sort out the Device Tree bindings for PCIe controllers. This work was done by Thomas Petazzoni.
  • Enable an additional USB interface on the OpenBlocks AX3 platform, which is available as part of the mini-PCIe connector inside the device. This work was done by Thomas Petazzoni.
  • Cleaned up all the Kirkwood platform Device Tree files to assign the pin muxing configurations to the appropriate devices. This work was done by Thomas Petazzoni.
  • Made various cleanups and improvements in the Armada 370/XP platform code (in arch/arm/mach-mvebu) to make it possible to support different base address for the internal registers depending on the board being used. Many hardcoded physical addresses were removed, as well as the static virtual to physical mapping. This work was done by Thomas Petazzoni.
  • Cleaned up many ARM platforms to remove their unneeded ->init_irq() callback, and also the ->map_io() callback which we changed to default to calling debug_ll_io_init() when not provided. This work was done by Maxime Ripard.
  • Extended the ssd1307fb driver that we contributed a few releases ago to also support the SSD1306 device. The SSD1306 and SSD1307 are OLED screens controlled over I2C that are used on Crystalfontz i.MX28 platforms. We also optimized significantly the communication with the SSD130x devices. This work was done by Maxime Ripard.
  • Added an Ethernet driver for the Allwinner SOCs. The work was initially done by Stefan Roese, and our engineer Maxime Ripard did all the final cleanup, development of an MDIO driver, and integration with all the Device Tree files of the Allwinner platforms.
  • Added support for the Allwinner I2C controller, by re-using and extending the existing i2c-mv64xxx driver used on Marvell platforms, since the hardware block was very similar. The Allwinner Device Tree files were also updated to add the I2C controllers. This work was done by Maxime Ripard.
  • Added basic support for the Allwinner A10s SOC: pin muxing information and Device Tree information. This work was done by Maxime Ripard.
  • Added support for the Olimex A10s-Olinuxino-micro, a new hardware platform manufactured by Olimex that uses the Allwinner A10s SOC. This work was done by Maxime Ripard.
  • Implemented a “Device Bus” driver for the Marvell SOCs, that allows to configure the access to NOR flash and other devices connected to the memory bus. It has been used to enabled NOR support on the Armada XP DB development platform. This work was done by Ezequiel Garcia.
  • Fixed a few bugs in the IIO subsystem, and a build failure on AT91 platform when CONFIG_PHYLIB was not enabled. This work was done by Alexandre Belloni.
  • Fixed the ARM low-level code that handles compatibility with ATAG bootloaders, to properly convert 32 bits memory sizes passed by the bootloader into 64 bits cells of the Device Tree, when LPAE is used. This work was done by Gregory Clement.
  • Michael Opdenacker made a few improvements and fixes to the documentation.

For the upcoming 3.12, we already have 131 patches lined up, and a few more will probably show up after this blog post is written. Over the last release cycles, Bootlin has become a regular contributor to ARM support in the Linux kernel, and we’re looking forward to doing more contributions in the future.

The details of our 3.11 contributions is:

Bootlin contributions to the 3.10 kernel

The 3.10 Linux kernel has been released a few days ago. According to LWN, with almost 13.500 non-merge commits, the 3.10 has been the busiest ever, and also the fastest. Bootlin engineers again contributed to this release, with 99 patches integrated, making Bootlin the 28th most active company contributing, right between ST-Ericsson (103 patches) and ARM (97 patches). See http://www.remword.com/kps_result/3.10_whole.html for the complete statistics.

This time, Bootlin contributions include:

  • LPAE support for the Marvell Armada XP SoC, done by Grégory Clement.
  • Fix for errata 4742 of the PJ4B CPU core (used in Armada 370/XP), which prevented booting Armada 370 platforms after ARM optimized some TLB operations. Done by Grégory Clement.
  • Support for NOR flash on Marvell Armada 370 and Armada XP SoC, done by Ezequiel Garcia
  • Addition of a mvebu-mbus driver to handle the address decoding mechanism and configurable memory windows of Marvell SoC. The mach-kirkwood, mach-orion5x, mach-dove, mach-mv78xx0 and mach-mvebu Marvell platforms are all converted to use it. Developping this driver was a requirement to enable PCIe in a Device Tree compatible way on these platforms. Done by Thomas Petazzoni.
  • Addition of Device Tree information for the PCIe controllers of the Armada 370 and Armada XP, but unfortunately not the PCIe driver itself (which will arrive in 3.11). Done by Thomas Petazzoni.
  • Support for the thermal sensor on Marvell Armada 370 and Armada XP SoC, done by Ezequiel Garcia
  • A lot of reorganization of the Device Tree compatible strings for the Allwinner ARM SoC support, to prepare for the addition of additional SoCs in the future. Done by Maxime Ripard.
  • Improvements to the Allwinner pinctrl driver, with support for the A10 and A13 SoC. Done by Maxime Ripard.
  • Enabling of the I2C GPIO expander of the Armada 370 based Mirabox platform. Done by Grégory Clement.
  • A few updates to the support for the i.MX28 Crystalfontz boards: touchscreen and one-wire support on CFA10049. Done by Alexandre Belloni.
  • Various cleanups and improvements to the OMAP GMPC driver, done by Ezequiel Garcia.
  • Various cleanups and improvements to the Marvell Armada 370/XP IRQ controller driver, done by Thomas Petazzoni.

In detail, the contributions are:

Workshop on the Altera SoC FPGA platform

On June 25, 2013, Altera and some partner companies where organizing a workshop in Toulouse (where some of the Bootlin offices are located) about the Altera SoC FPGA platform. For $99, I participated to this full-day workshop, with a small training of the hardware and software tools available for this platform, and went away with a the development kit that was used for the practical labs, the Arrow SoCKit evaluation board.

sockit-1

The Altera SoC FPGA platform is a single chip that combines a dual Cortex-A9 processor and a Cyclone V FPGA (other variants are available, such as single core ARM, or bigger FPGAs). Since both are integrated on the same chip, it removes the need for a complex bus between the application processor and a separate FPGA, and it provides a very high bandwidth between the processor and the FPGA to exchange data. As can be seen on the following diagram, the Arrow SocKit evaluation board has a good number of peripherals, some of them connected to the HPS side of the processor (HPS stands for Hard Processor System, which is dual Cortex-A9 and all the hard peripherals), and some others connected to the FPGA side of the processor. Specifically, the workshop was centered around playing with the LEDs and the buttons connected to the FPGA side.

Block diagram of the SoCKit evaluation board
Block diagram of the SoCKit evaluation board

The morning of the workshop was dedicated to the hardware part, using two tools: Qsys (Altera’s System Integration Tool) and Quartus II (FPGA design). The Qsys tool allows to graphically build the hardware architecture of the SoC FPGA: you can bring the Hard Processor System, and then some additional FPGA IPs and connect them together. In the examples, two PIO IPs were added to the FPGA side, one to control LEDs and the other to control buttons. All the pin muxing and the DRAM configuration also takes place in Qsys, which in the end will automatically generate numerous elements:

  • FPGA code to be used by Quartus (for the FPGA side)
  • pre-loader source code (actually modifications to U-Boot to take into account the pin muxing and the DRAM configuration)
  • a Device Tree for the Linux kernel (that takes into account all the peripherals enabled in the system configuration)
  • etc.
Qsys allows to design the overall architecture of the SoC FPGA components, including all the FPGA IPs. On this picture, we see the two PIO IPs used to control LEDs and buttons.
Qsys also to design the overall architecture of the SoC FPGA components, including all the FPGA IPs. On this picture, we see the two PIO IPs used to control LEDs and buttons.

Once this system-level configuration is done with Qsys, Quartus is used to synthesize the FPGA side. Finally, the FPGA bitstream can be loaded into the FPGA, and using a JTAG connection and a System Console tool, one can directly read/write the registers of the FPGA IPs that have been integrated, and easily test them without having any software running. With the SOCKit evaluation board, the JTAG connection takes place through a USB to micro-USB cable, so no special hardware is needed.

The afternoon of the workshop was dedicated to the software part, obviously mostly centered on U-Boot and Linux. The pre-loader source code (actually the U-Boot SPL) is generated by the Qsys tool to take into account all the details of the system configuration, so after doing a build of U-Boot, the labs explained how to push the U-Boot binary to the board using the JTAG connection, under the DS-5 development environment (which is the development environment provided by ARM, based on Eclipse, with a special integration of Altera tools). The lab showed that you can set breakpoints, and do step by step execution of U-Boot, as one would expect. One nice thing is that the “Peripheral Registers” view in DS-5 is automatically updated according to the hardware components in the system: all the registers of the FPGA IPs we had integrated were immediately visible, and one was able to play with the LEDs and buttons directly from DS-5 through the JTAG connection. The remainder of the labs were dedicated to booting a pre-built Linux kernel, using a Device Tree generated by Qsys previously and loaded by U-Boot. Once Linux was booted, the labs were demonstrating how to play with the LEDs using /sys/class/leds/.

Registers of FPGA IPs are automatically visible in DS5
Registers of FPGA IPs are automatically visible in DS5

All in all, it was a great workshop, giving a good overview of the tools they offer and the capabilities of such platforms, I definitely recommend others to look for the other dates of this workshop and attend, it was well worth the price (dates in US, dates in Europe). I also appreciated that the amount of marketing/commercial was really reduced to the minimum. After the lunch break, there was an additional presentation by a person from Linear Technology about the power supply architecture of two boards based on this SoC FPGA processor, and it was very technical and highly informative.

As an embedded Linux developer, I’ve however found the tools to be too much based on graphical interfaces, with millions of windows and buttons to fill in, and a sensation of not really controlling which tool was doing what exactly. For example, it is a bit unclear at first which files are really your “source” files and which other files are generated. Having graphical interfaces also makes me wonder how all the build steps can be automated. It seems like version control and automated builds are not necessarily taken into account when designing those tools, but more investigation is certainly needed to get a good understanding of what those tools are doing.

On the Linux kernel side, it is worth noting that Altera has engaged into an upstreaming process for this architecture, and one can find some mainline support for this platform in arch/arm/mach-socfpga in the kernel tree. It is worth mentioning that Xilinx also has a similar architecture combining a dual Cortex-A9 and FPGA, called Zynq, which has mainline kernel support in arch/arm/mach-zynq.

And below, the front and bottom of the SoC Kit evaluation board:

SoC Kit evaluation board back side

SoC Kit evaluation board front side

GSoC: Buildroot gaining improved ARM multimedia support

Google Summer of Code 2013 logo

The Buildroot project is participating for the first time to the famous Google Summer of Code. This program, operated by Google, allows open-source projects to have students working on specific tasks for the summer, and the students get paid for their work, get mentored by open-source developers, learn about software development, open-source communities and more.

For its first participation to the GSoC, the Buildroot community has chosen one project: improving support for multimedia features of popular ARM SoCs. This consists in packaging in Buildroot all the necessary libraries and software components to support OpenGL, OpenVG, EGL, OpenMAX and similar technologies for the major ARM processors. The selected student for this project is Spenser Gilliland and Bootlin engineer Thomas Petazzoni is mentoring Spenser for this project.

The focus of the project is to add support for the multimedia features of the OMAP3, OMAP4 and AM33xx processors from Texas Instruments, the Broadcom processor found on the RasberryPi, the i.MX6 processor from Freescale, the Exynos 4 from Samsung and the Allwinner A1x processors. Throughout the next three months, support for the multimedia capabilities of those processors in Buildroot should become easier to use.

Spenser has already contributed support for GStreamer 1.x in Buildroot (which required upgrading the entire GLib/Gtk/Webkit stack) and OpenMAX support for the RasberryPi, and he is currently working on OpenGL support for the OMAP3/OMAP4/AM33xx platforms. The initial part of Spenser’s work will be in the next 2013.08 Buildroot release, while the remainder will have to wait the 2013.11 release.

For more details about the project, see its description on the eLinux.org wiki, and you can also keep track of Spenser’s progress.

Bootlin contributions to the 3.9 kernel

A few months ago, we published a blog post showing our contributions to the 3.8 Linux kernel. With 128 commits merged in 3.8, Bootlin was ranked as the 17th company in terms of kernel contributions.

The 3.9 kernel has been released a few weeks ago, with again a significant number of contributions from Bootlin. According to these statistics, Bootlin contributed 92 patches during the 3.9 cycle, making the company the 26th most important contributor to the Linux kernel for this release, and this time, five engineers from Bootlin contributed patches.

Among the contributions that we made:

  • Added a basic infrastructure for irqchip drivers in the drivers/irqchip directory. This directory is now used to store the drivers for the IRQ controllers of various processors.
  • Made a number of improvements to the Marvell SDIO driver, including the addition of a Device Tree binding for it, and enabled its usage on Marvell Armada 370 and Armada XP platforms, as well as converting the Marvell Kirkwood platforms to use Device Tree probing instead of legacy probing for their SDIO interface.
  • Contributed a number of improvements to support Crystalfontz i.MX28 based modules, including the Device Tree for the CFA10037 expansion board, various improvements for the CFA10049 expansion boards, and a driver for the Himax HX8357B LCD controller.
  • A large number of improvements to the support of the Allwinner ARM SoCs, most notably a pinctrl driver for those SoCs, which allows to configure the muxing of I/O pins, and a gpio driver, to use the pins as general-purpose I/Os. We also contributed the support for the Miniand Hackberry platform, based on an Allwinner SoC. This work is all done by our engineer Maxime Ripard, who is the maintainer of the Allwinner SoC support in the Linux kernel.
  • Improvements to the PCA953x driver (for I2C GPIO expanders) in order to support the PCA9505 chip, that has 40 GPIOs. This required quite some work, as the PCA953x was originally limited to chips having at most 32 GPIOs. This improvement was done in order to support the GPIO expander box provided by Globalscale for the Armada 370-based Mirabox platform.
  • We added support for the Real Time Clock on Armada 370 and Armada XP based platforms, added support for local timers on Armada XP, added support for the new Armada XP GP evaluation board.
  • We enabled support for the SPI controllers and the USB controllers on Armada 370 and Armada XP based platforms.

Our high rate of contributions is going to continue, as we already have 95 patches merged for the upcoming 3.10 kernel and have already submitted a number of patches for the 3.11 kernel.

Here are details about our contributions to the 3.9 kernel:

FIQ Handlers in the ARM Linux Kernel

Part of the work on the CFA-10036 and its breakout boards was to write a driver that was using the FIQ mechanism provided by the ARM architecture to bitbang GPIOs on the first GPIO bank of the iMX28 port controller.

Abstract

FIQ stands for Fast Interrupt reQuest, and it is basically a higher priority interrupt. This means that it will always have precedence over regular interrupts, but also that regular interrupts won’t mask or interrupt an FIQ, while an FIQ will mask or interrupt any IRQ.

FIQs are usually not used by the Linux Kernel, yet some infrastructure is available to do everything you need to be able to use the FIQs in a driver. And since Linux only cares about the IRQs, it will never mess with the FIQs, allowing to achieve some hard real time constraints, without having to bother about the masked interrupts.

There are two more things to know about the FIQs. First, FIQs are executed in a dedicated execution mode, and this FIQ mode has 7 dedicated registers, from r8 to r14. This allows to have persistent values between each FIQ handler code, and avoids the overhead of pushing and popping in the handler. The second thing to know is that, unlike the regular IRQ handlers, the FIQ handler has to be written using ARM assembly, mostly because the C compiler won’t produce any code that can use only these r8 to r14 registers.

Practical case

In the CFA-10036 case, we wanted to bitbang a set of GPIOs at a programmable interval with a microsecond accuracy, and from a userspace application. The setup we chose was to make a large memory buffer of instructions available to userspace through mmap, and use a simple consumer/producer setup. An instruction was basically the interval to the next handler firing, which GPIOs values to clear, and which ones to set.

Step 1: Setup a timer

One thing to keep in mind is that basically, we will do many things behind the kernel’s back. So you won’t be able to use the standard kernel framework APIs from the FIQ handler. That means that we won’t be able to use the gpiolib, the regular timer API, etc. So you have to make sure to use either something that is not used at all by the kernel or something the kernel can deal with. The first thing to do then is to register a timer so that we can generate our FIQ on a regular basis. Here, we chose the third iMX28 timer, that is the first timer not used by the kernel. Of course, since it is device dependent and not using the kernel’s API, we had to do the timer initialization by hand in our driver.

We obviously made it generate an interrupt when it expires, and then had to poke into the iMX28 interrupt controller to generate a FIQ from this interrupt. How to achieve this is once again dependent on the hardware, and some architectures provide functions to do so (s3c24xx_set_fiq for Samsung’s Exynos, mxc_set_irq_fiq for Freescale’s IMX, etc.) while some others don’t, like it was the case for iMX28 (which is part of the MXS architecture), so we had to do it by hand once again in our driver.

Once this is done, we now have a timer that generates an FIQ on a regular basis. The second step will obviously be to register our handler for this FIQ.

Step 2: Register our handler

Registering an FIQ handler is actually quite simple. The first thing to do is actually to call the claim_fiq function, that mostly makes sure no other FIQ handler has already been registered.

The next step is to register your FIQ handler. This is done with the set_fiq_handler function. This  function takes a pointer to the handler and the size of the handler code as argument, to basically memcpy your handler directly into the interrupt vector.

Most of the time, we would have something like below in our assembly code, and compute the handler size by the difference between the two labels.

my_handler:
handler code
my_handler_end:

Beware that it can get nasty, especially when you use a numeric constant that will get stored in a literal pool (for example when storing large variables into a register using LDR), if you  don’t pay attention, the literal pool will be stored outside of the bounds you asked to copy, resulting in the value you use in the actual FIQ handler being garbage. We can also pre-set some register values that you will find in FIQ mode, typically to pass arguments to your handler, using the set_fiq_regs function.

The last step is obviously to enable the FIQ, using the enable_fiq function.

Once this is done, we have the basic infrastructure to process the data that will come from the shared buffer.

Step 3: Allocate the instruction buffer and share it

We needed a pretty large instruction buffer to share with userspace. We wanted to store about 1 million instructions in the buffer, each instruction taking 12 bytes (3 unsigned long integers), which makes around 12 MiB.

The usual allocation mechanism couldn’t be used, because __get_free_pages can only allocate up to 512 pages. Each page on ARM being of 4 KiB, this function is thus limited to 2 MiB.

So we chose to use CMA (Contiguous Memory Allocator) that was introduced in the 3.4 kernel, and is used precisely to allocate large chunk of contiguous memory. It achieves this by allocating a given size of movable pages at boot time, that will be used by the kernel as long as no one needs them, and will be reclaimed when a driver needs them. CMA is also used directly through the regular DMA API, so we’re in known territory.

The first thing to do to use CMA is to declare the memory region we want to reserve for our device in the device tree (we have been using the “Device tree support for CMA” patchset).

As you may know, the device tree is for hardware description and the CMA shouldn’t be in it at all, since it doesn’t describe the hardware in itself, but how we need to allocate the memory for a given piece of hardware. The chosen node is here exactly for that, since it will hold all the things the system needs, but doesn’t describe hardware. A similar case is the kernel command line. In our case, we add a subnode to chosen, with which amount of memory we should pre-allocate (0xc00000, which is 12 MiB, in our case), at which kernel address (0 in our case, since we basically don’t care about the base address of the buffer, we just want it to be there), and which device should use it.

Then, in our driver, we only need to call dma_alloc_coherent from our driver, and that’s it.

Now, we need to share this memory through mmap. This wouldn’t be a big deal, except for the caches. Indeed, the ARMv5 caches are virtually tagged, resulting in cache coherency problem when using two different virtual addresses pointing to the same physical address, which is exactly the situation we will be in.

We thus need to disable the cache on this particular mapping. This is done through a flag set with the pgprot_noncached function, that sets the page protection flags before calling the remap_pfn_range function in the mmap driver hook.

This should be ok by now, and you should be able to use the data inside the buffer from both sides now.

Step 4: Actual Results

We here tried to generate a 50kHz square waveform by bitbanging the GPIOs both using a FIQ and using a regular IRQs, and here is the result (to emulate some load on the system, a dd if=/dev/zero of=/file was run when the captures were taken).

interrupt

This is using regular IRQs. We can notice several thing wrong about this. The first one is pretty obvious, since we have a lot of jitter. The next one is that even though we requested a interval between each timer firing of 10microseconds, we here see that we are more around 16us, with quite a lot of latency.

Now, here is what we get with an FIQ:

fiq

We can see that there’s no longer any jitter, the 50kHz square waveform we requested is almost perfectly output by our FIQ handler. We can notice however that there is still a constant ~1us latency, presumably because we had to reprogram the timer from our handler.

Final Words

Working on this FIQ thing has been really great, mostly because it involved several things I wasn’t used to, like CMA, or to make sure the kernel could deal with something changing behind its back. For example, we had to change slightly the imx28 gpio driver, because it was keeping an internal cache of the GPIO values it previously set, resulting in a pretty nasty behaviour when changing a GPIO value from the FIQ, and then controlling another one through the regular GPIO interface.

The application for this was to generate waveforms sent to stepper drivers, to control a 3D printer from the CFA-10036. You can watch the end result of all this work on Crystalfontz‘ Youtube channel, and especially on this video:

Finally, we can conclude that the FIQ can be an effective way to achieve near-real-time latencies, on a vanilla kernel without any RT patches.

Of course, you can find the whole code on Crystalfontz Github, most notably the driver, the handler and a small application demo for it.