BM1088 IMU IIO Driver

The Linux industrial IO (IIO) is framework that is used to implement sensor drivers such as analog-to digital-converters (ADC), temperature, light, and inertial measurement unit (IMU). The BMI088 is Bosch IMU <https://www.bosch-sensortec.com/products/motion-sensors/imus/bmi088/_, which encompasses the accelerometer, the gyroscope and the temperature. This I2C-based driver implements the accelerometer and the gyroscope part of the IMU.

BMI088 Driver

Both the devices have separate I2C addresses and register spaces, so the BMI088 driver registers each accelerometer and gyroscope to the IIO framework as a separate device. This gives control to, for example the ability to enable/disable one device without disturbing the other device. Like all IIO based devices, both devices will appear in the /sys/bus/iio/devices/ for the userspace. The user can determine the device node by reading /sys/bus/iio/devices/iio:deviceX/name, which yields accelerometer and gyroscope. The driver uses the data-ready interrupts from the devices as a indication of the new data sets, and after receiving these such interrupts, the driver reads the data registers to retrieve the data. The data-ready interrupts must be connected to Jetson Always On (AON) GPIOs that have hardware timestamp capability to record the accurate time of the interrupt occurrences. This timestamp and the data will be passed to the userspace through the IIO framework. The driver supports only the data-ready interrupt mode.

Kernel Config

The driver can be enabled as loadable module by setting CONFIG_BMI088_IIO=m. Also, the kernel config for the hardware, timestamping CONFIG_TEGRA_HTS_GTE, must be set to y.

..note::

Remember the following information:

  • CONFIG_BMI088_IIO will only appear after CONFIG_TEGRA_HTS_GTE is set.

  • The driver config depends on CONFIG_I2C, CONFIG_SYSFS, CONFIG_IIO.

  • Do note select the CONFIG_NVS_BMI08X_IIO config.

After the driver has finished complining, the driver will be generated as bmi088.ko.

Device Tree

This section provides information about the required and optional properties.

Required Properties

Here is the list of required properties:

  • compatible
    • The value must be set to bmi,bmi088.

  • accel_i2c_addr
    • Must be set to an appropriate value that is based on datasheet and platform configuration.

    • The i2c address might be different based on how some pins are tied up.

  • reg
    • Must be set to the gyroscope I2C address that is based on the datasheet and platform configuration.

    • The i2c address might be different based on how some pins are tied up.

  • gyro_irq_gpio
    • The value is based on which GPIO line is connected to the gyroscope’s data-ready interrupt.

  • accel_irq_gpio
    • The value is based on the GPIO line that is connected to the accelerometer’s data-ready interrupt.

  • status
    • Needs to be set to OK to enable the DT node.

Optional Properties

Here list of optional properties:

  • accel_matrix
    • An array in the accelerometer mount matrix.

  • gyro_matrix
    • An array of gyroscope mount matrix.

  • accel_reg_0x53
    • The accelerometer INT1 config register, and the driver default value is 0xA.

    • The value 0xA makes INT1 line as the output and active high.

  • accel_reg_0x54
    • The accelerometer INT2 config register, and driver default value is 0x0.

    • By default driver uses INT1. Refer to the device datasheet for more information.

    • Select INT1 or INT2 as the data-ready interrupt.

  • gyro_reg_0x16
    • The gyroscope INT3/INT4 config register, and the driver default value is 0x1.

    • The default value makes INT3 as active high output line.

    • Refer to the device datasheet for more information.

  • gyro_reg_0x18
    • The gyroscope INT3/INT4 mapping register, and the driver default value is 0x1.

    • The default value maps INT3 the the data-ready interrupt.

    • Refer to the device datasheet for more information.

    • Select INT3 or INT4 as the data-ready interrupt.

bmi088@69 {
   compatible = "bmi,bmi088";
   accel_i2c_addr = <0x19>;
   status = "okay";
   reg = <0x69>;
   accel_irq_gpio = <&tegra_aon_gpio TEGRA_AON_GPIO(BB, 0) GPIO_ACTIVE_HIGH>;
   gyro_irq_gpio = <&tegra_aon_gpio TEGRA_AON_GPIO(BB, 1) GPIO_ACTIVE_HIGH>;
   accel_matrix = [01 00 00 00 01 00 00 00 01];
   gyro_matrix = [01 00 00 00 01 00 00 00 01];
   accel_reg_0x53 = <0x0A>;
   gyro_reg_0x16 = <0x01>;
   gyro_reg_0x18 = <0x01>;
};

