BMI088 IMU Driver
The Linux industrial IO (IIO) is framework used to implement sensor drivers such as ADC (analog to digital converters), temperature, light, IMU (inertial measurement unit). The BMI088 is Bosch IMU which encompasses accelerometer, gyroscope and temperature. This I2C based driver implements accelerometer and gyroscope part of the IMU.
BMI088 Driver
The BMI088 driver is enabled by default in the kernel config. It registers the accelerometer and gyroscope with the IIO framework as separate devices, since both sensors have separate I2C addresses and register spaces. This separation allows for individual control of each device, enabling or disabling one without affecting the other. Like all IIO-based devices, the accelerometer and gyroscope will appear at /sys/bus/iio/devices/
for the userspace. The user can determine the device node by reading /sys/bus/iio/devices/iio:deviceX/name
, which will yield accelerometer
and gyroscope
.
The driver uses data-ready interrupts from both devices as an indication of the new data sets. Upon receiving such an interrupt, the driver reads the data registers to retrieve the data. The data-ready interrupts must be connected to the Jetson’s Always On (AON) GPIOs, which are capable of hardware timestamping to record the accurate time of the interrupt occurrences. The timestamp and the data are then passed to userspace through the IIO framework. The driver supports only the data-ready interrupt mode.
Device Tree
This section provides information about the device tree.
Required Properties
Here is the list of the required properties:
compatible
: Must be set tobmi,bmi088
.accel_i2c_addr
: Must be set to the appropriate value based on the datasheet and platform configuration because the I2C address might be different based on how some pins are tied up.reg
: Must be set to the gyroscope I2C address based on the datasheet and platform configuration because the I2C address might be different based on how some pins are tied up.gyro_irq-gpios
: The value is based on which GPIO line is connected to the gyroscope’s data-ready interrupt.accel_irq-gpios
: The value is based on the GPIO line that is connected to the accelerometer’s data-ready interrupt.status
: To enable the DT node, set tookay
.timestamps
: List of GPIO lines for HTE timestamptimestamp-names
: Names for each sensor timestamp
Optional Properties
Here is the list of the 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.
Here is an example:
bmi088@69 { compatible = "bmi,bmi088"; accel_i2c_addr = <0x19>; status = "okay"; reg = <0x69>; accel_irq-gpios = <&gpio_aon TEGRA234_AON_GPIO(BB, 0) GPIO_ACTIVE_HIGH>; gyro_irq-gpios = <&gpio_aon TEGRA234_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>; timestamps = <&hte_aon TEGRA234_AON_GPIO(BB, 0)>, <&hte_aon TEGRA234_AON_GPIO(BB, 1)>; timestamp-names = "accelerometer", "gyroscope"; };
Accelerometer IIO Attributes
The accelerometer IIO device files mentioned in the following table is available in the /sys/bus/iio/devices/iio:deviceX/
directory, 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 value |
Usage |
---|---|---|---|
Buffer Management |
|||
buffer/enable |
0 |
0,1 |
|
buffer/length |
64 |
N/A |
|
buffer/watermark |
1 |
1, buffer length |
The application using poll and friends will wait until this number of samples is collected. |
Debug |
|||
dev_err |
|
N/A |
|
dev_state |
N/A |
N/A |
Read-only and displays the device state, for example, suspend/shutdown. |
|
N/A |
N/A |
Read-only and dumps the current register values. |
Common attributes |
|||
in_accel_sampling_frequency |
12.5 |
12.5, 25, 50, 100, 200, 400, 800, 1600 |
|
in_accel_sampling_frequency_available |
12.5, 25, 50, 100, 200, 400, 800, 1600 |
NA |
Read-only and displays the available ODRs. |
in_accel_scale |
0.000897 |
0.000897, 0.00179, 0.003591, 0.007182 |
|
in_accel_scale_available |
0.000897, 0.00179, 0.003591, 0.007182 |
N/A |
Read-only and displays 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 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 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 |
|
name |
“accelerometer” |
NA |
A read-only value. |
part |
“bmi08x accelerometer” |
N/A |
A read-only value that displays the Bosch IMU model. |
trigger/current_trigger |
accelerometer-devX |
N/A |
|
Channel Attributes |
|||
scan_elements/in_accel_x_en |
0 |
0,1 |
Writing 1 enables the X-axis/channel, and this setting needs to be made before you enable the buffer. |
scan_elements/in_accel_y_en |
0 |
0,1 |
Writing 1 enables Y-axis/channel, and this setting needs to be made before you enable the buffer. |
scan_elements/in_accel_z_en |
0 |
0,1 |
Writing 1 enables Z-axis/channel, and this setting needs to be made before you enable the buffer. |
scan_elements/in_timestamp_en |
0 |
0,1 |
Writing 1 enables the timestamp channel, and this setting needs to be made before you enable the buffer. |
scan_elements/in_accel_x_index |
0 |
NA |
|
scan_elements/in_accel_x_index |
0 |
NA |
|
scan_elements/in_accel_y_index |
1 |
NA |
|
scan_elements/in_accel_z_index |
2 |
N/A |
|
scan_elements/in_timestamp_index |
3 |
NA |
|
scan_elements/in_accel_x_type |
“le:s16/16>>0” |
N/A |
|
scan_elements/in_accel_y_type |
“le:s16/16>>0” |
N/A |
|
scan_elements/in_accel_z_type |
“le:s16/16>>0” |
N/A |
|
scan_elements/in_timestamp_type |
“le:s64/64>>0” |
N/A |
|
Gyroscope IIO Attributes
The gyroscope IIO device files in the following table is available in the /sys/bus/iio/devices/iio:deviceX/
directory, 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 value |
Usage |
---|---|---|---|
Buffer Management |
|||
buffer/enable |
0 |
0,1 |
Writing 1 enables buffer and data acquisition. |
buffer/length |
600 |
N/A |
|
buffer/watermark |
1 |
1, buffer length |
The application using poll and friends will wait until this number of samples is collected. |
Debug |
|||
dev_err |
|
N/A |
|
dev_state |
N/A |
N/A |
Read-only and displays the device state, for example, suspend/shutdown. |
dump_regs |
N/A |
N/A |
Read-only and dumps the current register values. |
Common attributes |
|||
in_anglvel_sampling_frequency |
100 |
100, 200, 400, 1000, 2000 |
|
in_anglvel_sampling_frequency_available |
100, 200, 400, 1000, 2000 |
NA |
Read-only and displays the available ODRs. |
in_anglvel_scale |
0.001065 |
0.001065, 0.000532, 0.000266, 0.000133, 0.000066 |
|
in_anglvel_scale_available |
0.000532, 0.000266, 0.000133, 0.000066 |
N/A |
Read-only and displays available scales. |
in_anglvel_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_anglvel_y_raw |
N/A |
N/A |
Fetches raw Y-axis value. To read, the respective scan element and device buffer must be enabled. |
in_anglvel_z_raw |
N/A |
N/A |
Fetches 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 |
|
name |
“gyroscope” |
NA |
A read-only value. |
part |
“bmi08x gyroscope” |
N/A |
A read-only value that displays the Bosch IMU model. |
trigger/current_trigger |
gyroscope-devX |
N/A |
|
Channel Attributes |
|||
scan_elements/in_anglvel_x_en |
0 |
0,1 |
Writing 1 enables the X-axis/channel, and this setting needs to be made before you enable the buffer. |
scan_elements/in_anglvel_y_en |
0 |
0,1 |
Writing 1 enables Y-axis/channel, and this setting needs to be made before you enable the buffer. |
scan_elements/in_anglvel_z_en |
0 |
0,1 |
Writing 1 enables Z-axis/channel, and this setting needs to be made before you enable the buffer. |
scan_elements/in_timestamp_en |
0 |
0,1 |
Writing 1 enables the timestamp channel, and this setting needs to be made before you enable the buffer. |
scan_elements/in_anglvel_x_index |
0 |
NA |
|
scan_elements/in_anglvel_y_index |
0 |
NA |
|
scan_elements/in_anglvel_z_index |
1 |
NA |
|
scan_elements/in_timestamp_index |
2 |
N/A |
|
scan_elements/in_anglvel_x_type |
“le:s16/16>>0” |
N/A |
|
scan_elements/in_anglvel_y_type |
“le:s16/16>>0” |
N/A |
|
scan_elements/in_anglvel_z_type |
“le:s16/16>>0” |
N/A |
|
scan_elements/in_timestamp_type |
“le:s64/64>>0” |
N/A |
|
Testing BMI088 Driver
In the <kernel source>/tools/iio/
directory, there is a sample IIO utility where kernel source
is the kernel source repository. The iio_generic_buffer.c
sample application is used to demonstrate the driver. During the execution, application enables the scan elements and buffer for the specified device as described in the following procedure. After after the testing is complete, the application automatically disables the scan elements and buffer.
Hardware Timestampping Engine (HTE)
The IIO framework uses signed 64-bits, also known as s64, to represent the timestamp information that gets reflected in the app iio_generic_buffer
userspace app in this section. However, the HTE uses unsigned 64bits, also known as u64.
Note
To ensure that HTE uses signed bits, run the following code sample to update the iio_generic_buffer.c file
before you complete the procedure in Complile and Execute procedure:
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
Copy the
iio_generic_buffer.c
,iio_utils.c
,iio_utils.h
, andbmi088.ko
files to DUT, for example, at/home/ubuntu/
.To install gcc on DUT, run the following command.
$ sudo apt install -y gcc
To compile the
iio_generic_buffer
, run the following command.gcc -I /home/ubuntu/ iio_utils.c iio_generic_buffer.c -o iio_generic_buffer
Note
This command assumes that the user is in the
/home/ubuntu
directory and has copied the files to the same location.You can complete this step from the host machine by doing a cross-compile.
Set the appropriate toolchain and cross-compile variables.
The following commands assume that the user is in the
<kernel source>/tools/iio/
directory in the host machine.Export
CROSS_COMPILE=<>
, for example,export CROSS_COMPILE=aarch64-linux-gnu-
.Export
PATH=$PATH:<path
tocross-compile toolchain>
.Export
ARCH=arm64
.
The
make iio_generic_buffer will generate the ``iio_generic_buffer
binary in the same directory.Copy the binary file to DUT.
To test accelerometer, complete the following steps:
Note
The following commands are executed as a root.
Execute
./iio_generic_buffer -a -c 10 --device-name accelerometer -g -l 2048
.If you execute
./iio_generic_buffer
without any options, a help message will display.The command in this step will fetch 10 samples in event mode.
To test gyroscope, complete the following steps:
Note
The following commands are executed as a root.
Execute
./iio_generic_buffer -a -c 10 --device-name gyroscope -g -l 2048
.
If you execute
./iio_generic_buffer
without any options, a help message will display.The command in this step will fetch 10 samples in event mode.
Note
For kernel 5.10.x and later, if the timestamp channel is specified, the IIO framework enables it by default. As a result, when you run the command above, the following error will occur:
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 disable the timestamp channel, before you run
iio_generic_buffer
in the Jetson device, runecho 0 > /sys/bus/iio/<iio device>/scan_elements/in_timestamp_en
as a root user.
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