wiki:TBR/Review/RsgTrialsAndTribulations

RsgTrialsAndTribulations

SPI Driver Development

Major/Minor? Device Driver Numbers

As is commonly done in various OS environments, device resources are assigned major and minor "device numbers" by RTEMS. While this concept is quite simple on the face of it, with libi2c things are a bit more complicated. An explanation of how these numbers are assigned was provided to me by Till Straumann:

"Traditionally, the major number is associated with a particular driver (registered with the OS) the minor number with a device instance; ultimately the semantics of the minor number are defined by the driver, the major number by the OS."

"libi2c registers itself with RTEMS under one major number and it uses specific semantics for the minor number."

One thing to realize here is that the major number here applies to the libi2c driver, which includes both I2C and SPI interfaces. So a hypothetical system could have two I2C and three SPI controllers, each with a number of devices attached. RTEMS would assign the same major number to all controllers and devices; only the minor number for each device would differ.

Device Minor Numbers

So, device minor numbers hide quite a bit of complexity behind a simple integer! Again from Till:

"The 'minor' number actually encodes three things:

# 'device' driver (e.g., temp. sensor) as registered with rtems_libi2c_register_drv(). The device driver knows what to write to/read from the device to achieve certain things. However, it doesn't know how to interact with the particular i2c/spi controller chip in order to write to/read from the device. # 'bus' driver (for a particular i2c/spi controller) as registered with rtems_libi2c_register_bus(). The bus driver knows how to communicate with the attached devices but it doesn't know about the semantics. # device address on the bus (multiple devices using the same 'device' and 'bus' drivers may be present."

SPI Usage

Yet again, from Till:

a) you register a bus-driver for your SPI chip with libi2c and get a bus number returned.

b) you register a device-driver for your EEPROM with libi2c on a bus (use number from step a) at a device address on that bus. You obtain a minor number back.

Optionally, step b) also creates a file system entry (mknod) with your name of choice, libi2c's major number and the minor number from step b)

Step b) can be repeated for multiple instances of identical devices (same dev-driver but different dev-address => different minor number).

Read Example

Even more from Till:

"Here's what happens when you e.g., read() from a libi2c device:

  • OS knows (by major number) that it has to call libi2c
  • OS dispatches rtems_i2c_read()
  • libi2c figures out what bus and device drivers (as registered in a+b) to use. It sends a addressing sequence using the bus driver and the device address (encoded in minor number)
  • libi2c calls the 'device' driver's 'read' function
  • the 'read' function does it's job (e.g., if you read from a thermometer the driver has to i) trigger a measurement, ii) read back from the device, interpret the results and hand them to the user.
  • the device driver accomplishes i), ii) using libi2c's low-level routines rtems_libi2c_start_write_bytes & friends to interact with the device
  • low-level routines use the bus driver (as encoded in 'minor') to actually perform the communication

A bit complicated but it strictly separates drivers for the bus controllers ('how' to read/write) from the drivers for the attached devices ('what' to read/write).

Look in libchip/i2c for examples of libi2c 'device' drivers."

Last modified on Dec 11, 2018 at 5:13:04 PM Last modified on Dec 11, 2018, 5:13:04 PM