Accelerometer IIO Attributes

The accelerometer IIO device files that are listed in the following table are available in /sys/bus/iio/devices/iio:deviceX/, where the X value is enumerated during IIO registration.

Note

The following table assumes that user is in the /sys/bus/iio/devices/iio:deviceX/ directory.

IIO SYSFS Interface

Default Value

Possible Values

Usage

Buffer Management

buffer/enable

0

0, 1

Writing 1 enables buffer and data acquisition, at least one axis needs to be enabled before enabling the buffer.

buffer/length

64

N/A

Internally kernel uses kmalloc to allocate the required length.
  • The maximum value depends on the state of system memory that is available to kernel at the point of the request.

buffer/watermark

1

1, buffer length

The application using poll and friends will wait till this number of samples are collected.

Debug

dev_err

Here are the values:
  • I2C Bus Errors:0

  • GTE Timestamp Errors:0

  • Sample dropped:0

N/A

Read-only, displays the current errors.
  • It records the i2c bus and hardware timestamp errors.

  • Hardware timestamp errors are recorded when the driver fails to retrieve hardware timestamp for the given datasets.
    The hardware timestamp, also known as GTE, has been dividied in the following way:
    • GTE Timestamp Errors: is a real timestamp failure, which means that the driver could not retrieve the hardware timestamp.

    • Sample dropped: The samples were dropped.

      This can happen when the data rate is higher than what i2c bus can handle.

dev_state

N/A

N/A

Read-only and displays device state, for example, suspend/shutdown.

dump_regs

N/A

N/A

Read-only and dumps all the current register values.

Common Attributes

in_accel_sampling_frequency

12.5

12.5, 25, 50, 100, 200, 400, 800, 1600

This is output data rate (ODR) in Hz.
  • The user can write any values from the list.

  • The I2C bus clock speed dictates what the user can program.

in_accel_sampling_frequency_available

12.5, 25, 50, 100, 200, 400, 800, 1600

N/A

Read-only and displays the available ODR.

in_accel_scale

0.000897

0.000897, 0.00179, 0.003591, and 0.007182

This interface represents the resolution and its value will be used to calculate actual value from the raw data.
  • Stop the user space application before you change the scale value.

in_accel_scale_available

0.000897, 0.00179, 0.003591, 0.007182

N/A

Read-only and displays the available scales.

in_accel_x_raw

N/A

N/A

Fetches the raw X-axis value.

To read, the respective scan element and device buffer must be enabled.

in_accel_y_raw

N/A

N/A

Fetches the raw Y-axis value.

To read, the respective scan element and device buffer must be enabled.

in_accel_z_raw

N/A

N/A

Fetches the raw Z-axis value.

To read, the respective scan element and device buffer must be enabled.

mount_matrix

1,0,0,0,1,0,0,0,1

N/A

Read-only, displays current mount matrix, which is by default, its identity matrix.

name

“accelerometer”

N/A

Read-only value.

part

“bmi08x accelerometer”

N/A

Read-only value displays the Bosch IMU model.

trigger/current_trigger

accelerometer-devX

N/A

The trigger comes from the device, and no other value is acceptable.
  • Here, the value for X is the same as the enumerated IIO device.

Channel Attributes

scan_elements/in_accel_x_en

0

0,1

Writing 1 enables X axis/channel, this needs to be set before you enable the buffer.

scan_elements/in_accel_x_en

0

0,1

Writing 1 enables Y axis/channel, this needs to be set before you enable the buffer.

scan_elements/in_accel_z_en

0

0,1

Writing 1 enables Z axis/channel, this needs to be set before you enable the buffer.

scan_elements/in_timestamp_en

0

0,1

Writing 1 enables timestamp channel, this needs to be set before you enable the buffer.

scan_elements/in_accel_x_index

0

N/A

Read-only and provides the channel index to the dataset.

The data set is 6 + 8 bytes, where there are two bytes for each axis, and eight bytes for the timestamp.

scan_elements/in_accel_y_index

1

N/A

Read-only and provides the channel index to the dataset.

