Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 25 additions & 7 deletions libraries/SPI/src/SPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,41 +42,59 @@ SPIClass::SPIClass(uint32_t mosi, uint32_t miso, uint32_t sclk, uint32_t ssel)
_spi.pin_mosi = digitalPinToPinName(mosi);
_spi.pin_sclk = digitalPinToPinName(sclk);
_spi.pin_ssel = digitalPinToPinName(ssel);

// Default configuration
_spi.duplex = true;
_spi.direction = SPI_DIRECTION_2LINES;
_spi.mode = SPI_MODE_MASTER;
}

/**
* @brief Initialize the SPI instance.
* @param device: device mode (optional), SPI_MASTER or SPI_SLAVE. Default is master.
*/
void SPIClass::begin(SPIDeviceMode device)
bool SPIClass::begin(SPIDeviceMode device)
{
_spi.handle.State = HAL_SPI_STATE_RESET;
_spiSettings = SPISettings();
_spiSettings.deviceMode = device;
spi_init(&_spi, _spiSettings.clockFreq, _spiSettings.dataMode,
auto error = spi_init(&_spi, _spiSettings.clockFreq, _spiSettings.dataMode,
_spiSettings.bitOrder, _spiSettings.deviceMode);
if (error != SPI_OK) {
Serial.printf("SPI init error: %d\n", error);
}

init = error == SPI_OK;
return init;
}

/**
* @brief This function should be used to configure the SPI instance in case you
* don't use the default parameters set by the begin() function.
* @param settings: SPI settings(clock speed, bit order, data mode, device mode).
*/
void SPIClass::beginTransaction(SPISettings settings)
bool SPIClass::beginTransaction(SPISettings settings)
{
if (_spiSettings != settings) {
_spiSettings = settings;
spi_init(&_spi, _spiSettings.clockFreq, _spiSettings.dataMode,
auto error = spi_init(&_spi, _spiSettings.clockFreq,
_spiSettings.dataMode,
_spiSettings.bitOrder, _spiSettings.deviceMode);
if (error != SPI_OK) {
Serial.printf("SPI init error: %d\n", error);
}
init = error == SPI_OK;
}

return init;
}

/**
* @brief End the transaction after beginTransaction usage
*/
void SPIClass::endTransaction(void)
{

// Nothing to do here
}

/**
Expand Down Expand Up @@ -211,9 +229,9 @@ void SPIClass::transfer(void *buf, size_t count, bool skipReceive)
* the SPI transfer. If NULL, the received data will be discarded.
* @param count: number of bytes to send/receive.
*/
void SPIClass::transfer(const void *tx_buf, void *rx_buf, size_t count)
spi_status_e SPIClass::transfer(const void *tx_buf, void *rx_buf, size_t count)
{
spi_transfer(&_spi, ((const uint8_t *)tx_buf), ((uint8_t *)rx_buf), count);
return spi_transfer(&_spi, ((const uint8_t *)tx_buf), ((uint8_t *)rx_buf), count);
}


Expand Down
21 changes: 18 additions & 3 deletions libraries/SPI/src/SPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,27 @@ class SPIClass {
_spi.pin_ssel = (ssel);
};

void begin(SPIDeviceMode device = SPI_MASTER);
void setDirection(uint32_t direction)
{
_spi.direction = direction;
if (direction == SPI_DIRECTION_1LINE)
_spi.duplex = false;
else
_spi.duplex = true;
};

void setDeviceMode(SPIDeviceMode deviceMode)
{
_spiSettings.deviceMode = deviceMode;
};

bool begin(SPIDeviceMode device = SPI_MASTER);
void end(void);

/* This function should be used to configure the SPI instance in case you
* don't use default parameters.
*/
void beginTransaction(SPISettings settings);
bool beginTransaction(SPISettings settings);
void endTransaction(void);

/* Transfer functions: must be called after initialization of the SPI
Expand All @@ -145,7 +159,7 @@ class SPIClass {
/* Expand SPI API
* https://github.com/arduino/ArduinoCore-API/discussions/189
*/
void transfer(const void *tx_buf, void *rx_buf, size_t count);
spi_status_e transfer(const void *tx_buf, void *rx_buf, size_t count);

/* These methods are deprecated and kept for compatibility.
* Use SPISettings with SPI.beginTransaction() to configure SPI parameters.
Expand Down Expand Up @@ -181,6 +195,7 @@ class SPIClass {
protected:
// spi instance
spi_t _spi;
bool init;

private:
/* Current SPISettings */
Expand Down
57 changes: 42 additions & 15 deletions libraries/SPI/src/utility/spi_com.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,12 +206,15 @@ static uint32_t compute_disable_delay(spi_t *obj)
* @param device : spi device mode: master or slave
* @retval None
*/
void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb, SPIDeviceMode device)
spi_status_e spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb, SPIDeviceMode device)
{
if (obj == NULL) {
return;
return SPI_ERROR;
}

// Set the device mode before any other initialization
obj->mode = device;

SPI_HandleTypeDef *handle = &(obj->handle);
uint32_t spi_freq = 0;
uint32_t pull = 0;
Expand All @@ -226,9 +229,11 @@ void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb, SPIDeviceMo
SPI_TypeDef *spi_ssel = pinmap_peripheral(obj->pin_ssel, PinMap_SPI_SSEL);

/* Pins MOSI/MISO/SCLK must not be NP. ssel can be NP. */
if (spi_mosi == NP || spi_miso == NP || spi_sclk == NP) {
core_debug("ERROR: at least one SPI pin has no peripheral\n");
return;
if (spi_mosi == NP || spi_miso == NP || spi_sclk == NP || spi_ssel == NP) {
if (spi_miso == NP && obj->duplex) {
core_debug("ERROR: at least one SPI pin has no peripheral\n");
return SPI_ERROR;
}
}

SPI_TypeDef *spi_data = pinmap_merge_peripheral(spi_mosi, spi_miso);
Expand All @@ -239,27 +244,31 @@ void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb, SPIDeviceMo
// Are all pins connected to the same SPI instance?
if (spi_data == NP || spi_cntl == NP || obj->spi == NP) {
core_debug("ERROR: SPI pins mismatch\n");
return;
return SPI_ERROR;
}
#if defined(SUBGHZSPI_BASE)
} else {
if (obj->pin_mosi != NC || obj->pin_miso != NC || obj->pin_sclk != NC || obj->pin_ssel != NC) {
core_debug("ERROR: SUBGHZ_SPI cannot define custom pins\n");
return;
return SPI_ERROR;
}
}
#endif

// Configure the SPI pins
if (obj->pin_ssel != NC) {
handle->Init.NSS = SPI_NSS_HARD_OUTPUT;
if (obj->mode == SPI_MODE_SLAVE) {
handle->Init.NSS = SPI_NSS_HARD_INPUT;
} else {
handle->Init.NSS = SPI_NSS_HARD_OUTPUT;
}
} else {
handle->Init.NSS = SPI_NSS_SOFT;
}

/* Fill default value */
handle->Instance = obj->spi;
handle->Init.Mode = (device == SPI_MASTER) ? SPI_MODE_MASTER : SPI_MODE_SLAVE;
handle->Instance = obj->spi;
handle->Init.Mode = obj->mode;

spi_freq = spi_getClkFreqInst(obj->spi);
/* For SUBGHZSPI, 'SPI_BAUDRATEPRESCALER_*' == 'SUBGHZSPI_BAUDRATEPRESCALER_*' */
Expand Down Expand Up @@ -290,7 +299,7 @@ void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb, SPIDeviceMo
obj->disable_delay = compute_disable_delay(obj);
#endif

handle->Init.Direction = SPI_DIRECTION_2LINES;
handle->Init.Direction = obj->direction;

if ((mode == SPI_MODE0) || (mode == SPI_MODE2)) {
handle->Init.CLKPhase = SPI_PHASE_1EDGE;
Expand Down Expand Up @@ -325,9 +334,22 @@ void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb, SPIDeviceMo
#if defined(SUBGHZSPI_BASE)
if (handle->Instance != SUBGHZSPI) {
#endif
/* Configure SPI GPIO pins */
pinmap_pinout(obj->pin_mosi, PinMap_SPI_MOSI);
pinmap_pinout(obj->pin_miso, PinMap_SPI_MISO);
/* Configure SPI GPIO pins based on device mode and duplex setting */
if (obj->mode == SPI_MODE_MASTER) {
/* Master mode: configure MOSI for output */
pinmap_pinout(obj->pin_mosi, PinMap_SPI_MOSI);
/* Configure MISO for input if duplex is enabled */
if (obj->duplex) {
pinmap_pinout(obj->pin_miso, PinMap_SPI_MISO);
}
} else {
/* Slave mode: configure MISO for output */
pinmap_pinout(obj->pin_miso, PinMap_SPI_MISO);
/* Configure MOSI for input if duplex is enabled */
if (obj->duplex) {
pinmap_pinout(obj->pin_mosi, PinMap_SPI_MOSI);
}
}
pinmap_pinout(obj->pin_sclk, PinMap_SPI_SCLK);
/*
* According the STM32 Datasheet for SPI peripheral we need to PULLDOWN
Expand Down Expand Up @@ -396,10 +418,15 @@ void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb, SPIDeviceMo
}
#endif

HAL_SPI_Init(handle);
HAL_StatusTypeDef status = HAL_SPI_Init(handle);
if (status != HAL_OK) {
core_debug("ERROR: HAL_SPI_Init failed\n");
return SPI_ERROR;
}

/* In order to set correctly the SPI polarity we need to enable the peripheral */
__HAL_SPI_ENABLE(handle);
return SPI_OK;
}

/**
Expand Down
6 changes: 4 additions & 2 deletions libraries/SPI/src/utility/spi_com.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ struct spi_s {
PinName pin_mosi;
PinName pin_sclk;
PinName pin_ssel;
bool duplex;
uint32_t direction;
uint32_t mode;
#if defined(SPI_IFCR_EOTC)
// Delay before disabling SPI.
// See https://github.com/stm32duino/Arduino_Core_STM32/issues/1294
Expand All @@ -39,7 +42,6 @@ struct spi_s {

typedef struct spi_s spi_t;


///@brief specifies the SPI speed bus in HZ.
#define SPI_SPEED_CLOCK_DEFAULT 4000000

Expand Down Expand Up @@ -88,7 +90,7 @@ typedef enum {
} spi_status_e;

/* Exported functions ------------------------------------------------------- */
void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb, SPIDeviceMode device);
spi_status_e spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb, SPIDeviceMode device_mode);
void spi_deinit(spi_t *obj);
spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buffer, uint16_t len);
uint32_t spi_getClkFreq(spi_t *obj);
Expand Down