Kernel Drivers vs. Userspace Drivers: A Guide for Embedded Linux Developers

Reading Time: 4 minutes

Introduction

In Embedded Linux projects, developers dedicate a substantial amount of time to managing external hardware interfaces. A common dilemma they face is deciding between developing a custom kernel driver (kernel module) or a userspace driver/application for a specific device. This decision can be intricate, as the optimal approach hinges on multiple factors. Making the wrong choice can result in extensive development efforts and potential stability issues in the implementation.

In this article, we will explore various factors that should be considered before making this decision. This article will not explain the deep levels of drivers nor give examples for some of the frameworks and methods presented here. It will however give some good guidance to help you and your team decide on whether to use kernel or userspace drivers.

Definitions

First let us start with the definitions when we are speaking of drivers.

Device or Peripheral: Some real hardware that sits either internally in an SoC, or externally on a PCBA or card. Think I/O, register spaces, buses, etc. This device requires some software to properly configure or control it.

Driver: A piece of software that is required to properly configure or control a device or peripheral.

Kernel Driver (kernel module): A driver that is running in kernel space. This can either be an LKM (loadable kernel module) or a built-in module – both apply to this discussion.

Userspace Driver: A driver that is running in userspace. It could be an application or a script, but it is relying on underlying libraries or kernel frameworks that allow it access to I/O, memory, etc.

Kernel Drivers

Kernel drivers come in many forms, but they all run in kernel space when executing. This gives them access to basically any of the major functions in the Linux kernel. With this access however comes some responsibility, as poorly written drivers can at best cause warnings and at worst panic the kernel and crash the running system. The drivers that “ship” with the Linux kernel fall under this category. There are dozens of types of devices, and various supporting frameworks within the kernel for each. Creating and modifying such drivers obviously requires expertise with the Linux kernel itself.

Userspace Drivers

The modern Linux kernel is filled with many frameworks that actually make it possible and sometimes even relatively easy to create userspace drivers in Linux. We will explore several of these, but certainly our list here is not an exhaustive one:

UIO: The UIO (userspace I/O framework) enables the creation of basic drivers that need to map I/O and occasionally handle interrupts. Although users can develop Linux kernel drivers using the UIO framework, there are several generic implementations already included in the kernel that can be directly utilized from userspace. Often, this can be achieved with some simple device tree additions and/or boot arguments.

This framework has become very popular in the FPGA space, as users can write drivers directly into their applications, controlling underlying IP, even handling interrupts.

spidev: The spidev framework is a Linux kernel implementation that exposes SPI buses to userspace as character devices in /dev, allowing users to communicate with SPI devices using a specific API or through various userspace applications. This approach facilitates the creation of pseudo SPI device drivers using shell scripts, making it accessible to users who may not be familiar or comfortable with kernel code.

i2c-dev: Like spidev, the i2c-dev framework exposes I2C buses to the userspace as char devices. Several userspace utilities and libraries are available as well, paving the way for drivers written as both traditional applications or scripts alike. With the large amount of external hardware that interfaces using I2C, this makes i2c-dev a good driver implementation choice for many embedded Linux designs.

Making the Choice

Choosing between a kernel driver or a userspace driver is not often straightforward. Below we will present some guidelines, however none of these rules are hard-and-fast as every design differs and there are potentially tradeoffs in any application:

  1. Is there an existing kernel driver available for the hardware?
    If so, 9 times out of 10, it is probably best to use this driver, especially if it has been upstreamed. If the driver does not meet all requirements of your design, then you should consider modifying it, and contributing your changes to upstream.
  2. Does the device practically need to directly integrate with or utilize some existing kernel framework?
    A few examples of these are devices which need to utilize V4L2 (video4Linux2), DRM/KMS (display), USB or APIs like DMA which are not directly exposed to userspace. In these cases, a kernel module may be necessary, or at minimum, creating a kernel driver that acts as a bridge interface to userspace might be acceptable as well.
  3. Is there an existing userspace interface that would allow you to bypass writing a driver?
    As discussed in the Userspace Driver section above, the Linux kernel has several frameworks allowing direct userspace access to hardware and memory. Thus, if your driver could be written using one of these, this may be a good choice.
  4. Are you or your team familiar with how to write kernel drivers?
    If you have answered no to all of the above and land here, then you should consider whether your team has the knowledge and skills to write a kernel driver. If not, it may be wise to consult a professional who can help you analyze your requirements and make a decision on the best approach here.

Summary

In this article, we explained some of the key points we believe should be considered when considering what type of Linux driver to use. These considerations arise from our hands-on experience assisting numerous customers in making informed decisions and implementing suitable solutions. Regardless of whether your design falls within categories #1 through #4 above, we highly recommend seeking guidance from professionals like Cornersoft Solutions for your Embedded Linux device driver requirements. Our extensive experience in developing customized solutions for clients ensures that we can provide tailored solutions to meet your unique needs.

Leave a Comment

Your email address will not be published. Required fields are marked *