Skip to content

Commit

Permalink
Merge pull request stm32duino#2171 from fpistm/SPI_rework
Browse files Browse the repository at this point in the history
[breaking] SPI library rework
  • Loading branch information
fpistm authored Nov 15, 2023
2 parents 462c518 + 0a926cf commit 0038100
Show file tree
Hide file tree
Showing 6 changed files with 265 additions and 574 deletions.
36 changes: 17 additions & 19 deletions CI/build/examples/BareMinimum/BareMinimum.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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();
Expand Down Expand Up @@ -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;
}
}
Expand Down
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);
```
Loading

0 comments on commit 0038100

Please sign in to comment.