The data set is 6 + 8 bytes, where there are two bytes for each axis, and eight bytes for the timestamp.

scan_elements/in_accel_z_index

2

N/A

Read-only and provides the channel index to the dataset.

The data set is 6 + 8 bytes, where there are two bytes for each axis, and eight bytes for the timestamp.

scan_elements/in_timestamp_index

3

N/A

Read-only and provides the channel index to the dataset.

The data set is 6 + 8 bytes, where there are two bytes for each axis, and eight bytes for the timestamp.

scan_elements/in_accel_x_type

“le:s16/16>>0”

N/A

Read-only and displays details about how the X-axis data is represented in the buffer.

This value means that the data is a little endian-signed 16 bits and does not require a shift operation.

scan_elements/in_accel_y_type

“le:s16/16>>0”

N/A

Read-only and displays details about how the Y-axis data is represented in the buffer.

This value means that the data is a little endian-signed 16 bits and does not require a shift operation.

scan_elements/in_accel_z_type

“le:s16/16>>0”

N/A

Read-only and displays details about how the Z-axis data is represented in the buffer.

This value means that the data is a little endian-signed 16 bits and does not require a shift operation.

scan_elements/in_timestamp_type

“le:s64/64>>0”

N/A

Read-only and displays details about how the timestamp data is represented in the buffer.

This value means data is a little endian-signed 64 bits and does not require a shift operation.

Gyroscope IIO

IIO SYSFS Interface

Default Value

Possible Values

Usage

Buffer Management

buffer/enable

0

0, 1

Writing 1 enables buffer and data acquisition.

buffer/length

600

N/A

Internally kernel uses kmalloc to allocate the required length.
  • The maximum value depends on the state of system memory that is available to kernel at the point of the request.

buffer/watermark

1

1, buffer length

The application that uses poll and friends will wait until this number of samples are collected.

Debug

dev_err

Here are the values:
  • I2C Bus Errors:0

  • GTE Timestamp Errors:0

  • Sample dropped:0

N/A

Read-only, displays the current errors.
  • It records the i2c bus and hardware timestamp errors.

  • Hardware timestamp errors are recorded when the driver fails to retrieve hardware timestamp for the given datasets.
    The hardware timestamp, also known as GTE, has been dividied in the following way:
    • GTE Timestamp Errors: is a real timestamp failure, which means that the driver could not retrieve the hardware timestamp.

    • Sample dropped: The samples were dropped.

      This can happen when the data rate is higher than what i2c bus can handle.

dev_state

N/A

N/A

Read-only and displays device state, for example, suspend/shutdown.

dump_regs

N/A

N/A

Read-only and dumps all the current register values.

Common Attributes

in_accel_sampling_frequency

100

100, 200, 400, 1000, 2000

This is output data rate (ODR) in Hz.
  • The user can write any values from the list.

  • The I2C bus clock speed dictates what the user can program.

in_accel_sampling_frequency_available

100, 200, 400, 1000, 2000

N/A

Read-only and displays the available ODR.

in_accel_scale

0.001065

0.001065, 0.000532, 0.000266, 0.000133, 0.000066

This interface represents the resolution and its value will be used to calculate actual value from the raw data.
  • Stop the user space application before you change the scale value.

in_accel_scale_available

0.001065, 0.000532, 0.000266, 0.000133, 0.000066

N/A

Read-only and displays the available scales.

in_accel_x_raw

N/A

N/A

Fetches the raw X-axis value.

To read, the respective scan element and device buffer must be enabled.

in_accel_y_raw

N/A

N/A

Fetches the raw Y-axis value.

To read, the respective scan element and device buffer must be enabled.

in_accel_z_raw

N/A

N/A

Fetches the raw Z-axis value.

To read, the respective scan element and device buffer must be enabled.

mount_matrix

1,0,0,0,1,0,0,0,1

N/A

Read-only, displays current mount matrix, which is by default, its identity matrix.

name

“gyroscope”

N/A

Read-only value.

part

“bmi08x gyroscope”

N/A

Read-only value displays the Bosch IMU model.

trigger/current_trigger

gyroscope-devX

N/A

The trigger comes from the device, and no other value is acceptable.
  • Here, the value for X is the same as the enumerated IIO device.

Channel Attributes

