Skip to content

[breaking] SPI library rework #2171

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Nov 15, 2023
Merged
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
36 changes: 17 additions & 19 deletions CI/build/examples/BareMinimum/BareMinimum.ino
Original file line number Diff line number Diff line change
@@ -19,38 +19,37 @@
/* ----------------------------------------------------------------------
Defines each of the tests performed
------------------------------------------------------------------- */
#define MAX_BLOCKSIZE 2
#define DELTA (0.0001f)
#define MAX_BLOCKSIZE 2
#define DELTA (0.0001f)
/* ----------------------------------------------------------------------
Test input data for Floating point sin_cos example for 32-blockSize
Generated by the MATLAB randn() function
------------------------------------------------------------------- */
const float32_t testInput_f32[MAX_BLOCKSIZE] =
{
-1.244916875853235400, -4.793533929171324800
const float32_t testInput_f32[MAX_BLOCKSIZE] = {
-1.244916875853235400, -4.793533929171324800
};
const float32_t testRefOutput_f32 = 1.000000000;
/* ----------------------------------------------------------------------
Declare Global variables
------------------------------------------------------------------- */
uint32_t blockSize = 2;
float32_t testOutput;
float32_t cosOutput;
float32_t sinOutput;
float32_t cosSquareOutput;
float32_t sinSquareOutput;
float32_t testOutput;
float32_t cosOutput;
float32_t sinOutput;
float32_t cosSquareOutput;
float32_t sinSquareOutput;
/* ----------------------------------------------------------------------
Max magnitude FFT Bin test
------------------------------------------------------------------- */
arm_status status;
/* CMSIS_DSP */

#ifndef USER_BTN
#define USER_BTN 2
#define USER_BTN 2
#endif

#ifndef LED_BUILTIN
#define LED_BUILTIN 13
#define LED_BUILTIN 13
#endif

#ifndef PIN_SERIAL_RX
@@ -72,8 +71,7 @@ SoftwareSerial swSerial(10, 11);

void setup() {
// Serial HW & SW
#if (!defined(USBD_USE_CDC) && !defined(DISABLE_GENERIC_SERIALUSB)) &&\
(!defined(VIRTIOCON) && !defined(DISABLE_GENERIC_SERIALVIRTIO))
#if (!defined(USBD_USE_CDC) && !defined(DISABLE_GENERIC_SERIALUSB)) && (!defined(VIRTIOCON) && !defined(DISABLE_GENERIC_SERIALVIRTIO))
Serial.setRx(PIN_SERIAL_RX);
Serial.setTx(digitalPinToPinName(PIN_SERIAL_TX));
#endif
@@ -92,7 +90,7 @@ void setup() {

// EEPROM
byte value = EEPROM.read(0x01);
EEPROM.write(EEPROM.length()-1, value);
EEPROM.write(EEPROM.length() - 1, value);

#ifndef STM32MP1xx
// IWDG
@@ -111,13 +109,13 @@ void setup() {
#endif

// SPI
SPISettings settings(SPI_SPEED_CLOCK_DEFAULT, MSBFIRST, SPI_MODE_0);
SPISettings settings(SPI_SPEED_CLOCK_DEFAULT, MSBFIRST, SPI_MODE0);
SPI.setMISO(PIN_SPI_MISO);
SPI.setMOSI(PIN_SPI_MOSI);
SPI.setSCLK(PIN_SPI_SCK);
SPI.setSSEL(digitalPinToPinName(PIN_SPI_SS));
SPI.begin(PIN_SPI_SS);
SPI.beginTransaction(1, settings);
SPI.begin();
SPI.beginTransaction(settings);
SPI.endTransaction();
SPI.transfer(1);
SPI.end();
@@ -146,7 +144,7 @@ void setup() {
diff = fabsf(testRefOutput_f32 - testOutput);
/* Comparison of sin_cos value with reference */
status = (diff > DELTA) ? ARM_MATH_TEST_FAILURE : ARM_MATH_SUCCESS;
if ( status == ARM_MATH_TEST_FAILURE) {
if (status == ARM_MATH_TEST_FAILURE) {
break;
}
}
93 changes: 43 additions & 50 deletions libraries/SPI/README.md
Original file line number Diff line number Diff line change
@@ -1,70 +1,63 @@
## SPI

STM32 SPI library has been modified with the possibility to manage several CS pins without to stop the SPI interface.
STM32 SPI library has been modified with the possibility to manage hardware CS pin linked to the SPI peripheral.
_We do not describe here the [SPI Arduino API](https://www.arduino.cc/en/Reference/SPI) but the functionalities added._

We give to the user 3 possibilities about the management of the CS pin:
1. the CS pin is managed directly by the user code before to transfer the data (like the Arduino SPI library)
2. the user gives the CS pin number to the library API and the library manages itself the CS pin (see example below)
3. the user uses a hardware CS pin linked to the SPI peripheral
User have 2 possibilities about the management of the CS pin:
* the CS pin is managed directly by the user code before to transfer the data (like the Arduino SPI library)
* the user uses a hardware CS pin linked to the SPI peripheral

### New API functions
### New SPISetting parameter

* **`SPIClass::SPIClass(uint8_t mosi, uint8_t miso, uint8_t sclk, uint8_t ssel)`**: alternative class constructor
_Params_ SPI mosi pin
_Params_ SPI miso pin
_Params_ SPI sclk pin
_Params_ (optional) SPI ssel pin. This pin must be an hardware CS pin. If you configure this pin, the chip select will be managed by the SPI peripheral. Do not use API functions with CS pin in parameter.
* `noReceive`: value can be `SPI_TRANSMITRECEIVE` or `SPI_TRANSMITONLY`. It allows to skip receive data after transmitting. Default `SPI_TRANSMITRECEIVE`.

* **`void SPIClass::begin(uint8_t _pin)`**: initialize the SPI interface and add a CS pin
_Params_ spi CS pin to be managed by the SPI library
### New API functions

* **`void beginTransaction(uint8_t pin, SPISettings settings)`**: allows to configure the SPI with other parameter. These new parameter are saved this an associated CS pin.
_Params_ SPI CS pin to be managed by the SPI library
_Params_ SPI settings
* `SPIClass::SPIClass(uint8_t mosi, uint8_t miso, uint8_t sclk, uint8_t ssel)`: alternative class constructor
_Params_ SPI `mosi` pin
_Params_ SPI `miso` pin
_Params_ SPI `sclk` pin
_Params_ (optional) SPI `ssel` pin. This pin must be an hardware CS pin. If you configure this pin, the chip select will be managed by the SPI peripheral.

* **`void endTransaction(uint8_t pin)`**: removes a CS pin and the SPI settings associated
_Params_ SPI CS pin managed by the SPI library
* `SPI_HandleTypeDef *getHandle(void)`: Could be used to mix Arduino API and STM32Cube HAL API (ex: DMA). **Use at your own risk.**

**_Note 1_** The following functions must be called after initialization of the SPI instance with `begin()` or `beginTransaction()`.
If you have several device to manage, you can call `beginTransaction()` several time with different CS pin in parameter.
Then you can call the following functions with different CS pin without call again `beginTransaction()` (until you call `end()` or `endTransaction()`).

**_Note 2_** If the mode is set to `SPI_CONTINUE`, the CS pin is kept enabled. Be careful in case you use several CS pin.
##### Example

* **`byte transfer(uint8_t pin, uint8_t _data, SPITransferMode _mode = SPI_LAST)`**: write/read one byte
_Params_ SPI CS pin managed by the SPI library
_Params_ data to write
_Params_ (optional) if `SPI_LAST` CS pin is reset, `SPI_CONTINUE` the CS pin is kept enabled.
_Return_ byte received
This is an example of the use of the hardware CS pin linked to the SPI peripheral:

* **`uint16_t transfer16(uint8_t pin, uint16_t _data, SPITransferMode _mode = SPI_LAST)`**: write/read half-word
_Params_ SPI CS pin managed by the SPI library
_Params_ 16bits data to write
_Params_ (optional) if `SPI_LAST` CS pin is reset, `SPI_CONTINUE` the CS pin is kept enabled.
_Return_ 16bits data received
```C++
#include <SPI.h>
// MOSI MISO SCLK SSEL
SPIClass SPI_3(PC12, PC11, PC10, PC9);

void setup() {
SPI_3.begin(); // Enable the SPI_3 instance with default SPISsettings
SPI_3.beginTransaction(settings); // Configure the SPI_3 instance with other settings
SPI_3.transfer(0x52); // Transfers data to the first device
SPI_3.end() //SPI_3 instance is disabled
}
```
* **`void transfer(uint8_t pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST)`**: write/read several bytes. Only one buffer used to write and read the data
_Params_ SPI CS pin managed by the SPI library
_Params_ pointer to data to write. The data will be replaced by the data read.
_Params_ number of data to write/read.
_Params_ (optional) if `SPI_LAST` CS pin is reset, `SPI_CONTINUE` the CS pin is kept enabled.
#### Change default `SPI` instance pins
It is also possible to change the default pins used by the `SPI` instance using above API:
* **`void transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST)`**: write/read several bytes. One buffer for the output data and one for the input data
_Params_ SPI CS pin managed by the SPI library
_Params_ pointer to data to write.
_Params_ pointer where to store the data read.
_Params_ number of data to write/read.
_Params_ (optional) if `SPI_LAST` CS pin is reset, `SPI_CONTINUE` the CS pin is kept enabled.
[[/img/Warning-icon.png|alt="Warning"]] **Have to be called before `begin()`.**
### Example
* `void setMISO(uint32_t miso)`
* `void setMOSI(uint32_t mosi)`
* `void setSCLK(uint32_t sclk)`
* `void setSSEL(uint32_t ssel)`
* `void setMISO(PinName miso)`
* `void setMOSI(PinName mosi)`
* `void setSCLK(PinName sclk)`
* `void setSSEL(PinName ssel)`
This is an example of the use of the CS pin management:
**_Note 1_** Using `setSSEL()` allows to enable hardware CS pin management linked to the SPI peripheral.
##### Example:
```C++
SPI.begin(2); //Enables the SPI instance with default settings and attaches the CS pin
SPI.beginTransaction(1, settings); //Attaches another CS pin and configure the SPI instance with other settings
SPI.transfer(1, 0x52); //Transfers data to the first device
SPI.transfer(2, 0xA4); //Transfers data to the second device. The SPI instance is configured with the right settings
SPI.end() //SPI instance is disabled
SPI.setMISO(PC_4); // using pin name PY_n
SPI.setMOSI(PC2); // using pin number PYn
SPI.begin(2);
```
359 changes: 70 additions & 289 deletions libraries/SPI/src/SPI.cpp

Large diffs are not rendered by default.

302 changes: 117 additions & 185 deletions libraries/SPI/src/SPI.h
Original file line number Diff line number Diff line change
@@ -38,76 +38,115 @@ extern "C" {
#define SPI_CLOCK_DIV64 64
#define SPI_CLOCK_DIV128 128

// SPI mode parameters for SPISettings
#define SPI_MODE0 0x00
#define SPI_MODE1 0x01
#define SPI_MODE2 0x02
#define SPI_MODE3 0x03

#define SPI_TRANSMITRECEIVE 0x0
#define SPI_TRANSMITONLY 0x1

// Transfer mode
enum SPITransferMode {
SPI_CONTINUE, /* Transfer not finished: CS pin kept active */
SPI_LAST /* Transfer ended: CS pin released */
};

// Indicates the user controls himself the CS pin outside of the spi class
#define CS_PIN_CONTROLLED_BY_USER NUM_DIGITAL_PINS

// Indicates there is no configuration selected
#define NO_CONFIG ((int16_t)(-1))

// Defines a default timeout delay in milliseconds for the SPI transfer
#ifndef SPI_TRANSFER_TIMEOUT
#define SPI_TRANSFER_TIMEOUT 1000
#endif

/*
* Defines the number of settings saved per SPI instance. Must be in range 1 to 254.
* Can be redefined in variant.h
*/
#ifndef NB_SPI_SETTINGS
#define NB_SPI_SETTINGS 4
#endif

class SPISettings {
public:
constexpr SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, bool noRecv = SPI_TRANSMITRECEIVE)
: pinCS(-1),
clk(clock),
bOrder(bitOrder),
dMode((spi_mode_e)(
(SPI_MODE0 == dataMode) ? SPI_MODE_0 :
(SPI_MODE1 == dataMode) ? SPI_MODE_1 :
(SPI_MODE2 == dataMode) ? SPI_MODE_2 :
(SPI_MODE3 == dataMode) ? SPI_MODE_3 :
SPI_MODE0
)),
noReceive(noRecv)
{ }
constexpr SPISettings()
: pinCS(-1),
clk(SPI_SPEED_CLOCK_DEFAULT),
bOrder(MSBFIRST),
dMode(SPI_MODE_0),
noReceive(SPI_TRANSMITRECEIVE)
{ }
SPISettings(uint32_t clock, BitOrder bitOrder, SPIMode dataMode, bool skipRecv = SPI_TRANSMITRECEIVE)
{
if (__builtin_constant_p(clock)) {
init_AlwaysInline(clock, bitOrder, dataMode, skipRecv);
} else {
init_MightInline(clock, bitOrder, dataMode, skipRecv);
}
}

SPISettings(uint32_t clock, BitOrder bitOrder, int dataMode, bool skipRecv = SPI_TRANSMITRECEIVE)
{
if (__builtin_constant_p(clock)) {
init_AlwaysInline(clock, bitOrder, (SPIMode)dataMode, skipRecv);
} else {
init_MightInline(clock, bitOrder, (SPIMode)dataMode, skipRecv);
}
}

// Default speed set to 4MHz, SPI mode set to MODE 0 and Bit order set to MSB first.
SPISettings()
{
init_AlwaysInline(SPI_SPEED_CLOCK_DEFAULT, MSBFIRST, SPI_MODE0, SPI_TRANSMITRECEIVE);
}

bool operator==(const SPISettings &rhs) const
{
if ((this->clockFreq == rhs.clockFreq) &&
(this->bitOrder == rhs.bitOrder) &&
(this->dataMode == rhs.dataMode) &&
(this->skipRecv == rhs.skipRecv)) {
return true;
}
return false;
}

bool operator!=(const SPISettings &rhs) const
{
return !(*this == rhs);
}

uint32_t getClockFreq() const
{
return clockFreq;
}
SPIMode getDataMode() const
{
return dataMode;
}
BitOrder getBitOrder() const
{
return (bitOrder);
}
bool getSkipRecv() const
{
return skipRecv;
}

void setClockFreq(uint32_t clkFreq)
{
clockFreq = clkFreq;
}
void setDataMode(SPIMode mode)
{
dataMode = mode;
}
void setBitOrder(BitOrder order)
{
bitOrder = order;
}
void setSkipRecv(bool skip)
{
skipRecv = skip;
}

private:
int16_t pinCS; //CS pin associated to the configuration
uint32_t clk; //specifies the spi bus maximum clock speed
BitOrder bOrder; //bit order (MSBFirst or LSBFirst)
spi_mode_e dMode; //one of the data mode
//Mode Clock Polarity (CPOL) Clock Phase (CPHA)
//SPI_MODE0 0 0
//SPI_MODE1 0 1
//SPI_MODE2 1 0
//SPI_MODE3 1 1
friend class SPIClass;
bool noReceive;
void init_MightInline(uint32_t clock, BitOrder bitOrder, SPIMode dataMode, bool skipRecv)
{
init_AlwaysInline(clock, bitOrder, dataMode, skipRecv);
}

// Core developer MUST use an helper function in beginTransaction() to use this data
void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, SPIMode dataMode, bool skipRecv) __attribute__((__always_inline__))
{
this->clockFreq = clock;
this->dataMode = dataMode;
this->bitOrder = bitOrder;
this->skipRecv = skipRecv;
}

uint32_t clockFreq;
SPIMode dataMode;
BitOrder bitOrder;
bool skipRecv;

friend class HardwareSPI;
};

const SPISettings DEFAULT_SPI_SETTINGS = SPISettings();

class SPIClass {
public:
SPIClass();
@@ -148,79 +187,33 @@ class SPIClass {
_spi.pin_ssel = (ssel);
};

virtual void begin(uint8_t _pin = CS_PIN_CONTROLLED_BY_USER);
virtual void begin(void);
void end(void);

/* This function should be used to configure the SPI instance in case you
* don't use default parameters.
* You can attach another CS pin to the SPI instance and each CS pin can be
* attach with specific SPI settings.
*/
virtual void beginTransaction(uint8_t pin, SPISettings settings);
void beginTransaction(SPISettings settings)
{
beginTransaction(CS_PIN_CONTROLLED_BY_USER, settings);
}

void endTransaction(uint8_t pin);
void endTransaction(void)
{
endTransaction(CS_PIN_CONTROLLED_BY_USER);
}
void beginTransaction(SPISettings settings);
virtual void endTransaction(void);

/* Transfer functions: must be called after initialization of the SPI
* instance with begin() or beginTransaction().
* You can specify the CS pin to use.
*/
virtual byte transfer(uint8_t pin, uint8_t _data, SPITransferMode _mode = SPI_LAST);
virtual uint16_t transfer16(uint8_t pin, uint16_t _data, SPITransferMode _mode = SPI_LAST);
virtual void transfer(uint8_t pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST);
virtual void transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST);

// Transfer functions when user controls himself the CS pin.
byte transfer(uint8_t _data, SPITransferMode _mode = SPI_LAST)
{
return transfer(CS_PIN_CONTROLLED_BY_USER, _data, _mode);
}

uint16_t transfer16(uint16_t _data, SPITransferMode _mode = SPI_LAST)
{
return transfer16(CS_PIN_CONTROLLED_BY_USER, _data, _mode);
}

void transfer(void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST)
{
transfer(CS_PIN_CONTROLLED_BY_USER, _buf, _count, _mode);
}

void transfer(void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST)
{
transfer(CS_PIN_CONTROLLED_BY_USER, _bufout, _bufin, _count, _mode);
}
virtual uint8_t transfer(uint8_t _data);
virtual uint16_t transfer16(uint16_t _data);
virtual void transfer(void *buf, size_t count);

/* These methods are deprecated and kept for compatibility.
* Use SPISettings with SPI.beginTransaction() to configure SPI parameters.
*/
void setBitOrder(uint8_t _pin, BitOrder);
void setBitOrder(BitOrder _order)
{
setBitOrder(CS_PIN_CONTROLLED_BY_USER, _order);
}

void setDataMode(uint8_t _pin, uint8_t);
void setDataMode(uint8_t _mode)
{
setDataMode(CS_PIN_CONTROLLED_BY_USER, _mode);
}

void setClockDivider(uint8_t _pin, uint8_t);
void setClockDivider(uint8_t _div)
{
setClockDivider(CS_PIN_CONTROLLED_BY_USER, _div);
}

// Not implemented functions. Kept for backward compatibility.
void usingInterrupt(uint8_t interruptNumber);
void setBitOrder(BitOrder);
void setDataMode(uint8_t);
void setDataMode(SPIMode);
void setClockDivider(uint8_t);

// Not implemented functions. Kept for compatibility.
void usingInterrupt(int interruptNumber);
void notUsingInterrupt(int interruptNumber);
void attachInterrupt(void);
void detachInterrupt(void);

@@ -235,68 +228,8 @@ class SPIClass {
spi_t _spi;

private:
/* Contains various spiSettings for the same spi instance. Each spi spiSettings
is associated to a CS pin. */
SPISettings spiSettings[NB_SPI_SETTINGS];

// Use to know which configuration is selected.
int16_t _CSPinConfig;

typedef enum {
GET_IDX = 0,
ADD_NEW_PIN = 1
} pin_option_t;

uint8_t pinIdx(uint8_t _pin, pin_option_t option)
{
uint8_t i;

if ((_pin > NUM_DIGITAL_PINS) && (!digitalPinIsValid(_pin))) {
return NB_SPI_SETTINGS;
}

for (i = 0; i < NB_SPI_SETTINGS; i++) {
if (_pin == spiSettings[i].pinCS) {
return i;
}
}

if (option == ADD_NEW_PIN) {
for (i = 0; i < NB_SPI_SETTINGS; i++) {
if (spiSettings[i].pinCS == -1) {
spiSettings[i].pinCS = _pin;
return i;
}
}
}
return i;
}

void RemovePin(uint8_t _pin)
{
if ((_pin > NUM_DIGITAL_PINS) && (!digitalPinIsValid(_pin))) {
return;
}

for (uint8_t i = 0; i < NB_SPI_SETTINGS; i++) {
if (spiSettings[i].pinCS == _pin) {
spiSettings[i].pinCS = -1;
spiSettings[i].clk = SPI_SPEED_CLOCK_DEFAULT;
spiSettings[i].bOrder = MSBFIRST;
spiSettings[i].dMode = SPI_MODE_0;
}
}
}

void RemoveAllPin(void)
{
for (uint8_t i = 0; i < NB_SPI_SETTINGS; i++) {
spiSettings[i].pinCS = -1;
spiSettings[i].clk = SPI_SPEED_CLOCK_DEFAULT;
spiSettings[i].bOrder = MSBFIRST;
spiSettings[i].dMode = SPI_MODE_0;
}
}
/* Current SPISettings */
SPISettings _spiSettings = DEFAULT_SPI_SETTINGS;
};

extern SPIClass SPI;
@@ -309,12 +242,11 @@ class SUBGHZSPIClass : public SPIClass {
_spi.spi = SUBGHZSPI;
}

void begin(uint8_t _pin = CS_PIN_CONTROLLED_BY_USER);
void beginTransaction(uint8_t pin, SPISettings settings);
byte transfer(uint8_t pin, uint8_t _data, SPITransferMode _mode = SPI_LAST);
uint16_t transfer16(uint8_t pin, uint16_t _data, SPITransferMode _mode = SPI_LAST);
void transfer(uint8_t pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST);
void transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST);
void begin();
void beginTransaction(SPISettings settings);
byte transfer(uint8_t _data);
uint16_t transfer16(uint16_t _data);
void transfer(void *_buf, size_t _count);
void enableDebugPins(uint32_t mosi = DEBUG_SUBGHZSPI_MOSI, uint32_t miso = DEBUG_SUBGHZSPI_MISO, uint32_t sclk = DEBUG_SUBGHZSPI_SCLK, uint32_t ssel = DEBUG_SUBGHZSPI_SS);

using SPIClass::beginTransaction;
31 changes: 9 additions & 22 deletions libraries/SPI/src/utility/spi_com.c
Original file line number Diff line number Diff line change
@@ -227,7 +227,7 @@ static uint32_t compute_disable_delay(spi_t *obj)
* @param msb : set to 1 in msb first
* @retval None
*/
void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb)
void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb)
{
if (obj == NULL) {
return;
@@ -313,13 +313,13 @@ void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb)

handle->Init.Direction = SPI_DIRECTION_2LINES;

if ((mode == SPI_MODE_0) || (mode == SPI_MODE_2)) {
if ((mode == SPI_MODE0) || (mode == SPI_MODE2)) {
handle->Init.CLKPhase = SPI_PHASE_1EDGE;
} else {
handle->Init.CLKPhase = SPI_PHASE_2EDGE;
}

if ((mode == SPI_MODE_0) || (mode == SPI_MODE_1)) {
if ((mode == SPI_MODE0) || (mode == SPI_MODE1)) {
handle->Init.CLKPolarity = SPI_POLARITY_LOW;
} else {
handle->Init.CLKPolarity = SPI_POLARITY_HIGH;
@@ -496,38 +496,25 @@ void spi_deinit(spi_t *obj)
#endif
}

/**
* @brief This function is implemented by user to send data over SPI interface
* @param obj : pointer to spi_t structure
* @param Data : data to be sent
* @param len : length in bytes of the data to be sent
* @param Timeout: Timeout duration in tick
* @retval status of the send operation (0) in case of error
*/
spi_status_e spi_send(spi_t *obj, uint8_t *Data, uint16_t len, uint32_t Timeout)
{
return spi_transfer(obj, Data, Data, len, Timeout, 1 /* SPI_TRANSMITONLY */);
}

/**
* @brief This function is implemented by user to send/receive data over
* SPI interface
* @param obj : pointer to spi_t structure
* @param tx_buffer : tx data to send before reception
* @param rx_buffer : data to receive
* @param buffer : tx data to send before reception
* @param len : length in byte of the data to send and receive
* @param Timeout: Timeout duration in tick
* @param skipReceive: skip receiving data after transmit or not
* @retval status of the send operation (0) in case of error
*/
spi_status_e spi_transfer(spi_t *obj, uint8_t *tx_buffer, uint8_t *rx_buffer,
uint16_t len, uint32_t Timeout, bool skipReceive)
spi_status_e spi_transfer(spi_t *obj, uint8_t *buffer, uint16_t len,
uint32_t Timeout, bool skipReceive)
{
spi_status_e ret = SPI_OK;
uint32_t tickstart, size = len;
SPI_TypeDef *_SPI = obj->handle.Instance;
uint8_t *tx_buffer = buffer;

if ((obj == NULL) || (len == 0) || (Timeout == 0U)) {
if ((len == 0) || (Timeout == 0U)) {
return Timeout > 0U ? SPI_ERROR : SPI_TIMEOUT;
}
tickstart = HAL_GetTick();
@@ -553,7 +540,7 @@ spi_status_e spi_transfer(spi_t *obj, uint8_t *tx_buffer, uint8_t *rx_buffer,
#else
while (!LL_SPI_IsActiveFlag_RXNE(_SPI));
#endif
*rx_buffer++ = LL_SPI_ReceiveData8(_SPI);
*buffer++ = LL_SPI_ReceiveData8(_SPI);
}
if ((Timeout != HAL_MAX_DELAY) && (HAL_GetTick() - tickstart >= Timeout)) {
ret = SPI_TIMEOUT;
18 changes: 9 additions & 9 deletions libraries/SPI/src/utility/spi_com.h
Original file line number Diff line number Diff line change
@@ -85,12 +85,13 @@ typedef struct spi_s spi_t;
//SPI_MODE2 1 0
//SPI_MODE3 1 1
//enum definitions coming from SPI.h of SAM
// SPI mode parameters for SPISettings
typedef enum {
SPI_MODE_0 = 0x00,
SPI_MODE_1 = 0x01,
SPI_MODE_2 = 0x02,
SPI_MODE_3 = 0x03
} spi_mode_e;
SPI_MODE0 = 0,
SPI_MODE1 = 1,
SPI_MODE2 = 2,
SPI_MODE3 = 3,
} SPIMode;

///@brief SPI errors
typedef enum {
@@ -100,11 +101,10 @@ typedef enum {
} spi_status_e;

/* Exported functions ------------------------------------------------------- */
void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb);
void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb);
void spi_deinit(spi_t *obj);
spi_status_e spi_send(spi_t *obj, uint8_t *Data, uint16_t len, uint32_t Timeout);
spi_status_e spi_transfer(spi_t *obj, uint8_t *tx_buffer,
uint8_t *rx_buffer, uint16_t len, uint32_t Timeout, bool skipReceive);
spi_status_e spi_transfer(spi_t *obj, uint8_t *buffer, uint16_t len,
uint32_t Timeout, bool skipReceive);
uint32_t spi_getClkFreq(spi_t *obj);

#ifdef __cplusplus