mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-28 02:11:43 +00:00
HAL: implement I2C and SPI directly instead of using i2clib and spilib.
This reduces library dependencies, improves error handling, and makes future enhancements easier.
This commit is contained in:
@@ -7,7 +7,13 @@
|
||||
|
||||
#include "HAL/I2C.h"
|
||||
|
||||
#include <i2clib/i2c-lib.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "DigitalInternal.h"
|
||||
#include "HAL/DIO.h"
|
||||
@@ -20,8 +26,8 @@ static wpi::mutex digitalI2CMXPMutex;
|
||||
|
||||
static uint8_t i2COnboardObjCount = 0;
|
||||
static uint8_t i2CMXPObjCount = 0;
|
||||
static uint8_t i2COnBoardHandle = 0;
|
||||
static uint8_t i2CMXPHandle = 0;
|
||||
static int i2COnBoardHandle = -1;
|
||||
static int i2CMXPHandle = -1;
|
||||
|
||||
static HAL_DigitalHandle i2CMXPDigitalHandle1 = HAL_kInvalidHandle;
|
||||
static HAL_DigitalHandle i2CMXPDigitalHandle2 = HAL_kInvalidHandle;
|
||||
@@ -42,30 +48,37 @@ void HAL_InitializeI2C(HAL_I2CPort port, int32_t* status) {
|
||||
return;
|
||||
}
|
||||
|
||||
wpi::mutex& lock = port == 0 ? digitalI2COnBoardMutex : digitalI2CMXPMutex;
|
||||
{
|
||||
std::lock_guard<wpi::mutex> sync(lock);
|
||||
if (port == 0) {
|
||||
i2COnboardObjCount++;
|
||||
if (i2COnBoardHandle > 0) return;
|
||||
i2COnBoardHandle = i2clib_open("/dev/i2c-2");
|
||||
} else if (port == 1) {
|
||||
i2CMXPObjCount++;
|
||||
if (i2CMXPHandle > 0) return;
|
||||
if ((i2CMXPDigitalHandle1 = HAL_InitializeDIOPort(
|
||||
HAL_GetPort(24), false, status)) == HAL_kInvalidHandle) {
|
||||
return;
|
||||
}
|
||||
if ((i2CMXPDigitalHandle2 = HAL_InitializeDIOPort(
|
||||
HAL_GetPort(25), false, status)) == HAL_kInvalidHandle) {
|
||||
HAL_FreeDIOPort(i2CMXPDigitalHandle1); // free the first port allocated
|
||||
return;
|
||||
}
|
||||
digitalSystem->writeEnableMXPSpecialFunction(
|
||||
digitalSystem->readEnableMXPSpecialFunction(status) | 0xC000, status);
|
||||
i2CMXPHandle = i2clib_open("/dev/i2c-1");
|
||||
if (port == 0) {
|
||||
std::lock_guard<wpi::mutex> sync(digitalI2COnBoardMutex);
|
||||
i2COnboardObjCount++;
|
||||
if (i2COnboardObjCount > 1) return;
|
||||
int handle = open("/dev/i2c-2", O_RDWR);
|
||||
if (handle < 0) {
|
||||
std::printf("Failed to open onboard i2c bus: %s\n", std::strerror(errno));
|
||||
return;
|
||||
}
|
||||
return;
|
||||
i2COnBoardHandle = handle;
|
||||
} else {
|
||||
std::lock_guard<wpi::mutex> sync(digitalI2CMXPMutex);
|
||||
i2CMXPObjCount++;
|
||||
if (i2CMXPObjCount > 1) return;
|
||||
if ((i2CMXPDigitalHandle1 = HAL_InitializeDIOPort(
|
||||
HAL_GetPort(24), false, status)) == HAL_kInvalidHandle) {
|
||||
return;
|
||||
}
|
||||
if ((i2CMXPDigitalHandle2 = HAL_InitializeDIOPort(
|
||||
HAL_GetPort(25), false, status)) == HAL_kInvalidHandle) {
|
||||
HAL_FreeDIOPort(i2CMXPDigitalHandle1); // free the first port allocated
|
||||
return;
|
||||
}
|
||||
digitalSystem->writeEnableMXPSpecialFunction(
|
||||
digitalSystem->readEnableMXPSpecialFunction(status) | 0xC000, status);
|
||||
int handle = open("/dev/i2c-1", O_RDWR);
|
||||
if (handle < 0) {
|
||||
std::printf("Failed to open MXP i2c bus: %s\n", std::strerror(errno));
|
||||
return;
|
||||
}
|
||||
i2CMXPHandle = handle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,15 +102,26 @@ int32_t HAL_TransactionI2C(HAL_I2CPort port, int32_t deviceAddress,
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t handle = port == 0 ? i2COnBoardHandle : i2CMXPHandle;
|
||||
wpi::mutex& lock = port == 0 ? digitalI2COnBoardMutex : digitalI2CMXPMutex;
|
||||
struct i2c_msg msgs[2];
|
||||
msgs[0].addr = deviceAddress;
|
||||
msgs[0].flags = 0;
|
||||
msgs[0].len = sendSize;
|
||||
msgs[0].buf = dataToSend;
|
||||
msgs[1].addr = deviceAddress;
|
||||
msgs[1].flags = I2C_M_RD;
|
||||
msgs[1].len = receiveSize;
|
||||
msgs[1].buf = dataReceived;
|
||||
|
||||
{
|
||||
std::lock_guard<wpi::mutex> sync(lock);
|
||||
return i2clib_writeread(
|
||||
handle, deviceAddress, reinterpret_cast<const char*>(dataToSend),
|
||||
static_cast<int32_t>(sendSize), reinterpret_cast<char*>(dataReceived),
|
||||
static_cast<int32_t>(receiveSize));
|
||||
struct i2c_rdwr_ioctl_data rdwr;
|
||||
rdwr.msgs = msgs;
|
||||
rdwr.nmsgs = 2;
|
||||
|
||||
if (port == 0) {
|
||||
std::lock_guard<wpi::mutex> sync(digitalI2COnBoardMutex);
|
||||
return ioctl(i2COnBoardHandle, I2C_RDWR, &rdwr);
|
||||
} else {
|
||||
std::lock_guard<wpi::mutex> sync(digitalI2CMXPMutex);
|
||||
return ioctl(i2CMXPHandle, I2C_RDWR, &rdwr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,12 +143,22 @@ int32_t HAL_WriteI2C(HAL_I2CPort port, int32_t deviceAddress,
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t handle = port == 0 ? i2COnBoardHandle : i2CMXPHandle;
|
||||
wpi::mutex& lock = port == 0 ? digitalI2COnBoardMutex : digitalI2CMXPMutex;
|
||||
{
|
||||
std::lock_guard<wpi::mutex> sync(lock);
|
||||
return i2clib_write(handle, deviceAddress,
|
||||
reinterpret_cast<const char*>(dataToSend), sendSize);
|
||||
struct i2c_msg msg;
|
||||
msg.addr = deviceAddress;
|
||||
msg.flags = 0;
|
||||
msg.len = sendSize;
|
||||
msg.buf = dataToSend;
|
||||
|
||||
struct i2c_rdwr_ioctl_data rdwr;
|
||||
rdwr.msgs = &msg;
|
||||
rdwr.nmsgs = 1;
|
||||
|
||||
if (port == 0) {
|
||||
std::lock_guard<wpi::mutex> sync(digitalI2COnBoardMutex);
|
||||
return ioctl(i2COnBoardHandle, I2C_RDWR, &rdwr);
|
||||
} else {
|
||||
std::lock_guard<wpi::mutex> sync(digitalI2CMXPMutex);
|
||||
return ioctl(i2CMXPHandle, I2C_RDWR, &rdwr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,12 +182,22 @@ int32_t HAL_ReadI2C(HAL_I2CPort port, int32_t deviceAddress, uint8_t* buffer,
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t handle = port == 0 ? i2COnBoardHandle : i2CMXPHandle;
|
||||
wpi::mutex& lock = port == 0 ? digitalI2COnBoardMutex : digitalI2CMXPMutex;
|
||||
{
|
||||
std::lock_guard<wpi::mutex> sync(lock);
|
||||
return i2clib_read(handle, deviceAddress, reinterpret_cast<char*>(buffer),
|
||||
static_cast<int32_t>(count));
|
||||
struct i2c_msg msg;
|
||||
msg.addr = deviceAddress;
|
||||
msg.flags = I2C_M_RD;
|
||||
msg.len = count;
|
||||
msg.buf = buffer;
|
||||
|
||||
struct i2c_rdwr_ioctl_data rdwr;
|
||||
rdwr.msgs = &msg;
|
||||
rdwr.nmsgs = 1;
|
||||
|
||||
if (port == 0) {
|
||||
std::lock_guard<wpi::mutex> sync(digitalI2COnBoardMutex);
|
||||
return ioctl(i2COnBoardHandle, I2C_RDWR, &rdwr);
|
||||
} else {
|
||||
std::lock_guard<wpi::mutex> sync(digitalI2CMXPMutex);
|
||||
return ioctl(i2CMXPHandle, I2C_RDWR, &rdwr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,20 +206,20 @@ void HAL_CloseI2C(HAL_I2CPort port) {
|
||||
// Set port out of range error here
|
||||
return;
|
||||
}
|
||||
wpi::mutex& lock = port == 0 ? digitalI2COnBoardMutex : digitalI2CMXPMutex;
|
||||
{
|
||||
std::lock_guard<wpi::mutex> sync(lock);
|
||||
if ((port == 0 ? i2COnboardObjCount-- : i2CMXPObjCount--) == 0) {
|
||||
int32_t handle = port == 0 ? i2COnBoardHandle : i2CMXPHandle;
|
||||
i2clib_close(handle);
|
||||
}
|
||||
}
|
||||
|
||||
if (port == 1) {
|
||||
if (port == 0) {
|
||||
std::lock_guard<wpi::mutex> sync(digitalI2COnBoardMutex);
|
||||
if (i2COnboardObjCount-- == 0) {
|
||||
close(i2COnBoardHandle);
|
||||
}
|
||||
} else {
|
||||
std::lock_guard<wpi::mutex> sync(digitalI2CMXPMutex);
|
||||
if (i2CMXPObjCount-- == 0) {
|
||||
close(i2CMXPHandle);
|
||||
}
|
||||
HAL_FreeDIOPort(i2CMXPDigitalHandle1);
|
||||
HAL_FreeDIOPort(i2CMXPDigitalHandle2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
Reference in New Issue
Block a user