Embedded Linux device drivers: Reading driver state at runtime

July 31, 2018

CHRIS.SIMMONDS_#1-July 31, 2018

Editor's Note: Embedded Linux has consistently ranked among the top operating systems used in embedded system design. With the rapid growth in interest in the Internet of Things (IoT), the ability of embedded Linux to serve multiple roles will prove vital in supporting diverse needs at each layer of the IoT application hierarchy. In turn, the ability of engineers to master embedded Linux systems will become critical for achieving rapid, reliable development of more sophisticated systems. In Mastering Embedded Linux Programming - Second Edition, author Chris Simmonds takes the reader on a detailed tour across the breadth and depth of this important operating system, using detailed examples to illustrate each key point.

In this excerpt, Chapter 9, from the book, the author describes how kernel device drivers interact with system hardware and how developers can write device drivers and use them in their applications. This article continues this excerpt. Be sure to read the earlier entry: Part 1.

Adapted from Mastering Embedded Linux Programming - Second Edition, by Chris Simmonds.

Chapter 9. Interfacing with Device Drivers (Continued)
By Chris Simmonds

Finding out about drivers at runtime

Once you have a running Linux system, it is useful to know which device drivers are loaded and what state they are in. You can find out a lot by reading the files in /proc and /sys.

First of all, you can list the character and block device drivers currently loaded and active by reading /proc/devices:

  # cat /proc/devices
   Character devices:
     1 mem
     2 pty
     3 ttyp
     4 /dev/vc/0
     4 tty
     4 ttyS
     5 /dev/tty
     5 /dev/console
     5 /dev/ptmx
     7 vcs
    10 misc
    13 input
    29 fb
    81 video4linux
    89 i2c
    90 mtd
   116 alsa
   128 ptm
   136 pts
   153 spi
   180 usb
   189 usb_device
   204 ttySC
   204 ttyAMA
   207 ttymxc
   226 drm
   239 ttyLP
   240 ttyTHS
   241 ttySiRF
   242 ttyPS
   243 ttyWMT
   244 ttyAS
   245 ttyO
   246 ttyMSM
   247 ttyAML
   248 bsg
   249 iio
   250 watchdog
   251 ptp
   252 pps
   253 media
   254 rtc
   Block devices:
   259 blkext
     7 loop
     8 sd
    11 sr
    31 mtdblock
    65 sd
    66 sd
    67 sd
    68 sd
    69 sd
    70 sd
    71 sd
   128 sd
   129 sd
   130 sd
   131 sd
   132 sd
   133 sd
   134 sd
   135 sd
   179 mmc

For each driver, you can see the major number and the base name. However, this does not tell you how many devices each driver is attached to. It only shows ttyAMA but gives you no clue that it is attached to four real serial ports. I will come back to that later when I look at sysfs.

Of course, network devices do not appear in this list, because they do not have device nodes. Instead, you can use tools such as ifconfig or ip to get a list of network devices:

# ip link show
   1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state
       link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
   2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc
    pfifo_fast state DOWN mode DEFAULT qlen 1000
       link/ether 54:4a:16:bb:b7:03 brd ff:ff:ff:ff:ff:ff
   3: usb0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc
    pfifo_fast state UP mode DEFAULT qlen 1000
       link/ether aa:fb:7f:5e:a8:d5 brd ff:ff:ff:ff:ff:ff

You can also find out about devices attached to USB or PCI buses using the well-known commands: lsusb and lspci. There is information about them in the respective manual pages and plenty of online guides, so I will not describe them any further here.

The really interesting information is in sysfs, which is the next topic.

Getting information from sysfs

You can define sysfs in a pedantic way as a representation of kernel objects, attributes, and relationships. A kernel object is a directory, an attribute is a file, and a relationship is a symbolic link from one object to another. From a more practical point of view, since the Linux device driver model represents all devices and drivers as kernel objects, you can see the kernel's view of the system laid out before you by looking in /sys, as shown here:

# ls /sys
   block     class     devices   fs        module
   bus       dev       firmware  kernel    power

In the context of discovering information about devices and drivers, I will look at three of these directories: devices, class, and block.

The devices: /sys/devices

This is the kernel's view of the devices discovered since boot and how they are connected to each other. It is organized at the top level by the system bus, so what you see varies from one system to another. This is the QEMU emulation of the ARM Versatile:

  # ls /sys/devices
   platform    software    system      tracepoint  virtual

There are three directories that are present on all systems:

  • system/: This contains devices at the heart of the system, including CPUs and clocks.

  • virtual/: This contains devices that are memory-based. You will find the memory devices that appear as /dev/null, /dev/random, and /dev/zero in virtual/mem. You will find the loopback device, lo, in virtual/net.

  • platform/: This is a catch-all for devices that are not connected via a conventional hardware bus. This maybe almost everything on an embedded device.

The other devices appear in directories that correspond to actual system buses. For example, the PCI root bus, if there is one, appears as pci0000:00.

Navigating this hierarchy is quite hard, because it requires some knowledge of the topology of your system, and the path-names become quite long and hard to remember. To make life easier, /sys/class and /sys/block offer two different views of the devices.

Continue reading on page two >>


< Previous
Page 1 of 2
Next >

Loading comments...