From f78c3795e30313ae6db6aab24bb1b658a657a77c Mon Sep 17 00:00:00 2001 From: Ryan Blue Date: Tue, 29 Oct 2024 23:43:24 -0400 Subject: [PATCH] Convert rest of SPI HAL API to use handles --- hal/src/main/native/athena/SPI.cpp | 205 ++++++++++++---------- hal/src/main/native/include/hal/SPI.h | 101 +++++------ hal/src/main/native/sim/SPI.cpp | 120 ++++++++++--- wpilibc/src/main/native/cpp/SPI.cpp | 6 +- wpilibc/src/main/native/include/frc/SPI.h | 3 +- 5 files changed, 251 insertions(+), 184 deletions(-) diff --git a/hal/src/main/native/athena/SPI.cpp b/hal/src/main/native/athena/SPI.cpp index 431edaa8c82..f1f094172d4 100644 --- a/hal/src/main/native/athena/SPI.cpp +++ b/hal/src/main/native/athena/SPI.cpp @@ -320,14 +320,14 @@ HAL_SPIHandle HAL_InitializeSPI(HAL_SPIPort port, int32_t* status) { return hal_handle; } -int32_t HAL_TransactionSPI(HAL_SPIPort port, const uint8_t* dataToSend, +int32_t HAL_TransactionSPI(HAL_SPIHandle handle, const uint8_t* dataToSend, uint8_t* dataReceived, int32_t size) { - auto spi = spiHandles->Get(spiHandles->GetHandleForPort(port)); + auto spi = spiHandles->Get(handle); if (!spi) { return -1; } - if (SPIInUseByAuto(port)) { + if (SPIInUseByAuto(spi->port)) { return -1; } @@ -341,14 +341,14 @@ int32_t HAL_TransactionSPI(HAL_SPIPort port, const uint8_t* dataToSend, return ioctl(spi->nativeHandle, SPI_IOC_MESSAGE(1), &xfer); } -int32_t HAL_WriteSPI(HAL_SPIPort port, const uint8_t* dataToSend, +int32_t HAL_WriteSPI(HAL_SPIHandle handle, const uint8_t* dataToSend, int32_t sendSize) { - auto spi = spiHandles->Get(spiHandles->GetHandleForPort(port)); + auto spi = spiHandles->Get(handle); if (!spi) { return -1; } - if (SPIInUseByAuto(port)) { + if (SPIInUseByAuto(spi->port)) { return -1; } @@ -361,13 +361,13 @@ int32_t HAL_WriteSPI(HAL_SPIPort port, const uint8_t* dataToSend, return ioctl(spi->nativeHandle, SPI_IOC_MESSAGE(1), &xfer); } -int32_t HAL_ReadSPI(HAL_SPIPort port, uint8_t* buffer, int32_t count) { - auto spi = spiHandles->Get(spiHandles->GetHandleForPort(port)); +int32_t HAL_ReadSPI(HAL_SPIHandle handle, uint8_t* buffer, int32_t count) { + auto spi = spiHandles->Get(handle); if (!spi) { return -1; } - if (SPIInUseByAuto(port)) { + if (SPIInUseByAuto(spi->port)) { return -1; } @@ -380,25 +380,25 @@ int32_t HAL_ReadSPI(HAL_SPIPort port, uint8_t* buffer, int32_t count) { return ioctl(spi->nativeHandle, SPI_IOC_MESSAGE(1), &xfer); } -void HAL_CloseSPI(HAL_SPIPort port) { - auto spi = spiHandles->Get(spiHandles->GetHandleForPort(port)); +void HAL_CloseSPI(HAL_SPIHandle handle) { + auto spi = spiHandles->Get(handle); if (!spi) { return; } int32_t status = 0; - HAL_FreeSPIAuto(port, &status); + HAL_FreeSPIAuto(spi->port, &status); { std::scoped_lock lock(spi->apiMutex); close(spi->nativeHandle); } - if (port < 4) { + if (spi->port < 4) { CommonSPIPortFree(); } - switch (port) { + switch (spi->port) { // Case 0 does not need to do anything case 1: HAL_FreeDIOPort(digitalHandles[0]); @@ -418,11 +418,11 @@ void HAL_CloseSPI(HAL_SPIPort port) { default: break; } - spiHandles->Free(spiHandles->GetHandleForPort(port)); + spiHandles->Free(handle); } -void HAL_SetSPISpeed(HAL_SPIPort port, int32_t speed) { - auto spi = spiHandles->Get(spiHandles->GetHandleForPort(port)); +void HAL_SetSPISpeed(HAL_SPIHandle handle, int32_t speed) { + auto spi = spiHandles->Get(handle); if (!spi) { return; } @@ -431,8 +431,8 @@ void HAL_SetSPISpeed(HAL_SPIPort port, int32_t speed) { ioctl(spi->nativeHandle, SPI_IOC_WR_MAX_SPEED_HZ, &speed); } -void HAL_SetSPIMode(HAL_SPIPort port, HAL_SPIMode mode) { - auto spi = spiHandles->Get(spiHandles->GetHandleForPort(port)); +void HAL_SetSPIMode(HAL_SPIHandle handle, HAL_SPIMode mode) { + auto spi = spiHandles->Get(handle); if (!spi) { return; } @@ -443,8 +443,8 @@ void HAL_SetSPIMode(HAL_SPIPort port, HAL_SPIMode mode) { ioctl(spi->nativeHandle, SPI_IOC_WR_MODE, &mode8); } -HAL_SPIMode HAL_GetSPIMode(HAL_SPIPort port) { - auto spi = spiHandles->Get(spiHandles->GetHandleForPort(port)); +HAL_SPIMode HAL_GetSPIMode(HAL_SPIHandle handle) { + auto spi = spiHandles->Get(handle); if (!spi) { return HAL_SPI_kMode0; } @@ -456,67 +456,45 @@ HAL_SPIMode HAL_GetSPIMode(HAL_SPIPort port) { return static_cast(mode8 & SPI_MODE_3); } -void HAL_SetSPIChipSelectActiveHigh(HAL_SPIPort port, int32_t* status) { - if (port < 0 || port >= kSpiMaxHandles) { - *status = PARAMETER_OUT_OF_RANGE; - hal::SetLastError( - status, fmt::format("SPI port must be between 0 and {}. Requested {}", - kSpiMaxHandles, static_cast(port))); - return; - } - - auto spi = spiHandles->Get(spiHandles->GetHandleForPort( - port)); // TODO: consolidate with above check +void HAL_SetSPIChipSelectActiveHigh(HAL_SPIHandle handle, int32_t* status) { + auto spi = spiHandles->Get(handle); if (!spi) { - *status = INCOMPATIBLE_STATE; + *status = HAL_HANDLE_ERROR; return; } std::scoped_lock lock(spi->apiMutex); - if (port < 4) { + if (spi->port < 4) { spiSystem->writeChipSelectActiveHigh_Hdr( - spiSystem->readChipSelectActiveHigh_Hdr(status) | (1 << port), status); + spiSystem->readChipSelectActiveHigh_Hdr(status) | (1 << spi->port), + status); } else { spiSystem->writeChipSelectActiveHigh_MXP(1, status); } } -void HAL_SetSPIChipSelectActiveLow(HAL_SPIPort port, int32_t* status) { - if (port < 0 || port >= kSpiMaxHandles) { - *status = PARAMETER_OUT_OF_RANGE; - hal::SetLastError( - status, fmt::format("SPI port must be between 0 and {}. Requested {}", - kSpiMaxHandles, static_cast(port))); - return; - } - - auto spi = spiHandles->Get(spiHandles->GetHandleForPort( - port)); // TODO: consolidate with above check +void HAL_SetSPIChipSelectActiveLow(HAL_SPIHandle handle, int32_t* status) { + auto spi = spiHandles->Get(handle); if (!spi) { + *status = HAL_HANDLE_ERROR; return; } std::scoped_lock lock(spi->apiMutex); - if (port < 4) { + if (spi->port < 4) { spiSystem->writeChipSelectActiveHigh_Hdr( - spiSystem->readChipSelectActiveHigh_Hdr(status) & ~(1 << port), status); + spiSystem->readChipSelectActiveHigh_Hdr(status) & ~(1 << spi->port), + status); } else { spiSystem->writeChipSelectActiveHigh_MXP(0, status); } } -void HAL_InitSPIAuto(HAL_SPIPort port, int32_t bufferSize, int32_t* status) { - if (port < 0 || port >= kSpiMaxHandles) { - *status = PARAMETER_OUT_OF_RANGE; - hal::SetLastError( - status, fmt::format("SPI port must be between 0 and {}. Requested {}", - kSpiMaxHandles, static_cast(port))); - return; - } - - if (!spiHandles->Get(spiHandles->GetHandleForPort( - port))) { // TODO: consolidate with above check - *status = INCOMPATIBLE_STATE; +void HAL_InitSPIAuto(HAL_SPIHandle handle, int32_t bufferSize, + int32_t* status) { + auto spi = spiHandles->Get(handle); + if (!spi) { + *status = HAL_HANDLE_ERROR; return; } @@ -528,12 +506,12 @@ void HAL_InitSPIAuto(HAL_SPIPort port, int32_t bufferSize, int32_t* status) { } // remember the initialized port for other entry points - spiAutoPort = port; + spiAutoPort = spi->port; // configure the correct chip select - if (port < 4) { + if (spi->port < 4) { spiSystem->writeAutoSPI1Select(false, status); - spiSystem->writeAutoChipSelect(port, status); + spiSystem->writeAutoChipSelect(spi->port, status); } else { spiSystem->writeAutoSPI1Select(true, status); spiSystem->writeAutoChipSelect(0, status); @@ -544,23 +522,15 @@ void HAL_InitSPIAuto(HAL_SPIPort port, int32_t bufferSize, int32_t* status) { std::make_unique(g_SpiAutoData_index, bufferSize, status); } -void HAL_FreeSPIAuto(HAL_SPIPort port, int32_t* status) { - if (port < 0 || port >= kSpiMaxHandles) { - *status = PARAMETER_OUT_OF_RANGE; - hal::SetLastError( - status, fmt::format("SPI port must be between 0 and {}. Requested {}", - kSpiMaxHandles, static_cast(port))); - return; - } - - if (!spiHandles->Get(spiHandles->GetHandleForPort( - port))) { // TODO: consolidate with above check - *status = INCOMPATIBLE_STATE; +void HAL_FreeSPIAuto(HAL_SPIHandle handle, int32_t* status) { + auto spi = spiHandles->Get(handle); + if (!spi) { + *status = HAL_HANDLE_ERROR; return; } std::scoped_lock lock(spiAutoMutex); - if (spiAutoPort != port) { + if (spiAutoPort != spi->port) { return; } spiAutoPort = kSpiMaxHandles; @@ -577,10 +547,17 @@ void HAL_FreeSPIAuto(HAL_SPIPort port, int32_t* status) { spiAutoRunning = false; } -void HAL_StartSPIAutoRate(HAL_SPIPort port, double period, int32_t* status) { +void HAL_StartSPIAutoRate(HAL_SPIHandle handle, double period, + int32_t* status) { + auto spi = spiHandles->Get(handle); + if (!spi) { + *status = HAL_HANDLE_ERROR; + return; + } + std::scoped_lock lock(spiAutoMutex); // FPGA only has one auto SPI engine - if (port != spiAutoPort) { + if (spi->port != spiAutoPort) { *status = INCOMPATIBLE_STATE; return; } @@ -597,13 +574,20 @@ void HAL_StartSPIAutoRate(HAL_SPIPort port, double period, int32_t* status) { spiSystem->writeAutoTriggerConfig_ExternalClock(false, status); } -void HAL_StartSPIAutoTrigger(HAL_SPIPort port, HAL_Handle digitalSourceHandle, +void HAL_StartSPIAutoTrigger(HAL_SPIHandle handle, + HAL_Handle digitalSourceHandle, HAL_AnalogTriggerType analogTriggerType, HAL_Bool triggerRising, HAL_Bool triggerFalling, int32_t* status) { + auto spi = spiHandles->Get(handle); + if (!spi) { + *status = HAL_HANDLE_ERROR; + return; + } + std::scoped_lock lock(spiAutoMutex); // FPGA only has one auto SPI engine - if (port != spiAutoPort) { + if (spi->port != spiAutoPort) { *status = INCOMPATIBLE_STATE; return; } @@ -635,10 +619,16 @@ void HAL_StartSPIAutoTrigger(HAL_SPIPort port, HAL_Handle digitalSourceHandle, spiSystem->writeAutoTriggerConfig(config, status); } -void HAL_StopSPIAuto(HAL_SPIPort port, int32_t* status) { +void HAL_StopSPIAuto(HAL_SPIHandle handle, int32_t* status) { + auto spi = spiHandles->Get(handle); + if (!spi) { + *status = HAL_HANDLE_ERROR; + return; + } + std::scoped_lock lock(spiAutoMutex); // FPGA only has one auto SPI engine - if (port != spiAutoPort) { + if (spi->port != spiAutoPort) { *status = INCOMPATIBLE_STATE; return; } @@ -653,9 +643,16 @@ void HAL_StopSPIAuto(HAL_SPIPort port, int32_t* status) { spiAutoRunning = false; } -void HAL_SetSPIAutoTransmitData(HAL_SPIPort port, const uint8_t* dataToSend, +void HAL_SetSPIAutoTransmitData(HAL_SPIHandle handle, const uint8_t* dataToSend, int32_t dataSize, int32_t zeroSize, int32_t* status) { + auto spi = spiHandles->Get(handle); + if (!spi) { + *status = HAL_HANDLE_ERROR; + return; + } + + // todo: use the setlasterror out of range method for this if (dataSize < 0 || dataSize > 32) { *status = PARAMETER_OUT_OF_RANGE; hal::SetLastError( @@ -678,7 +675,7 @@ void HAL_SetSPIAutoTransmitData(HAL_SPIPort port, const uint8_t* dataToSend, std::scoped_lock lock(spiAutoMutex); // FPGA only has one auto SPI engine - if (port != spiAutoPort) { + if (spi->port != spiAutoPort) { *status = INCOMPATIBLE_STATE; return; } @@ -695,10 +692,16 @@ void HAL_SetSPIAutoTransmitData(HAL_SPIPort port, const uint8_t* dataToSend, spiSystem->writeAutoByteCount(config, status); } -void HAL_ForceSPIAutoRead(HAL_SPIPort port, int32_t* status) { +void HAL_ForceSPIAutoRead(HAL_SPIHandle handle, int32_t* status) { + auto spi = spiHandles->Get(handle); + if (!spi) { + *status = HAL_HANDLE_ERROR; + return; + } + std::scoped_lock lock(spiAutoMutex); // FPGA only has one auto SPI engine - if (port != spiAutoPort) { + if (spi->port != spiAutoPort) { *status = INCOMPATIBLE_STATE; return; } @@ -706,12 +709,18 @@ void HAL_ForceSPIAutoRead(HAL_SPIPort port, int32_t* status) { spiSystem->strobeAutoForceOne(status); } -int32_t HAL_ReadSPIAutoReceivedData(HAL_SPIPort port, uint32_t* buffer, +int32_t HAL_ReadSPIAutoReceivedData(HAL_SPIHandle handle, uint32_t* buffer, int32_t numToRead, double timeout, int32_t* status) { + auto spi = spiHandles->Get(handle); + if (!spi) { + *status = HAL_HANDLE_ERROR; + return 0; + } + std::scoped_lock lock(spiAutoMutex); // FPGA only has one auto SPI engine - if (port != spiAutoPort) { + if (spi->port != spiAutoPort) { *status = INCOMPATIBLE_STATE; return 0; } @@ -722,10 +731,16 @@ int32_t HAL_ReadSPIAutoReceivedData(HAL_SPIPort port, uint32_t* buffer, return numRemaining; } -int32_t HAL_GetSPIAutoDroppedCount(HAL_SPIPort port, int32_t* status) { +int32_t HAL_GetSPIAutoDroppedCount(HAL_SPIHandle handle, int32_t* status) { + auto spi = spiHandles->Get(handle); + if (!spi) { + *status = HAL_HANDLE_ERROR; + return 0; + } + std::scoped_lock lock(spiAutoMutex); // FPGA only has one auto SPI engine - if (port != spiAutoPort) { + if (spi->port != spiAutoPort) { *status = INCOMPATIBLE_STATE; return 0; } @@ -733,12 +748,18 @@ int32_t HAL_GetSPIAutoDroppedCount(HAL_SPIPort port, int32_t* status) { return spiSystem->readTransferSkippedFullCount(status); } -void HAL_ConfigureSPIAutoStall(HAL_SPIPort port, int32_t csToSclkTicks, +void HAL_ConfigureSPIAutoStall(HAL_SPIHandle handle, int32_t csToSclkTicks, int32_t stallTicks, int32_t pow2BytesPerRead, int32_t* status) { + auto spi = spiHandles->Get(handle); + if (!spi) { + *status = HAL_HANDLE_ERROR; + return; + } std::scoped_lock lock(spiAutoMutex); + // FPGA only has one auto SPI engine - if (port != spiAutoPort) { + if (spi->port != spiAutoPort) { *status = INCOMPATIBLE_STATE; return; } diff --git a/hal/src/main/native/include/hal/SPI.h b/hal/src/main/native/include/hal/SPI.h index 1f6c4c7647a..9b62cee398d 100644 --- a/hal/src/main/native/include/hal/SPI.h +++ b/hal/src/main/native/include/hal/SPI.h @@ -38,14 +38,13 @@ HAL_SPIHandle HAL_InitializeSPI(HAL_SPIPort port, int32_t* status); * This is a lower-level interface to the spi hardware giving you more control * over each transaction. * - * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 - * for MXP + * @param handle The SPI port handle. * @param dataToSend Buffer of data to send as part of the transaction. * @param dataReceived Buffer to read data into. * @param size Number of bytes to transfer. [0..7] * @return Number of bytes transferred, -1 for error */ -int32_t HAL_TransactionSPI(HAL_SPIPort port, const uint8_t* dataToSend, +int32_t HAL_TransactionSPI(HAL_SPIHandle handle, const uint8_t* dataToSend, uint8_t* dataReceived, int32_t size); /** @@ -53,13 +52,12 @@ int32_t HAL_TransactionSPI(HAL_SPIPort port, const uint8_t* dataToSend, * * Writes to a device and wait until the transaction is complete. * - * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 - * for MXP + * @param handle The SPI port handle. * @param dataToSend The data to write to the register on the device. * @param sendSize The number of bytes to be written * @return The number of bytes written. -1 for an error */ -int32_t HAL_WriteSPI(HAL_SPIPort port, const uint8_t* dataToSend, +int32_t HAL_WriteSPI(HAL_SPIHandle port, const uint8_t* dataToSend, int32_t sendSize); /** @@ -70,95 +68,86 @@ int32_t HAL_WriteSPI(HAL_SPIPort port, const uint8_t* dataToSend, * Most spi devices will require a register address to be written before they * begin returning data. * - * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for - * MXP + * @param handle The SPI port handle. * @param buffer A pointer to the array of bytes to store the data read from the * device. * @param count The number of bytes to read in the transaction. [1..7] * @return Number of bytes read. -1 for error. */ -int32_t HAL_ReadSPI(HAL_SPIPort port, uint8_t* buffer, int32_t count); +int32_t HAL_ReadSPI(HAL_SPIHandle handle, uint8_t* buffer, int32_t count); /** * Closes the SPI port. * - * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP + * @param handle The SPI port handle. */ -void HAL_CloseSPI(HAL_SPIPort port); +void HAL_CloseSPI(HAL_SPIHandle handle); /** * Sets the clock speed for the SPI bus. * - * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for - * MXP - * @param speed The speed in Hz (500KHz-10MHz) + * @param handle The SPI port handle. + * @param speed The speed in Hz (500KHz-10MHz) */ -void HAL_SetSPISpeed(HAL_SPIPort port, int32_t speed); +void HAL_SetSPISpeed(HAL_SPIHandle handle, int32_t speed); /** * Sets the SPI Mode. * - * @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 + * @param handle The SPI port handle. + * @param mode The SPI mode to use */ -void HAL_SetSPIMode(HAL_SPIPort port, HAL_SPIMode mode); +void HAL_SetSPIMode(HAL_SPIHandle handle, 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 - * @return The SPI mode currently set + * @param handle The SPI port handle. + * @return The SPI mode currently set */ -HAL_SPIMode HAL_GetSPIMode(HAL_SPIPort port); +HAL_SPIMode HAL_GetSPIMode(HAL_SPIHandle handle); /** * Sets the CS Active high for a SPI port. * - * @param[in] port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for - * MXP + * @param[in] handle The SPI port handle. * @param[out] status the error code, or 0 for success */ -void HAL_SetSPIChipSelectActiveHigh(HAL_SPIPort port, int32_t* status); +void HAL_SetSPIChipSelectActiveHigh(HAL_SPIHandle handle, int32_t* status); /** * Sets the CS Active low for a SPI port. * - * @param[in] port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 - * for MXP + * @param[in] handle The SPI port handle. * @param[out] status the error code, or 0 for success */ -void HAL_SetSPIChipSelectActiveLow(HAL_SPIPort port, int32_t* status); +void HAL_SetSPIChipSelectActiveLow(HAL_SPIHandle handle, int32_t* status); /** * Initializes the SPI automatic accumulator. * - * @param[in] port The number of the port to use. 0-3 for Onboard CS0-CS2, - * 4 for MXP. + * @param[in] handle The SPI port handle. * @param[in] bufferSize The accumulator buffer size. * @param[out] status the error code, or 0 for success */ -void HAL_InitSPIAuto(HAL_SPIPort port, int32_t bufferSize, int32_t* status); +void HAL_InitSPIAuto(HAL_SPIHandle handle, int32_t bufferSize, int32_t* status); /** * Frees an SPI automatic accumulator. * - * @param[in] port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 - * for MXP. + * @param[in] handle The SPI port handle. * @param[out] status the error code, or 0 for success */ -void HAL_FreeSPIAuto(HAL_SPIPort port, int32_t* status); +void HAL_FreeSPIAuto(HAL_SPIHandle handle, int32_t* status); /** * Sets the period for automatic SPI accumulation. * - * @param[in] port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 - * for MXP. + * @param[in] handle The SPI port handle. * @param[in] period The accumulation period (seconds). * @param[out] status the error code, or 0 for success */ -void HAL_StartSPIAutoRate(HAL_SPIPort port, double period, int32_t* status); +void HAL_StartSPIAutoRate(HAL_SPIHandle handle, double period, int32_t* status); /** * Starts the auto SPI accumulator on a specific trigger. @@ -166,8 +155,7 @@ void HAL_StartSPIAutoRate(HAL_SPIPort port, double period, int32_t* status); * Note that triggering on both rising and falling edges is a valid * configuration. * - * @param[in] port The number of the port to use. 0-3 for Onboard - * CS0-CS2, 4 for MXP. + * @param[in] handle The SPI port handle. * @param[in] digitalSourceHandle The trigger source to use (Either * HAL_AnalogTriggerHandle or HAL_DigitalHandle). * @param[in] analogTriggerType The analog trigger type, if the source is an @@ -176,7 +164,8 @@ void HAL_StartSPIAutoRate(HAL_SPIPort port, double period, int32_t* status); * @param[in] triggerFalling Trigger on the falling edge if true. * @param[out] status the error code, or 0 for success */ -void HAL_StartSPIAutoTrigger(HAL_SPIPort port, HAL_Handle digitalSourceHandle, +void HAL_StartSPIAutoTrigger(HAL_SPIHandle handle, + HAL_Handle digitalSourceHandle, HAL_AnalogTriggerType analogTriggerType, HAL_Bool triggerRising, HAL_Bool triggerFalling, int32_t* status); @@ -184,35 +173,32 @@ void HAL_StartSPIAutoTrigger(HAL_SPIPort port, HAL_Handle digitalSourceHandle, /** * Stops an automatic SPI accumulation. * - * @param[in] port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 - * for MXP. + * @param[in] handle The SPI port handle. * @param[out] status the error code, or 0 for success */ -void HAL_StopSPIAuto(HAL_SPIPort port, int32_t* status); +void HAL_StopSPIAuto(HAL_SPIHandle handle, int32_t* status); /** * Sets the data to be transmitted to the device to initiate a read. * - * @param[in] port The number of the port to use. 0-3 for Onboard CS0-CS2, - * 4 for MXP. + * @param[in] handle The SPI port handle. * @param[in] dataToSend Pointer to the data to send (Gets copied for continue * use, so no need to keep alive). * @param[in] dataSize The length of the data to send. * @param[in] zeroSize The number of zeros to send after the data. * @param[out] status the error code, or 0 for success */ -void HAL_SetSPIAutoTransmitData(HAL_SPIPort port, const uint8_t* dataToSend, +void HAL_SetSPIAutoTransmitData(HAL_SPIHandle handle, const uint8_t* dataToSend, int32_t dataSize, int32_t zeroSize, int32_t* status); /** * Immediately forces an SPI read to happen. * - * @param[in] port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 - * for MXP. + * @param[in] handle The SPI port handle. * @param[out] status the error code, or 0 for success */ -void HAL_ForceSPIAutoRead(HAL_SPIPort port, int32_t* status); +void HAL_ForceSPIAutoRead(HAL_SPIHandle handle, int32_t* status); /** * Reads data received by the SPI accumulator. Each received data sequence @@ -221,40 +207,37 @@ void HAL_ForceSPIAutoRead(HAL_SPIPort port, int32_t* status); * sequence is the same as the combined dataSize + zeroSize set in * HAL_SetSPIAutoTransmitData. * - * @param[in] port The number of the port to use. 0-3 for Onboard CS0-CS2, - * 4 for MXP. + * @param[in] handle The SPI port handle. * @param[out] buffer The buffer to store the data into. * @param[in] numToRead The number of words to read. * @param[in] timeout The read timeout (in seconds). * @param[out] status the error code, or 0 for success * @return The number of words actually read. */ -int32_t HAL_ReadSPIAutoReceivedData(HAL_SPIPort port, uint32_t* buffer, +int32_t HAL_ReadSPIAutoReceivedData(HAL_SPIHandle handle, uint32_t* buffer, int32_t numToRead, double timeout, int32_t* status); /** * Gets the count of how many SPI accumulations have been missed. * - * @param[in] port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 - * for MXP. + * @param[in] handle The SPI port handle. * @param[out] status the error code, or 0 for success * @return The number of missed accumulations. */ -int32_t HAL_GetSPIAutoDroppedCount(HAL_SPIPort port, int32_t* status); +int32_t HAL_GetSPIAutoDroppedCount(HAL_SPIHandle handle, int32_t* status); /** * Configure the Auto SPI Stall time between reads. * - * @param[in] port The number of the port to use. 0-3 for Onboard - * CS0-CS2, 4 for MXP. + * @param[in] handle The SPI port handle. * @param[in] csToSclkTicks the number of ticks to wait before asserting the * cs pin * @param[in] stallTicks the number of ticks to stall for * @param[in] pow2BytesPerRead the number of bytes to read before stalling * @param[out] status the error code, or 0 for success */ -void HAL_ConfigureSPIAutoStall(HAL_SPIPort port, int32_t csToSclkTicks, +void HAL_ConfigureSPIAutoStall(HAL_SPIHandle handle, int32_t csToSclkTicks, int32_t stallTicks, int32_t pow2BytesPerRead, int32_t* status); diff --git a/hal/src/main/native/sim/SPI.cpp b/hal/src/main/native/sim/SPI.cpp index ecc841381b8..3987587b42e 100644 --- a/hal/src/main/native/sim/SPI.cpp +++ b/hal/src/main/native/sim/SPI.cpp @@ -6,66 +6,128 @@ #include "HALInitializer.h" #include "mockdata/SPIDataInternal.h" - +#include "hal/handles/IndexedHandleResource.h" +#include "HALInternal.h" +#include using namespace hal; +namespace { +struct SPI { + HAL_SPIPort port; +}; +} // namespace + +static constexpr int32_t kSpiMaxHandles = 5; + +typedef IndexedHandleResource + SPIHandleResource; + +static SPIHandleResource* spiHandles; + namespace hal::init { -void InitializeSPI() {} +void InitializeSPI() { + static SPIHandleResource sH; + spiHandles = &sH; +} } // namespace hal::init extern "C" { HAL_SPIHandle HAL_InitializeSPI(HAL_SPIPort port, int32_t* status) { hal::init::CheckInit(); + if (port < 0 || port >= kSpiMaxHandles) { + *status = PARAMETER_OUT_OF_RANGE; + hal::SetLastError( + status, fmt::format("SPI port must be between 0 and {}. Requested {}", + kSpiMaxHandles, static_cast(port))); + return HAL_kInvalidHandle; + } + + HAL_SPIHandle hal_handle; + auto spi = + spiHandles->Allocate(static_cast(port), &hal_handle, status); + + if (*status != 0) { + return HAL_kInvalidHandle; + } + SimSPIData[port].initialized = true; - // TODO: deal with this - return 0; + spi->port = port; + return hal_handle; } -int32_t HAL_TransactionSPI(HAL_SPIPort port, const uint8_t* dataToSend, + +int32_t HAL_TransactionSPI(HAL_SPIHandle handle, const uint8_t* dataToSend, uint8_t* dataReceived, int32_t size) { - return SimSPIData[port].Transaction(dataToSend, dataReceived, size); + auto spi = spiHandles->Get(handle); + if (!spi) { + return -1; + } + return SimSPIData[spi->port].Transaction(dataToSend, dataReceived, size); } -int32_t HAL_WriteSPI(HAL_SPIPort port, const uint8_t* dataToSend, + +int32_t HAL_WriteSPI(HAL_SPIHandle handle, const uint8_t* dataToSend, int32_t sendSize) { - return SimSPIData[port].Write(dataToSend, sendSize); + auto spi = spiHandles->Get(handle); + if (!spi) { + return -1; + } + return SimSPIData[spi->port].Write(dataToSend, sendSize); } -int32_t HAL_ReadSPI(HAL_SPIPort port, uint8_t* buffer, int32_t count) { - return SimSPIData[port].Read(buffer, count); +int32_t HAL_ReadSPI(HAL_SPIHandle handle, uint8_t* buffer, int32_t count) { + auto spi = spiHandles->Get(handle); + if (!spi) { + return -1; + } + return SimSPIData[spi->port].Read(buffer, count); } -void HAL_CloseSPI(HAL_SPIPort port) { - SimSPIData[port].initialized = false; +void HAL_CloseSPI(HAL_SPIHandle handle) { + auto spi = spiHandles->Get(handle); + if (!spi) { + return; + } + SimSPIData[spi->port].initialized = false; + spiHandles->Free(handle); } -void HAL_SetSPISpeed(HAL_SPIPort port, int32_t speed) {} -void HAL_SetSPIMode(HAL_SPIPort port, HAL_SPIMode mode) {} -HAL_SPIMode HAL_GetSPIMode(HAL_SPIPort port) { +void HAL_SetSPISpeed(HAL_SPIHandle handle, int32_t speed) {} +void HAL_SetSPIMode(HAL_SPIHandle handle, HAL_SPIMode mode) {} +HAL_SPIMode HAL_GetSPIMode(HAL_SPIHandle port) { return HAL_SPI_kMode0; } -void HAL_SetSPIChipSelectActiveHigh(HAL_SPIPort port, int32_t* status) {} -void HAL_SetSPIChipSelectActiveLow(HAL_SPIPort port, int32_t* status) {} +void HAL_SetSPIChipSelectActiveHigh(HAL_SPIHandle handle, int32_t* status) {} +void HAL_SetSPIChipSelectActiveLow(HAL_SPIHandle handle, int32_t* status) {} -void HAL_InitSPIAuto(HAL_SPIPort port, int32_t bufferSize, int32_t* status) {} -void HAL_FreeSPIAuto(HAL_SPIPort port, int32_t* status) {} -void HAL_StartSPIAutoRate(HAL_SPIPort port, double period, int32_t* status) {} -void HAL_StartSPIAutoTrigger(HAL_SPIPort port, HAL_Handle digitalSourceHandle, +void HAL_InitSPIAuto(HAL_SPIHandle handle, int32_t bufferSize, + int32_t* status) {} +void HAL_FreeSPIAuto(HAL_SPIHandle handle, int32_t* status) {} +void HAL_StartSPIAutoRate(HAL_SPIHandle handle, double period, + int32_t* status) {} +void HAL_StartSPIAutoTrigger(HAL_SPIHandle handle, + HAL_Handle digitalSourceHandle, HAL_AnalogTriggerType analogTriggerType, HAL_Bool triggerRising, HAL_Bool triggerFalling, int32_t* status) {} -void HAL_StopSPIAuto(HAL_SPIPort port, int32_t* status) {} -void HAL_SetSPIAutoTransmitData(HAL_SPIPort port, const uint8_t* dataToSend, +void HAL_StopSPIAuto(HAL_SPIHandle handle, int32_t* status) {} +void HAL_SetSPIAutoTransmitData(HAL_SPIHandle handle, const uint8_t* dataToSend, int32_t dataSize, int32_t zeroSize, int32_t* status) {} -void HAL_ForceSPIAutoRead(HAL_SPIPort port, int32_t* status) {} -int32_t HAL_ReadSPIAutoReceivedData(HAL_SPIPort port, uint32_t* buffer, +void HAL_ForceSPIAutoRead(HAL_SPIHandle handle, int32_t* status) {} +int32_t HAL_ReadSPIAutoReceivedData(HAL_SPIHandle handle, uint32_t* buffer, int32_t numToRead, double timeout, int32_t* status) { - return SimSPIData[port].ReadAutoReceivedData(buffer, numToRead, timeout, - status); + auto spi = spiHandles->Get(handle); + if (!spi) { + *status = HAL_HANDLE_ERROR; + return 0; + } + return SimSPIData[spi->port].ReadAutoReceivedData(buffer, numToRead, timeout, + status); } -int32_t HAL_GetSPIAutoDroppedCount(HAL_SPIPort port, int32_t* status) { +int32_t HAL_GetSPIAutoDroppedCount(HAL_SPIHandle handle, int32_t* status) { return 0; } -void HAL_ConfigureSPIAutoStall(HAL_SPIPort port, int32_t csToSclkTicks, +void HAL_ConfigureSPIAutoStall(HAL_SPIHandle handle, int32_t csToSclkTicks, int32_t stallTicks, int32_t pow2BytesPerRead, int32_t* status) {} diff --git a/wpilibc/src/main/native/cpp/SPI.cpp b/wpilibc/src/main/native/cpp/SPI.cpp index 88f8f1a9fde..259637546b9 100644 --- a/wpilibc/src/main/native/cpp/SPI.cpp +++ b/wpilibc/src/main/native/cpp/SPI.cpp @@ -157,9 +157,9 @@ void SPI::Accumulator::Update() { SPI::SPI(Port port) : m_port(static_cast(port)) { int32_t status = 0; - HAL_InitializeSPI(m_port, &status); - HAL_SetSPIMode(m_port, m_mode); + m_handle = HAL_InitializeSPI(m_port, &status); FRC_CheckErrorStatus(status, "Port {}", static_cast(m_port)); + HAL_SetSPIMode(m_port, m_mode); HAL_Report(HALUsageReporting::kResourceType_SPI, static_cast(port) + 1); @@ -203,7 +203,7 @@ int SPI::Read(bool initiate, uint8_t* dataReceived, int size) { if (initiate) { wpi::SmallVector dataToSend; dataToSend.resize(size); - retVal = HAL_TransactionSPI(m_port, dataToSend.data(), dataReceived, size); + retVal = HAL_TransactionSPI(m_handle, dataToSend.data(), dataReceived, size); } else { retVal = HAL_ReadSPI(m_port, dataReceived, size); } diff --git a/wpilibc/src/main/native/include/frc/SPI.h b/wpilibc/src/main/native/include/frc/SPI.h index 8f7f87349b4..a5ce5283a6c 100644 --- a/wpilibc/src/main/native/include/frc/SPI.h +++ b/wpilibc/src/main/native/include/frc/SPI.h @@ -357,7 +357,8 @@ class SPI { double GetAccumulatorIntegratedAverage() const; protected: - hal::Handle m_port; + HAL_SPIPort m_port; + hal::Handle m_handle; HAL_SPIMode m_mode = HAL_SPIMode::HAL_SPI_kMode0; private: