[hal,wpilib] Add support for second I2C port (#7878)

This commit is contained in:
Thad House
2025-04-28 08:29:01 -07:00
committed by GitHub
parent 85a8fc9943
commit 08297430b5
9 changed files with 54 additions and 43 deletions

View File

@@ -16,7 +16,7 @@
HAL_ENUM(HAL_I2CPort) {
HAL_I2C_kInvalid = -1,
HAL_I2C_kOnboard,
HAL_I2C_kMXP
HAL_I2C_kPort0,
HAL_I2C_kPort1
};
/** @} */

View File

@@ -18,37 +18,46 @@
#include "HALInitializer.h"
#include "HALInternal.h"
#include "PortsInternal.h"
#include "hal/DIO.h"
#include "hal/HAL.h"
using namespace hal;
static wpi::mutex digitalI2COnBoardMutex;
static uint8_t i2COnboardObjCount{0};
static int i2COnBoardHandle{-1};
namespace {
constexpr const char* physicalPorts[kNumI2cBuses] = {"/dev/i2c-1",
"/dev/i2c-10"};
struct I2C {
wpi::mutex initMutex;
int objCount = 0;
int fd = -1;
};
static I2C i2cObjs[kNumI2cBuses];
} // namespace
namespace hal::init {
void InitializeI2C() {}
} // namespace hal::init
extern "C" {
void HAL_InitializeI2C(HAL_I2CPort port, int32_t* status) {
hal::init::CheckInit();
if (port != 0) {
if (port < 0 || port > 2) {
*status = RESOURCE_OUT_OF_RANGE;
hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for I2C", 0, 0,
hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for I2C", 0, 1,
port);
return;
}
std::scoped_lock lock(digitalI2COnBoardMutex);
i2COnboardObjCount++;
if (i2COnboardObjCount > 1) {
std::scoped_lock lock(i2cObjs[port].initMutex);
i2cObjs[port].objCount++;
if (i2cObjs[port].objCount > 1) {
return;
}
int handle = open("/dev/i2c-1", O_RDWR);
int handle = open(physicalPorts[port], O_RDWR);
if (handle < 0) {
int err = errno;
*status = NO_AVAILABLE_RESOURCES;
@@ -56,18 +65,18 @@ void HAL_InitializeI2C(HAL_I2CPort port, int32_t* status) {
std::strerror(err)));
wpi::print("Failed to open onboard i2c bus: {}\n", std::strerror(err));
handle = -1;
i2COnboardObjCount--;
i2cObjs[port].objCount--;
return;
}
i2COnBoardHandle = handle;
i2cObjs[port].fd = handle;
}
int32_t HAL_TransactionI2C(HAL_I2CPort port, int32_t deviceAddress,
const uint8_t* dataToSend, int32_t sendSize,
uint8_t* dataReceived, int32_t receiveSize) {
if (port != 0) {
if (port < 0 || port > 2) {
int32_t status = 0;
hal::SetLastErrorIndexOutOfRange(&status, "Invalid Index for I2C", 0, 0,
hal::SetLastErrorIndexOutOfRange(&status, "Invalid Index for I2C", 0, 1,
port);
return -1;
}
@@ -86,15 +95,15 @@ int32_t HAL_TransactionI2C(HAL_I2CPort port, int32_t deviceAddress,
rdwr.msgs = msgs;
rdwr.nmsgs = 2;
std::scoped_lock lock(digitalI2COnBoardMutex);
return ioctl(i2COnBoardHandle, I2C_RDWR, &rdwr);
std::scoped_lock lock(i2cObjs[port].initMutex);
return ioctl(i2cObjs[port].fd, I2C_RDWR, &rdwr);
}
int32_t HAL_WriteI2C(HAL_I2CPort port, int32_t deviceAddress,
const uint8_t* dataToSend, int32_t sendSize) {
if (port != 0) {
if (port < 0 || port > 2) {
int32_t status = 0;
hal::SetLastErrorIndexOutOfRange(&status, "Invalid Index for I2C", 0, 0,
hal::SetLastErrorIndexOutOfRange(&status, "Invalid Index for I2C", 0, 2,
port);
return -1;
}
@@ -109,15 +118,15 @@ int32_t HAL_WriteI2C(HAL_I2CPort port, int32_t deviceAddress,
rdwr.msgs = &msg;
rdwr.nmsgs = 1;
std::scoped_lock lock(digitalI2COnBoardMutex);
return ioctl(i2COnBoardHandle, I2C_RDWR, &rdwr);
std::scoped_lock lock(i2cObjs[port].initMutex);
return ioctl(i2cObjs[port].fd, I2C_RDWR, &rdwr);
}
int32_t HAL_ReadI2C(HAL_I2CPort port, int32_t deviceAddress, uint8_t* buffer,
int32_t count) {
if (port != 0) {
if (port < 0 || port > 2) {
int32_t status = 0;
hal::SetLastErrorIndexOutOfRange(&status, "Invalid Index for I2C", 0, 0,
hal::SetLastErrorIndexOutOfRange(&status, "Invalid Index for I2C", 0, 1,
port);
return -1;
}
@@ -132,21 +141,22 @@ int32_t HAL_ReadI2C(HAL_I2CPort port, int32_t deviceAddress, uint8_t* buffer,
rdwr.msgs = &msg;
rdwr.nmsgs = 1;
std::scoped_lock lock(digitalI2COnBoardMutex);
return ioctl(i2COnBoardHandle, I2C_RDWR, &rdwr);
std::scoped_lock lock(i2cObjs[port].initMutex);
return ioctl(i2cObjs[port].fd, I2C_RDWR, &rdwr);
}
void HAL_CloseI2C(HAL_I2CPort port) {
if (port != 0) {
if (port < 0 || port > 2) {
int32_t status = 0;
hal::SetLastErrorIndexOutOfRange(&status, "Invalid Index for I2C", 0, 0,
hal::SetLastErrorIndexOutOfRange(&status, "Invalid Index for I2C", 0, 1,
port);
return;
}
std::scoped_lock lock(digitalI2COnBoardMutex);
if (i2COnboardObjCount-- == 0) {
close(i2COnBoardHandle);
std::scoped_lock lock(i2cObjs[port].initMutex);
if (i2cObjs[port].objCount-- == 0) {
close(i2cObjs[port].objCount);
i2cObjs[port].fd = -1;
}
}

View File

@@ -10,6 +10,7 @@ namespace hal {
constexpr int32_t kNumCanBuses = 5;
constexpr int32_t kNumSmartIo = 6;
constexpr int32_t kNumI2cBuses = 2;
constexpr int32_t kNumAccumulators = 0;
constexpr int32_t kNumAnalogInputs = 8;
constexpr int32_t kNumAnalogOutputs = 0;

View File

@@ -31,7 +31,7 @@ TEST(I2CSimTest, I2CInitialization) {
INDEX_TO_TEST, &TestI2CInitializationCallback, &callbackParam, false);
ASSERT_TRUE(0 != callbackId);
port = HAL_I2C_kMXP;
port = HAL_I2C_kPort1;
gTestI2CCallbackName = "Unset";
HAL_InitializeI2C(port, &status);
EXPECT_STREQ("Initialized", gTestI2CCallbackName.c_str());

View File

@@ -23,10 +23,10 @@ class I2C {
* I2C connection ports.
*/
enum Port {
/// Onboard I2C port.
kOnboard = 0,
/// MXP (roboRIO MXP) I2C port.
kMXP
/// I2C Port 0.
kPort0 = 0,
/// I2C Port 1.
kPort1
};
/**

View File

@@ -17,7 +17,7 @@ class Robot : public frc::TimedRobot {
public:
void RobotPeriodic() override;
static constexpr frc::I2C::Port kPort = frc::I2C::Port::kOnboard;
static constexpr frc::I2C::Port kPort = frc::I2C::Port::kPort0;
private:
static constexpr int deviceAddress = 4;

View File

@@ -20,10 +20,10 @@ import java.nio.ByteBuffer;
public class I2C implements AutoCloseable {
/** I2C connection ports. */
public enum Port {
/** Onboard I2C port. */
kOnboard(0),
/** MXP (roboRIO MXP) I2C port. */
kMXP(1);
/** I2C Port 0. */
kPort0(0),
/** I2C Port 1. */
kPort1(1);
/** Port value. */
public final int value;

View File

@@ -18,7 +18,7 @@ class ADXL345SimTest {
void testInitI2C(ADXL345_I2C.Range range) {
HAL.initialize(500, 0);
try (ADXL345_I2C accel = new ADXL345_I2C(I2C.Port.kMXP, range)) {
try (ADXL345_I2C accel = new ADXL345_I2C(I2C.Port.kPort0, range)) {
ADXL345Sim sim = new ADXL345Sim(accel);
sim.setX(1.91);

View File

@@ -15,7 +15,7 @@ import java.util.Optional;
* code using the roboRIO's I2C port.
*/
public class Robot extends TimedRobot {
static final Port kPort = Port.kOnboard;
static final Port kPort = Port.kPort0;
private static final int kDeviceAddress = 4;
private final I2C m_arduino = new I2C(kPort, kDeviceAddress);