Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move to per i2c bus mutex in Qurt i2c driver #23531

Merged
merged 1 commit into from
Feb 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 33 additions & 7 deletions src/lib/drivers/device/qurt/I2C.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,16 @@ I2C::_config_i2c_bus_func_t I2C::_config_i2c_bus = NULL;
I2C::_set_i2c_address_func_t I2C::_set_i2c_address = NULL;
I2C::_i2c_transfer_func_t I2C::_i2c_transfer = NULL;

pthread_mutex_t I2C::_mutex = PTHREAD_MUTEX_INITIALIZER;
// There is a mutex per I2C bus. A mutex isn't required with normal
// use since per bus I2C accesses are made via work item tied to a per bus thread.
// But it is here anyways in case someone decides to use the bus in some different
// custom code that has a separate thread.
struct I2C::_bus_mutex_t I2C::_bus_mutex[I2C::MAX_I2C_BUS] = {
{1, PTHREAD_MUTEX_INITIALIZER},
{2, PTHREAD_MUTEX_INITIALIZER},
{4, PTHREAD_MUTEX_INITIALIZER},
{5, PTHREAD_MUTEX_INITIALIZER}
};

I2C::I2C(uint8_t device_type, const char *name, const int bus, const uint16_t address, const uint32_t frequency) :
CDev(name, nullptr),
Expand Down Expand Up @@ -91,10 +100,27 @@ I2C::init()
goto out;
}

pthread_mutex_lock(&_mutex);
if (_mutex == nullptr) {
for (int i = 0; i < MAX_I2C_BUS; i++) {
if (get_device_bus() == _bus_mutex[i]._bus) {
_mutex = &_bus_mutex[i]._mutex;
break;
}
}

if (_mutex == nullptr) {
PX4_ERR("NULL i2c bus mutex");
goto out;

} else {
PX4_INFO("Set up I2C bus mutex for bus %d", get_device_bus());
}
}

pthread_mutex_lock(_mutex);
// Open the actual I2C device
_i2c_fd = _config_i2c_bus(get_device_bus(), get_device_address(), _frequency);
pthread_mutex_unlock(&_mutex);
pthread_mutex_unlock(_mutex);

if (_i2c_fd == PX4_ERROR) {
PX4_ERR("i2c init failed");
Expand Down Expand Up @@ -131,9 +157,9 @@ I2C::set_device_address(int address)
if ((_i2c_fd != PX4_ERROR) && (_set_i2c_address != NULL)) {
PX4_INFO("Set i2c address 0x%x, fd %d", address, _i2c_fd);

pthread_mutex_lock(&_mutex);
pthread_mutex_lock(_mutex);
_set_i2c_address(_i2c_fd, address);
pthread_mutex_unlock(&_mutex);
pthread_mutex_unlock(_mutex);

Device::set_device_address(address);
}
Expand All @@ -150,9 +176,9 @@ I2C::transfer(const uint8_t *send, const unsigned send_len, uint8_t *recv, const
do {
// PX4_INFO("transfer out %p/%u in %p/%u", send, send_len, recv, recv_len);

pthread_mutex_lock(&_mutex);
pthread_mutex_lock(_mutex);
ret = _i2c_transfer(_i2c_fd, send, send_len, recv, recv_len);
pthread_mutex_unlock(&_mutex);
pthread_mutex_unlock(_mutex);

if (ret != PX4_ERROR) { break; }

Expand Down
10 changes: 9 additions & 1 deletion src/lib/drivers/device/qurt/I2C.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,18 @@ class __EXPORT I2C : public CDev
private:
uint32_t _frequency{0};
int _i2c_fd{-1};
pthread_mutex_t *_mutex{nullptr};

static const int MAX_I2C_BUS{4};

static _config_i2c_bus_func_t _config_i2c_bus;
static _set_i2c_address_func_t _set_i2c_address;
static _i2c_transfer_func_t _i2c_transfer;
static pthread_mutex_t _mutex;

static struct _bus_mutex_t {
int _bus;
pthread_mutex_t _mutex{PTHREAD_MUTEX_INITIALIZER};
} _bus_mutex[MAX_I2C_BUS];
};

} // namespace device
Expand Down
Loading