diff --git a/hal/src/main/native/athena/I2C.cpp b/hal/src/main/native/athena/I2C.cpp index 53f2035e66..e09251df14 100644 --- a/hal/src/main/native/athena/I2C.cpp +++ b/hal/src/main/native/athena/I2C.cpp @@ -7,7 +7,13 @@ #include "HAL/I2C.h" -#include +#include +#include +#include +#include +#include + +#include #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 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 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 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 sync(lock); - return i2clib_writeread( - handle, deviceAddress, reinterpret_cast(dataToSend), - static_cast(sendSize), reinterpret_cast(dataReceived), - static_cast(receiveSize)); + struct i2c_rdwr_ioctl_data rdwr; + rdwr.msgs = msgs; + rdwr.nmsgs = 2; + + if (port == 0) { + std::lock_guard sync(digitalI2COnBoardMutex); + return ioctl(i2COnBoardHandle, I2C_RDWR, &rdwr); + } else { + std::lock_guard 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 sync(lock); - return i2clib_write(handle, deviceAddress, - reinterpret_cast(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 sync(digitalI2COnBoardMutex); + return ioctl(i2COnBoardHandle, I2C_RDWR, &rdwr); + } else { + std::lock_guard 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 sync(lock); - return i2clib_read(handle, deviceAddress, reinterpret_cast(buffer), - static_cast(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 sync(digitalI2COnBoardMutex); + return ioctl(i2COnBoardHandle, I2C_RDWR, &rdwr); + } else { + std::lock_guard 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 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 sync(digitalI2COnBoardMutex); + if (i2COnboardObjCount-- == 0) { + close(i2COnBoardHandle); + } + } else { + std::lock_guard sync(digitalI2CMXPMutex); + if (i2CMXPObjCount-- == 0) { + close(i2CMXPHandle); + } HAL_FreeDIOPort(i2CMXPDigitalHandle1); HAL_FreeDIOPort(i2CMXPDigitalHandle2); } - return; } } // extern "C" diff --git a/hal/src/main/native/athena/SPI.cpp b/hal/src/main/native/athena/SPI.cpp index d0a5caa40d..08fc5530e3 100644 --- a/hal/src/main/native/athena/SPI.cpp +++ b/hal/src/main/native/athena/SPI.cpp @@ -7,11 +7,16 @@ #include "HAL/SPI.h" +#include +#include +#include +#include + #include #include +#include #include -#include #include #include "DigitalInternal.h" @@ -111,13 +116,21 @@ void HAL_InitializeSPI(HAL_SPIPort port, int32_t* status) { return; } + int handle; if (HAL_GetSPIHandle(port) != 0) return; switch (port) { case 0: CommonSPIPortInit(status); if (*status != 0) return; // CS0 is not a DIO port, so nothing to allocate - HAL_SetSPIHandle(HAL_SPI_kOnboardCS0, spilib_open("/dev/spidev0.0")); + handle = open("/dev/spidev0.0", O_RDWR); + if (handle < 0) { + std::printf("Failed to open SPI port %d: %s\n", port, + std::strerror(errno)); + CommonSPIPortFree(); + return; + } + HAL_SetSPIHandle(HAL_SPI_kOnboardCS0, handle); break; case 1: CommonSPIPortInit(status); @@ -130,7 +143,15 @@ void HAL_InitializeSPI(HAL_SPIPort port, int32_t* status) { CommonSPIPortFree(); return; } - HAL_SetSPIHandle(HAL_SPI_kOnboardCS1, spilib_open("/dev/spidev0.1")); + handle = open("/dev/spidev0.1", O_RDWR); + if (handle < 0) { + std::printf("Failed to open SPI port %d: %s\n", port, + std::strerror(errno)); + CommonSPIPortFree(); + HAL_FreeDIOPort(digitalHandles[0]); + return; + } + HAL_SetSPIHandle(HAL_SPI_kOnboardCS1, handle); break; case 2: CommonSPIPortInit(status); @@ -143,7 +164,15 @@ void HAL_InitializeSPI(HAL_SPIPort port, int32_t* status) { CommonSPIPortFree(); return; } - HAL_SetSPIHandle(HAL_SPI_kOnboardCS2, spilib_open("/dev/spidev0.2")); + handle = open("/dev/spidev0.2", O_RDWR); + if (handle < 0) { + std::printf("Failed to open SPI port %d: %s\n", port, + std::strerror(errno)); + CommonSPIPortFree(); + HAL_FreeDIOPort(digitalHandles[1]); + return; + } + HAL_SetSPIHandle(HAL_SPI_kOnboardCS2, handle); break; case 3: CommonSPIPortInit(status); @@ -156,7 +185,15 @@ void HAL_InitializeSPI(HAL_SPIPort port, int32_t* status) { CommonSPIPortFree(); return; } - HAL_SetSPIHandle(HAL_SPI_kOnboardCS3, spilib_open("/dev/spidev0.3")); + handle = open("/dev/spidev0.3", O_RDWR); + if (handle < 0) { + std::printf("Failed to open SPI port %d: %s\n", port, + std::strerror(errno)); + CommonSPIPortFree(); + HAL_FreeDIOPort(digitalHandles[2]); + return; + } + HAL_SetSPIHandle(HAL_SPI_kOnboardCS3, handle); break; case 4: initializeDigital(status); @@ -193,13 +230,22 @@ void HAL_InitializeSPI(HAL_SPIPort port, int32_t* status) { } digitalSystem->writeEnableMXPSpecialFunction( digitalSystem->readEnableMXPSpecialFunction(status) | 0x00F0, status); - HAL_SetSPIHandle(HAL_SPI_kMXP, spilib_open("/dev/spidev1.0")); + handle = open("/dev/spidev1.0", O_RDWR); + if (handle < 0) { + std::printf("Failed to open SPI port %d: %s\n", port, + std::strerror(errno)); + HAL_FreeDIOPort(digitalHandles[5]); // free the first port allocated + HAL_FreeDIOPort(digitalHandles[6]); // free the second port allocated + HAL_FreeDIOPort(digitalHandles[7]); // free the third port allocated + HAL_FreeDIOPort(digitalHandles[8]); // free the fourth port allocated + return; + } + HAL_SetSPIHandle(HAL_SPI_kMXP, handle); break; default: *status = PARAMETER_OUT_OF_RANGE; break; } - return; } /** @@ -220,10 +266,14 @@ int32_t HAL_TransactionSPI(HAL_SPIPort port, uint8_t* dataToSend, return -1; } + struct spi_ioc_transfer xfer; + std::memset(&xfer, 0, sizeof(xfer)); + xfer.tx_buf = (__u64)dataToSend; + xfer.rx_buf = (__u64)dataReceived; + xfer.len = size; + std::lock_guard sync(spiApiMutexes[port]); - return spilib_writeread( - HAL_GetSPIHandle(port), reinterpret_cast(dataToSend), - reinterpret_cast(dataReceived), static_cast(size)); + return ioctl(HAL_GetSPIHandle(port), SPI_IOC_MESSAGE(1), &xfer); } /** @@ -241,10 +291,13 @@ int32_t HAL_WriteSPI(HAL_SPIPort port, uint8_t* dataToSend, int32_t sendSize) { return -1; } + struct spi_ioc_transfer xfer; + std::memset(&xfer, 0, sizeof(xfer)); + xfer.tx_buf = (__u64)dataToSend; + xfer.len = sendSize; + std::lock_guard sync(spiApiMutexes[port]); - return spilib_write(HAL_GetSPIHandle(port), - reinterpret_cast(dataToSend), - static_cast(sendSize)); + return ioctl(HAL_GetSPIHandle(port), SPI_IOC_MESSAGE(1), &xfer); } /** @@ -265,9 +318,13 @@ int32_t HAL_ReadSPI(HAL_SPIPort port, uint8_t* buffer, int32_t count) { return -1; } + struct spi_ioc_transfer xfer; + std::memset(&xfer, 0, sizeof(xfer)); + xfer.rx_buf = (__u64)buffer; + xfer.len = count; + std::lock_guard sync(spiApiMutexes[port]); - return spilib_read(HAL_GetSPIHandle(port), reinterpret_cast(buffer), - static_cast(count)); + return ioctl(HAL_GetSPIHandle(port), SPI_IOC_MESSAGE(1), &xfer); } /** @@ -285,7 +342,7 @@ void HAL_CloseSPI(HAL_SPIPort port) { { std::lock_guard sync(spiApiMutexes[port]); - spilib_close(HAL_GetSPIHandle(port)); + close(HAL_GetSPIHandle(port)); } HAL_SetSPIHandle(port, 0); @@ -327,7 +384,7 @@ void HAL_SetSPISpeed(HAL_SPIPort port, int32_t speed) { } std::lock_guard sync(spiApiMutexes[port]); - spilib_setspeed(HAL_GetSPIHandle(port), speed); + ioctl(HAL_GetSPIHandle(port), SPI_IOC_WR_MAX_SPEED_HZ, &speed); } /** @@ -346,9 +403,13 @@ void HAL_SetSPIOpts(HAL_SPIPort port, HAL_Bool msbFirst, return; } + uint8_t mode = 0; + mode |= (!msbFirst ? 8 : 0); + mode |= (clkIdleHigh ? 2 : 0); + mode |= (sampleOnTrailing ? 1 : 0); + std::lock_guard sync(spiApiMutexes[port]); - spilib_setopts(HAL_GetSPIHandle(port), msbFirst, sampleOnTrailing, - clkIdleHigh); + ioctl(HAL_GetSPIHandle(port), SPI_IOC_WR_MODE, &mode); } /** @@ -462,13 +523,7 @@ static void spiAccumulatorProcess(uint64_t currentTime, // perform SPI transaction uint8_t resp_b[4]; - { - std::lock_guard sync(spiApiMutexes[accum->port]); - spilib_writeread(HAL_GetSPIHandle(accum->port), - reinterpret_cast(accum->cmd), - reinterpret_cast(resp_b), - static_cast(accum->xferSize)); - } + HAL_TransactionSPI(accum->port, accum->cmd, resp_b, accum->xferSize); // convert from bytes uint32_t resp = 0;