scan_elements/in_anglvel_x_en

0

0,1

Writing 1 enables the X axis/channel, and this needs to be set before you enable the buffer.

scan_elements/in_anglvel_y_en

0

0,1

Writing 1 enables the Y axis/channel, and this needs to be set before you enable the buffer.

scan_elements/in_anglvel_z_en

0

0,1

Writing 1 enables the Z axis/channel, and this needs to be set before you enable the buffer.

scan_elements/in_timestamp_en

0

0,1

Writing 1 enables the timestamp channel, and this needs to be set before you enable the buffer.

scan_elements/in_anglvel_x_index

0

N/A

Read-only and provides the channel index to the dataset.

The data set is 6 + 8 bytes, where there are two bytes for each axis, and eight bytes for the timestamp.

scan_elements/in_anglvel_y_index

1

N/A

Read-only and provides the channel index to the dataset.

The data set is 6 + 8 bytes, where there are two bytes for each axis, and eight bytes for the timestamp.

scan_elements/in_anglvel_z_index

2

N/A

Read-only and provides the channel index to the dataset.

The data set is 6 + 8 bytes, where there are two bytes for each axis, and eight bytes for the timestamp.

scan_elements/in_timestamp_index

3

N/A

Read-only and provides the channel index to the dataset.

The data set is 6 + 8 bytes, where there are two bytes for each axis, and eight bytes for the timestamp.

scan_elements/in_anglvel_x_type

“le:s16/16>>0”

N/A

Read-only and displays details about how the X-axis data is represented in the buffer.

This value means that the data is a little endian-signed 16 bits and does not require a shift operation.

scan_elements/in_anglvel_y_type

“le:s16/16>>0”

N/A

Read-only and displays details about how the Y-axis data is represented in the buffer.

This value means that the data is a little endian-signed 16 bits and does not require a shift operation.

scan_elements/in_anglvel_z_type

“le:s16/16>>0”

N/A

Read-only and displays details about how the Z-axis data is represented in the buffer.

This value means that the data is a little endian-signed 16 bits and does not require a shift operation.

scan_elements/in_timestamp_type

“le:s64/64>>0”

N/A

Read-only and displays details about how the timestamp data is represented in the buffer.

This value means data is a little endian-signed 64 bits and does not require a shift operation.

Testing the BM1088 Driver

There is a sample IIO utility available in <kernel source>/tools/iio/, where kernel source is the kernel source repository. The iio_generic_buffer.c sample application is used to demonstrate the driver. During the execution, the application enables the scan elements and buffer for the specified device as described in Hardware Timesptamping Engine (GTE). After the process is complete, the application automatically disables the scan elements and buffer.

Hardware Timesptamping Engine (GTE)

The IIO framework uses s64, which are signed 64bits to represent the timestamp information that is reflected the app iio_generic_buffer userspace in this section. However the GTE uses u64, which are unsigned 64bits. Run the following command to to update the iio_generic_buffer.c file to use signed bits as below before proceeding to the next section.

diff --git a/iio_generic_buffer.c b/iio_generic_buffer.c
index f90ea14..1cbde1e 100644
--- a/iio_generic_buffer.c
+++ b/iio_generic_buffer.c
@@ -158,7 +158,7 @@ void print8byte(uint64_t input, struct iio_channel_info *info)
printf("%05f ",
((float)val + info->offset) * info->scale);
} else {
- printf("%05f ", ((float)input + info->offset) * info->scale);
+ printf("%" PRIu64 " ", input);
}
}

Compile and Execute

Note

For the kernel version 5.10.x and later, if the timestamp channel is specified, the IIO framework enables it by default, and the above command will result in in the following error:

root@jetson:~# ./iio_generic_buffer -a -c 10 --device-name accelerometer -g -l 64
iio device number being used is 0
trigger-less mode selected
Auto-channels selected but some channels are already activated in sysfs
Proceeding without activating any channels
Failed to enable buffer: Invalid argument

To get around that, make sure to disable timestamp channel before executing iio_generic_buffer by issuing “echo 0 > /sys/bus/iio/<iio device>/scan_elements/in_timestamp_en” in the jetson device as a root.

Accelerometer Sample Output

