VOXL I2C
Table of contents
Overview
All I2C ports that are broken out on VOXL’s headers are internally mapped to the Sensors DSP (SDSP). This also means that you cannot use I2C ports via /dev/i2c* as other embedded Linux systems may allow. We provide a simple library, libvoxl-io to enable communication with I2C functionality from the applications processor (Linux userspace). This layer hides the SDSP RPC calls and allows compiling programs that use I2C without the need of Hexagon DSP toolchain or build environment.
The libvoxl-io library header and API description can be found here: https://gitlab.com/voxl-public/libvoxl_io/blob/master/lib/include/voxl_io.h
The library is included with the VOXL Software Bundle.
I2C Port Numbers
I2C port numbers correspond directly with the BLSP numbers. Please see datasheet page for more details.
- J1 : I2C8 (5V levels)
- J7 : I2C6
- J10 : I2C7
- N/A : I2C3 is used to connect to on-board pressure sensor BMP-280
- there are additional I2C ports, used for communication with cameras, and are not available to VOXL users.
- J11 : I2C12 (WARNING I2C12 is not functioning. It is disabled in
libvoxl_io
)
Examples and Tools
voxl-i2c
This tool allows you to scan, read or write data from/to devices on I2C port from linux command line.
https://gitlab.com/voxl-public/libvoxl_io/blob/master/lib/apps/voxl-i2c.c
~ # voxl-i2c
Description:
Command line tool for using i2c functionality via SDSP
Usage:
voxl-i2c scan <i2c_bus> <bit_rate> [register_address=0]
Scan all i2c addresses (0-126)
Print the value of specified register for detected devices
voxl-i2c read <i2c_bus> <bit_rate> <i2c_address> <start_register> <read_size>
Read data from i2c slave starting from start_register and print their values
voxl-i2c write <i2c_bus> <bit_rate> <i2c_address> <start_register> <data>
Write data to i2c slave starting from start_register
Data should be provided as space-delimited array of uint8's
Usage Examples:
Read example (read some calibration data from on-board pressure sensor BMP-280 )
~ # voxl-i2c read 3 400000 118 0x88 10
7 110 144 104 24 252 222 148 40 214
Read and write example in a bash script (set up MPU6050 IMU and read raw data (assume sensor connected externally to I2C6))
set -e
#set mpu6050 to run mode
voxl-i2c write 6 400000 0x68 107 0
sleep 0.1
#set up sampling rates, gyro and accel ranges
voxl-i2c write 6 400000 0x68 26 0 0x18 0x18
#read 14 bytes (3 gyro, 3 accel, 1 temperature values.. 2 bytes each)
while :
do
voxl-i2c read 6 400000 0x68 59 14
done
The output should be something like this..
0 25 1 101 8 51 243 16 255 188 0 2 0 2
0 21 1 83 8 55 243 32 255 218 255 242 0 1
0 19 1 84 8 38 243 48 255 191 0 2 0 4
...
...
16-bit and 32-bit Register Access
Accessing 16-bit (and 32-bit) registers is supported by libvoxl_io
. However, please note that the register address is sent Least Significant Byte (LSB) first. So, if you are accessing a 16-bit register and the i2c device is expecting MSB first, then you need to byte swap order of byte0 and byte1 in the 4-byte register address before providing it to the i2c read/write calls. In case of 32-bit registers, the order of all 4 bytes needs to be reversed if i2c device expects MSB first.
Performance
- Initializing I2C port (
voxl_i2c_init
) can take around 15-20 ms (iflibvoxl_io
is already loaded in SDSP) or up to 100+ms (iflibvoxl_io
is not loaded on SDSP). - Once I2C port is open, reading / writing (
voxl_i2c_read
andvoxl_i2c_write
) should take 1-2ms (assuminglibvoxl_io
is already loaded in SDSP). However, sincevoxl-i2c
tool opens and closes the port every time, the minimum call time forvoxl-i2c
read or write is 20ms and can be higher depending on CPU load. - Actual I2C read and write calls on SDSP are much quicker (about 250us to execute one-byte read or write transaction), but CPU<->SDSP communication introduces additional delay, resulting in 1-2ms as seen on the CPU side.
- “Loaded on SDSP” means there is another process currently using
libvoxl_io
on SDSP. SDSP will clean up and unload any library which is not used. - For example, calling
voxl-i2c
multiple times (one after another) will result in loading and unloadinglibvoxl_io
each time, unless another process is continuously usinglibvoxl_io
.
Warnings and Limitations
- An I2C port should not be open concurrently by several processes, otherwise undesired behavior may occur (such as one process closing the port while another is still using it - would result in second process unable to continue using the process).
- Concurrent usage of the same port by multiple processes is not prohibited by
libvoxl_io
, but has to be handled carefully, especially opening and closing the port. TODO: need to check what happens if you read / write at the same time from different threads / processes.