ardupilot/libraries/AP_HAL_Linux/I2CDriver.h
Lucas De Marchi a4c1b0d75f AP_HAL_Linux: add constructor to find I2C bus reliably
The device number in /dev may not be reliable from one boot to another
due to the initialization order of each bus.

For example, in Minnow Board Max, the exposed I2C buses may be i2c-7 and
i2c-8 or i2c-8 and i2c-9 depending if the platform driver in the kernel
is initialized before or after the PCI.

It also may change with different version and configuration of the DT or
UEFI used making another kernel driver to bind to the device. This means that
for Minnow Board Max we need to use something like below to pass to the
constructor:

	static const char * const i2c_devpaths[] = {
	    /* UEFI with lpss set to ACPI */
	    "/devices/platform/80860F41:05",
	    /* UEFI with lpss set to PCI */
	    "/devices/pci0000:00/0000:00:18.6",
	     NULL
	};

The devpath here is the one returned by udev with the following command:

	udevadm info -q path /dev/<i2c-device>

In contrary to the device number in /dev/i2c-N, this path in sysfs is
stable across reboots and can only change if there's a change in the
UEFI firmware or the board's device tree.

This patch assumes the currently supported boards don't have this
problem so it's not touching them.
2015-06-30 09:10:54 +10:00

55 lines
1.9 KiB
C++

#ifndef __AP_HAL_LINUX_I2CDRIVER_H__
#define __AP_HAL_LINUX_I2CDRIVER_H__
#include <AP_HAL_Linux.h>
class Linux::LinuxI2CDriver : public AP_HAL::I2CDriver {
public:
LinuxI2CDriver(AP_HAL::Semaphore* semaphore, const char *device);
LinuxI2CDriver(AP_HAL::Semaphore* semaphore, const char * const devpaths[]);
~LinuxI2CDriver();
void begin();
void end();
void setTimeout(uint16_t ms);
void setHighSpeed(bool active);
/* write: for i2c devices which do not obey register conventions */
uint8_t write(uint8_t addr, uint8_t len, uint8_t* data);
/* writeRegister: write a single 8-bit value to a register */
uint8_t writeRegister(uint8_t addr, uint8_t reg, uint8_t val);
/* writeRegisters: write bytes to contigious registers */
uint8_t writeRegisters(uint8_t addr, uint8_t reg,
uint8_t len, uint8_t* data);
/* read: for i2c devices which do not obey register conventions */
uint8_t read(uint8_t addr, uint8_t len, uint8_t* data);
/* readRegister: read from a device register - writes the register,
* then reads back an 8-bit value. */
uint8_t readRegister(uint8_t addr, uint8_t reg, uint8_t* data);
/* readRegister: read contigious device registers - writes the first
* register, then reads back multiple bytes */
uint8_t readRegisters(uint8_t addr, uint8_t reg,
uint8_t len, uint8_t* data);
uint8_t readRegistersMultiple(uint8_t addr, uint8_t reg,
uint8_t len, uint8_t count,
uint8_t* data);
uint8_t lockup_count();
AP_HAL::Semaphore* get_semaphore() { return _semaphore; }
private:
bool set_address(uint8_t addr);
AP_HAL::Semaphore* _semaphore;
char *_device = NULL;
int _fd = -1;
uint8_t _addr;
};
#endif // __AP_HAL_LINUX_I2CDRIVER_H__