[hal,wpilib] Fix SPI Mode Setting (#4434)

SPI Mode setting was very broken. MSB and LSB sets did not work (MSB is the only one supported)
and if LSB was set (which was the default) the ioct to set clock phase would fail. This
deprecates all the individual functions, the LSB/MSB functions, and adds an SPI mode selection
function. This is usually more understandable, and shows up in a lot more documentation
This commit is contained in:
Thad House
2022-09-24 00:11:37 -07:00
committed by GitHub
parent 773198537c
commit 17f504f548
19 changed files with 243 additions and 95 deletions

View File

@@ -364,19 +364,27 @@ void HAL_SetSPISpeed(HAL_SPIPort port, int32_t speed) {
ioctl(HAL_GetSPIHandle(port), SPI_IOC_WR_MAX_SPEED_HZ, &speed);
}
void HAL_SetSPIOpts(HAL_SPIPort port, HAL_Bool msbFirst,
HAL_Bool sampleOnTrailing, HAL_Bool clkIdleHigh) {
void HAL_SetSPIMode(HAL_SPIPort port, HAL_SPIMode mode) {
if (port < 0 || port >= kSpiMaxHandles) {
return;
}
uint8_t mode = 0;
mode |= (!msbFirst ? 8 : 0);
mode |= (clkIdleHigh ? 2 : 0);
mode |= (sampleOnTrailing ? 1 : 0);
uint8_t mode8 = mode & SPI_MODE_3;
std::scoped_lock lock(spiApiMutexes[port]);
ioctl(HAL_GetSPIHandle(port), SPI_IOC_WR_MODE, &mode);
ioctl(HAL_GetSPIHandle(port), SPI_IOC_WR_MODE, &mode8);
}
HAL_SPIMode HAL_GetSPIMode(HAL_SPIPort port) {
if (port < 0 || port >= kSpiMaxHandles) {
return HAL_SPI_kMode0;
}
uint8_t mode8 = 0;
std::scoped_lock lock(spiApiMutexes[port]);
ioctl(HAL_GetSPIHandle(port), SPI_IOC_RD_MODE, &mode8);
return static_cast<HAL_SPIMode>(mode8 & SPI_MODE_3);
}
void HAL_SetSPIChipSelectActiveHigh(HAL_SPIPort port, int32_t* status) {

View File

@@ -15,6 +15,27 @@
using namespace hal;
using namespace wpi::java;
static_assert(HAL_SPIPort::HAL_SPI_kInvalid ==
edu_wpi_first_hal_SPIJNI_INVALID_PORT);
static_assert(HAL_SPIPort::HAL_SPI_kOnboardCS0 ==
edu_wpi_first_hal_SPIJNI_ONBOARD_CS0_PORT);
static_assert(HAL_SPIPort::HAL_SPI_kOnboardCS1 ==
edu_wpi_first_hal_SPIJNI_ONBOARD_CS1_PORT);
static_assert(HAL_SPIPort::HAL_SPI_kOnboardCS2 ==
edu_wpi_first_hal_SPIJNI_ONBOARD_CS2_PORT);
static_assert(HAL_SPIPort::HAL_SPI_kOnboardCS3 ==
edu_wpi_first_hal_SPIJNI_ONBOARD_CS3_PORT);
static_assert(HAL_SPIPort::HAL_SPI_kMXP == edu_wpi_first_hal_SPIJNI_MXP_PORT);
static_assert(HAL_SPIMode::HAL_SPI_kMode0 ==
edu_wpi_first_hal_SPIJNI_SPI_MODE0);
static_assert(HAL_SPIMode::HAL_SPI_kMode1 ==
edu_wpi_first_hal_SPIJNI_SPI_MODE1);
static_assert(HAL_SPIMode::HAL_SPI_kMode2 ==
edu_wpi_first_hal_SPIJNI_SPI_MODE2);
static_assert(HAL_SPIMode::HAL_SPI_kMode3 ==
edu_wpi_first_hal_SPIJNI_SPI_MODE3);
extern "C" {
/*
@@ -202,16 +223,27 @@ Java_edu_wpi_first_hal_SPIJNI_spiSetSpeed
/*
* Class: edu_wpi_first_hal_SPIJNI
* Method: spiSetOpts
* Signature: (IIII)V
* Method: spiSetMode
* Signature: (II)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_SPIJNI_spiSetOpts
(JNIEnv*, jclass, jint port, jint msb_first, jint sample_on_trailing,
jint clk_idle_high)
Java_edu_wpi_first_hal_SPIJNI_spiSetMode
(JNIEnv*, jclass, jint port, jint mode)
{
HAL_SetSPIOpts(static_cast<HAL_SPIPort>(port), msb_first, sample_on_trailing,
clk_idle_high);
HAL_SetSPIMode(static_cast<HAL_SPIPort>(port),
static_cast<HAL_SPIMode>(mode));
}
/*
* Class: edu_wpi_first_hal_SPIJNI
* Method: spiGetMode
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_SPIJNI_spiGetMode
(JNIEnv*, jclass, jint port)
{
return static_cast<jint>(HAL_GetSPIMode(static_cast<HAL_SPIPort>(port)));
}
/*

View File

@@ -90,23 +90,27 @@ void HAL_CloseSPI(HAL_SPIPort port);
*
* @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for
* MXP
* @param speed The speed in Hz (0-1MHz)
* @param speed The speed in Hz (500KHz-10MHz)
*/
void HAL_SetSPISpeed(HAL_SPIPort port, int32_t speed);
/**
* Sets the SPI options.
* Sets the SPI Mode.
*
* @param port The number of the port to use. 0-3 for Onboard
* CS0-CS2, 4 for MXP
* @param msbFirst True to write the MSB first, False for LSB first
* @param sampleOnTrailing True to sample on the trailing edge, False to sample
* on the leading edge
* @param clkIdleHigh True to set the clock to active low, False to set the
* clock active high
* @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for
* MXP
* @param mode The SPI mode to use
*/
void HAL_SetSPIOpts(HAL_SPIPort port, HAL_Bool msbFirst,
HAL_Bool sampleOnTrailing, HAL_Bool clkIdleHigh);
void HAL_SetSPIMode(HAL_SPIPort port, HAL_SPIMode mode);
/**
* Gets the SPI Mode.
*
* @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for
* MXP
* @returns The SPI mode currently set
*/
HAL_SPIMode HAL_GetSPIMode(HAL_SPIPort port);
/**
* Sets the CS Active high for a SPI port.

View File

@@ -25,6 +25,15 @@ HAL_ENUM(HAL_SPIPort) {
};
// clang-format on
// clang-format off
HAL_ENUM(HAL_SPIMode) {
HAL_SPI_kMode0 = 0,
HAL_SPI_kMode1 = 1,
HAL_SPI_kMode2 = 2,
HAL_SPI_kMode3 = 3,
};
// clang-format on
#ifdef __cplusplus
namespace hal {

View File

@@ -34,8 +34,10 @@ void HAL_CloseSPI(HAL_SPIPort port) {
SimSPIData[port].initialized = false;
}
void HAL_SetSPISpeed(HAL_SPIPort port, int32_t speed) {}
void HAL_SetSPIOpts(HAL_SPIPort port, HAL_Bool msbFirst,
HAL_Bool sampleOnTrailing, HAL_Bool clkIdleHigh) {}
void HAL_SetSPIMode(HAL_SPIPort port, HAL_SPIMode mode) {}
HAL_SPIMode HAL_GetSPIMode(HAL_SPIPort port) {
return HAL_SPI_kMode0;
}
void HAL_SetSPIChipSelectActiveHigh(HAL_SPIPort port, int32_t* status) {}
void HAL_SetSPIChipSelectActiveLow(HAL_SPIPort port, int32_t* status) {}
int32_t HAL_GetSPIHandle(HAL_SPIPort port) {