Files
MotorDriver.Research/ODrive-fw-v0.5.6/Firmware/Drivers/STM32/stm32_spi_arbiter.hpp
T
2025-05-13 01:34:53 +03:00

94 lines
2.9 KiB
C++

#ifndef __STM32_SPI_ARBITER_HPP
#define __STM32_SPI_ARBITER_HPP
#include "stm32_gpio.hpp"
#include <spi.h>
class Stm32SpiArbiter {
public:
struct SpiTask {
SPI_InitTypeDef config;
Stm32Gpio ncs_gpio;
const uint8_t* tx_buf;
uint8_t* rx_buf;
size_t length;
void (*on_complete)(void*, bool);
void* on_complete_ctx;
bool is_in_use = false;
struct SpiTask* next;
};
Stm32SpiArbiter(SPI_HandleTypeDef* hspi): hspi_(hspi) {}
/**
* Reserves the task for the caller if it's not in use currently.
*
* This can be used by the caller to ensure that the task structure is not
* overwritten while it's in use in a preceding transfer.
*
* Example:
*
* if (acquire_task(&task)) {
* transfer_async(&task)
* }
*
* A call to release_task() makes the task available for use again.
*/
static bool acquire_task(SpiTask* task);
/**
* Releases the task so that the next call to `acquire_task()` returns true.
* This should usually be called inside the on_complete() callback after
* the rx buffer has been processed.
*/
static void release_task(SpiTask* task);
/**
* @brief Enqueues a non-blocking transfer.
*
* Once the transfer completes, fails or is aborted, the callback is invoked.
*
* This function is thread-safe with respect to all other public functions
* of this class.
*
* @param task: Contains all configuration data for this transfer.
* The struct pointed to by this argument must remain valid and
* unmodified until the completion callback is invoked.
*/
void transfer_async(SpiTask* task);
/**
* @brief Executes a blocking transfer.
*
* If the SPI is busy this function waits until it becomes available or
* the specified timeout passes, whichever comes first.
*
* Returns true on successful transfer or false otherwise.
*
* This function is thread-safe with respect to all other public functions
* of this class.
*
* @param config: The SPI configuration to apply for this transfer.
* @param ncs_gpio: The active low GPIO to actuate during this transfer.
* @param tx_buf: Buffer for the outgoing data to be sent. Can be null unless
* rx_buf is null too.
* @param rx_buf: Buffer for the incoming data to be sent. Can be null unless
* tx_buf is null too.
*/
bool transfer(SPI_InitTypeDef config, Stm32Gpio ncs_gpio, const uint8_t* tx_buf, uint8_t* rx_buf, size_t length, uint32_t timeout_ms);
/**
* @brief Completion method to be called from HAL_SPI_TxCpltCallback,
* HAL_SPI_RxCpltCallback and HAL_SPI_TxRxCpltCallback.
*/
void on_complete();
private:
bool start();
SPI_HandleTypeDef* hspi_;
SpiTask* task_list_ = nullptr;
};
#endif // __STM32_SPI_ARBITER_HPP