root@tegra-ubuntu:~# ./iio_generic_buffer -a -c 10 --device-name accelerometer -g
iio device number being used is 2
trigger-less mode selected
scan element filename:/sys/bus/iio/devices/iio:device2/scan_elements/in_accel_y_en , enabled:0
scan element filename:/sys/bus/iio/devices/iio:device2/scan_elements/in_accel_x_en , enabled:0
scan element filename:/sys/bus/iio/devices/iio:device2/scan_elements/in_timestamp_en , enabled:0
scan element filename:/sys/bus/iio/devices/iio:device2/scan_elements/in_accel_z_en , enabled:0
No channels are enabled, enabling all channels
Enabling: in_accel_y_en
Enabling: in_accel_x_en
Enabling: in_timestamp_en
Enabling: in_accel_z_en
scan element filename:/sys/bus/iio/devices/iio:device2/scan_elements/in_accel_y_en , enabled:1
scan element filename:/sys/bus/iio/devices/iio:device2/scan_elements/in_accel_x_en , enabled:1
scan element filename:/sys/bus/iio/devices/iio:device2/scan_elements/in_timestamp_en , enabled:1
scan element filename:/sys/bus/iio/devices/iio:device2/scan_elements/in_accel_z_en , enabled:1
buffer directory: /sys/bus/iio/devices/iio:device2/buffer
X Axis   Y Axis    Z Axis   Timestamp [This row is not present in the output]
-9.484633 -0.103250 1.109713 4515182411776
-9.560051 -0.098761 1.115998 4515261579264
-9.547482 -0.096965 1.116896 4515340746752
-9.543890 -0.092476 1.117793 4515419914240
-9.547482 -0.096067 1.112406 4515499606016
-9.542993 -0.096965 1.112406 4515578773504
-9.550175 -0.107739 1.112406 4515657940992
-9.548379 -0.105046 1.115100 4515737108480
-9.540298 -0.101454 1.109713 4515816275968
-9.545686 -0.095170 1.116896 4515895443456
Disabling: in_accel_y_en
Disabling: in_accel_x_en
Disabling: in_timestamp_en
Disabling: in_accel_z_en

Gyroscope Sample Output

root@tegra-ubuntu:~# ./iio_generic_buffer -a -c 10 --device-name gyroscope -g
iio device number being used is 3
trigger-less mode selected
scan element filename:/sys/bus/iio/devices/iio:device3/scan_elements/in_anglvel_z_en , enabled:0
scan element filename:/sys/bus/iio/devices/iio:device3/scan_elements/in_timestamp_en , enabled:0
scan element filename:/sys/bus/iio/devices/iio:device3/scan_elements/in_anglvel_y_en , enabled:0
scan element filename:/sys/bus/iio/devices/iio:device3/scan_elements/in_anglvel_x_en , enabled:0
No channels are enabled, enabling all channels
Enabling: in_anglvel_z_en
Enabling: in_timestamp_en
Enabling: in_anglvel_y_en
Enabling: in_anglvel_x_en
scan element filename:/sys/bus/iio/devices/iio:device3/scan_elements/in_anglvel_z_en , enabled:1
scan element filename:/sys/bus/iio/devices/iio:device3/scan_elements/in_timestamp_en , enabled:1
scan element filename:/sys/bus/iio/devices/iio:device3/scan_elements/in_anglvel_y_en , enabled:1
scan element filename:/sys/bus/iio/devices/iio:device3/scan_elements/in_anglvel_x_en , enabled:1
buffer directory: /sys/bus/iio/devices/iio:device3/buffer
X Axis   Y Axis    Z Axis   Timestamp [This row is not present in the output]
0.000000 0.000000 -0.001064 4629188837376
0.000000 0.000000 -0.002128 4629198798848
0.001064 0.000000 -0.002128 4629208760320
0.002128 0.000000 -0.002128 4629218721792
0.002128 0.000000 -0.001064 4629228683264
0.002128 0.000000 -0.001064 4629238644736
0.002128 0.000000 -0.001064 4629248606208
0.001064 0.000000 -0.001064 4629258567680
0.001064 0.000000 -0.001064 4629268529152
0.002128 -0.001064 -0.001064 4629278490624
Disabling: in_anglvel_z_en
Disabling: in_timestamp_en
Disabling: in_anglvel_y_en
Disabling: in_anglvel_x_en