.. _SD.Kernel.Bmi088ImuIioDriver: .. include:: /content/swdocs.rsts .. spelling:: accelerometer gyroscope bmi accel addr datasheet irq gpio GPIO Accelerometer xA kmalloc dev regs devX le DT DUT IMU BMI088 IIO iio deviceX I2C AON datasets dataset anglvel Timestampping gcc 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. Kernel Configuration @@@@@@@@@@@@@@@@@@@@ The driver can be enabled as loadable module by setting ``CONFIG_BMI088_IIO=m``. In addition, 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. BM1088 Driver @@@@@@@@@@@@@ Since both the devices have separate I2C addresses and register spaces, the BMI088 driver registers each accelerometer and gyroscope to IIO framework as separate devices. This gives control to, for example, enable or disable each device without disturbing another device. Like all IIO-based devices, both the devices 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``, this will yield ``accelerometer`` and ``gyroscope``. The driver uses data ready interrupts from both the devices as a indication of the new data sets, upon receiving such interrupt driver reads data registers to retrieve the data. The data-ready interrupts must be connected to Jetson Always On (AON) GPIOs, which have hardware timestamp capability to record the accurate time of the interrupt occurrences. This timestamp the data will be passed to userspace through IIO framework. The driver supports only 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 to ``bmi,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_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``: To enable the DT node, set to ``okay``. 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: .. code-block:: none 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 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. .. list-table:: :widths: auto :header-rows: 1 * - IIO sysfs Interface - Default value - Possible value - Usage * - **Buffer Management** - - - * - buffer/enable - 0 - 0,1 - Writing 1 enables buffer and data acquisition. - Before you enable the buffer, at least one axis needs to be enabled. * - buffer/length - 64 - N/A - Internally, the kernel uses ``kmalloc`` to allocate the required lengths. - The max value depends on the state of the system memory. * - buffer/watermark - 1 - 1, buffer length - The application using poll and friends will wait until this number of samples is 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 i2c bus and hardware timestamp errors. The timestamp errors are recorded when the driver fails to retrieve the hardware timestamp for the specified datasets. The hardware timestamp, also known as GTE, has been divided as follows: - GTE Timestamp Errors: a real timestamp failure, which means that the driver was not able to retrieve the hardware timestamp. - Sample dropped: the were samples 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 the device state, for example, suspend/shutdown. * - ``dump_regs`` - 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 - This is the output data rate (ODR) in Hz, and 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 - NA - Read-only and displays the available ODRs. * - in_accel_scale - 0.000897 - 0.000897, 0.00179, 0.003591, 0.007182 - This interface represents the resolution, and its value will be used to calculate the 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 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 - Read-only, displays current mount matrix, by default its identity matrix. Refer to `https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/iio/mount-matrix.txt `_ for more information. * - 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 - The trigger comes from the device, and no other value is acceptable. Here ``X`` is number that is the same as the enumerated IIO device. * - **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 - Read-only and puts the channel index to the data set. 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_index - 0 - NA - Read-only and puts the channel index to the data set. 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 - NA - Read-only and puts the channel index to the data set. 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 data set. 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 - NA - Read-only, gives channel index into 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 X-axis data is represented in the buffer. This value means that the data is 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 Y-axis data is represented in the buffer. This value means data is little endian signed 16 bits and does not require shift operation. * - scan_elements/in_accel_z_type - "le:s16/16>>0" - N/A - Read-only and displays details about how Z-axis data is represented in the buffer. This value means data is little endian signed 16 bits and does not require shift operation. * - scan_elements/in_timestamp_type - "le:s64/64>>0" - N/A - Read-only and displays details about how timestamp data is represented in the buffer. This value means data is little endian signed 64 bits and does not require shift operation. 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. .. list-table:: :widths: auto :header-rows: 1 * - 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 - Internally, the kernel uses ``kmalloc`` to allocate the required lengths. - The max value depends on the state of the system memory that is available to the kernel at the point of request. * - buffer/watermark - 1 - 1, buffer length - The application using poll and friends will wait until this number of samples is 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 i2c bus and hardware timestamp errors. The timestamp errors are recorded when the driver fails to retrieve the hardware timestamp for the specified datasets. The hardware timestamp, also known as GTE, has been divided as follows: - GTE Timestamp Errors: a real timestamp failure, which means that the driver was not able to 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 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 - This is the output data rate (ODR) in Hz, and the user can write any values from the list. The I2C bus clock speed dictates what the user can program. * - 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 - This interface represents the resolution, and its value will be used to calculate the actual value from the raw data. Stop the user space application **before** you change the scale value. * - 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 - Read-only, displays current mount matrix, by default its identity matrix. Refer to `https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/iio/mount-matrix.txt `_ for more information. * - 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 - The trigger comes from the device, and no other value is acceptable. Here ``X`` is number that 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 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 - Read-only and puts the channel index to the data set. 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 - 0 - NA - Read-only and puts the channel index to the data set. 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 - 1 - NA - Read-only and puts the channel index to the data set. 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 - 2 - N/A - Read-only and provides the channel index to the data set. 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 X-axis data is represented in the buffer. This value means that the data is 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 Y-axis data is represented in the buffer. This value means data is little endian signed 16 bits and does not require shift operation. * - scan_elements/in_anglvel_z_type - "le:s16/16>>0" - N/A - Read-only and displays details about how Z-axis data is represented in the buffer. This value means data is little endian signed 16 bits and does not require shift operation. * - scan_elements/in_timestamp_type - "le:s64/64>>0" - N/A - Read-only and displays details about how timestamp data is represented in the buffer. This value means data is little endian signed 64 bits and does not require shift operation. Testing BMI088 Driver @@@@@@@@@@@@@@@@@@@@@ In the ``/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 (GTE) @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ The IIO framework uses s64, for example signed 64-bits, to represent the timestamp information that gets reflected in the ``app iio_generic_buffer`` userspace app in this section. However, the GTE uses u64, for example, unsigned 64bits. .. note:: To ensure that GTE 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: .. code-block:: none 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``, and ``bmi088.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 ``/tools/iio/`` directory in the host machine. #. Export ``CROSS_COMPILE=<>``, for example, ``export CROSS_COMPILE=aarch64-linux-gnu-``. #. Export ``PATH=$PATH:``. #. 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. #. Insert ``bmi088.ko`` as the root for ``insmod bmi088.ko``. #. 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. - 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: .. code-block:: none 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, run ``echo 0 > /sys/bus/iio//scan_elements/in_timestamp_en`` as a root user. Accelerometer Sample Output @@@@@@@@@@@@@@@@@@@@@@@@@@@ .. code-block:: none 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 @@@@@@@@@@@@@@@@@@@@@@@ .. code-block:: none 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