Skip to content

Commit 0038100

Browse files
authoredNov 15, 2023
Merge pull request #2171 from fpistm/SPI_rework
[breaking] SPI library rework
2 parents 462c518 + 0a926cf commit 0038100

File tree

6 files changed

+265
-574
lines changed

6 files changed

+265
-574
lines changed
 

‎CI/build/examples/BareMinimum/BareMinimum.ino

+17-19
Original file line numberDiff line numberDiff line change
@@ -19,38 +19,37 @@
1919
/* ----------------------------------------------------------------------
2020
Defines each of the tests performed
2121
------------------------------------------------------------------- */
22-
#define MAX_BLOCKSIZE 2
23-
#define DELTA (0.0001f)
22+
#define MAX_BLOCKSIZE 2
23+
#define DELTA (0.0001f)
2424
/* ----------------------------------------------------------------------
2525
Test input data for Floating point sin_cos example for 32-blockSize
2626
Generated by the MATLAB randn() function
2727
------------------------------------------------------------------- */
28-
const float32_t testInput_f32[MAX_BLOCKSIZE] =
29-
{
30-
-1.244916875853235400, -4.793533929171324800
28+
const float32_t testInput_f32[MAX_BLOCKSIZE] = {
29+
-1.244916875853235400, -4.793533929171324800
3130
};
3231
const float32_t testRefOutput_f32 = 1.000000000;
3332
/* ----------------------------------------------------------------------
3433
Declare Global variables
3534
------------------------------------------------------------------- */
3635
uint32_t blockSize = 2;
37-
float32_t testOutput;
38-
float32_t cosOutput;
39-
float32_t sinOutput;
40-
float32_t cosSquareOutput;
41-
float32_t sinSquareOutput;
36+
float32_t testOutput;
37+
float32_t cosOutput;
38+
float32_t sinOutput;
39+
float32_t cosSquareOutput;
40+
float32_t sinSquareOutput;
4241
/* ----------------------------------------------------------------------
4342
Max magnitude FFT Bin test
4443
------------------------------------------------------------------- */
4544
arm_status status;
4645
/* CMSIS_DSP */
4746

4847
#ifndef USER_BTN
49-
#define USER_BTN 2
48+
#define USER_BTN 2
5049
#endif
5150

5251
#ifndef LED_BUILTIN
53-
#define LED_BUILTIN 13
52+
#define LED_BUILTIN 13
5453
#endif
5554

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

7372
void setup() {
7473
// Serial HW & SW
75-
#if (!defined(USBD_USE_CDC) && !defined(DISABLE_GENERIC_SERIALUSB)) &&\
76-
(!defined(VIRTIOCON) && !defined(DISABLE_GENERIC_SERIALVIRTIO))
74+
#if (!defined(USBD_USE_CDC) && !defined(DISABLE_GENERIC_SERIALUSB)) && (!defined(VIRTIOCON) && !defined(DISABLE_GENERIC_SERIALVIRTIO))
7775
Serial.setRx(PIN_SERIAL_RX);
7876
Serial.setTx(digitalPinToPinName(PIN_SERIAL_TX));
7977
#endif
@@ -92,7 +90,7 @@ void setup() {
9290

9391
// EEPROM
9492
byte value = EEPROM.read(0x01);
95-
EEPROM.write(EEPROM.length()-1, value);
93+
EEPROM.write(EEPROM.length() - 1, value);
9694

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

113111
// SPI
114-
SPISettings settings(SPI_SPEED_CLOCK_DEFAULT, MSBFIRST, SPI_MODE_0);
112+
SPISettings settings(SPI_SPEED_CLOCK_DEFAULT, MSBFIRST, SPI_MODE0);
115113
SPI.setMISO(PIN_SPI_MISO);
116114
SPI.setMOSI(PIN_SPI_MOSI);
117115
SPI.setSCLK(PIN_SPI_SCK);
118116
SPI.setSSEL(digitalPinToPinName(PIN_SPI_SS));
119-
SPI.begin(PIN_SPI_SS);
120-
SPI.beginTransaction(1, settings);
117+
SPI.begin();
118+
SPI.beginTransaction(settings);
121119
SPI.endTransaction();
122120
SPI.transfer(1);
123121
SPI.end();
@@ -146,7 +144,7 @@ void setup() {
146144
diff = fabsf(testRefOutput_f32 - testOutput);
147145
/* Comparison of sin_cos value with reference */
148146
status = (diff > DELTA) ? ARM_MATH_TEST_FAILURE : ARM_MATH_SUCCESS;
149-
if ( status == ARM_MATH_TEST_FAILURE) {
147+
if (status == ARM_MATH_TEST_FAILURE) {
150148
break;
151149
}
152150
}

‎libraries/SPI/README.md

+43-50
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,63 @@
11
## SPI
22

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

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

11-
### New API functions
10+
### New SPISetting parameter
1211

13-
* **`SPIClass::SPIClass(uint8_t mosi, uint8_t miso, uint8_t sclk, uint8_t ssel)`**: alternative class constructor
14-
_Params_ SPI mosi pin
15-
_Params_ SPI miso pin
16-
_Params_ SPI sclk pin
17-
_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.
12+
* `noReceive`: value can be `SPI_TRANSMITRECEIVE` or `SPI_TRANSMITONLY`. It allows to skip receive data after transmitting. Default `SPI_TRANSMITRECEIVE`.
1813

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

22-
* **`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.
23-
_Params_ SPI CS pin to be managed by the SPI library
24-
_Params_ SPI settings
16+
* `SPIClass::SPIClass(uint8_t mosi, uint8_t miso, uint8_t sclk, uint8_t ssel)`: alternative class constructor
17+
_Params_ SPI `mosi` pin
18+
_Params_ SPI `miso` pin
19+
_Params_ SPI `sclk` pin
20+
_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.
2521

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

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

33-
**_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.
25+
##### Example
3426

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

41-
* **`uint16_t transfer16(uint8_t pin, uint16_t _data, SPITransferMode _mode = SPI_LAST)`**: write/read half-word
42-
_Params_ SPI CS pin managed by the SPI library
43-
_Params_ 16bits data to write
44-
_Params_ (optional) if `SPI_LAST` CS pin is reset, `SPI_CONTINUE` the CS pin is kept enabled.
45-
_Return_ 16bits data received
29+
```C++
30+
#include <SPI.h>
31+
// MOSI MISO SCLK SSEL
32+
SPIClass SPI_3(PC12, PC11, PC10, PC9);
33+
34+
void setup() {
35+
SPI_3.begin(); // Enable the SPI_3 instance with default SPISsettings
36+
SPI_3.beginTransaction(settings); // Configure the SPI_3 instance with other settings
37+
SPI_3.transfer(0x52); // Transfers data to the first device
38+
SPI_3.end() //SPI_3 instance is disabled
39+
}
40+
```
4641
47-
* **`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
48-
_Params_ SPI CS pin managed by the SPI library
49-
_Params_ pointer to data to write. The data will be replaced by the data read.
50-
_Params_ number of data to write/read.
51-
_Params_ (optional) if `SPI_LAST` CS pin is reset, `SPI_CONTINUE` the CS pin is kept enabled.
42+
#### Change default `SPI` instance pins
43+
It is also possible to change the default pins used by the `SPI` instance using above API:
5244
53-
* **`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
54-
_Params_ SPI CS pin managed by the SPI library
55-
_Params_ pointer to data to write.
56-
_Params_ pointer where to store the data read.
57-
_Params_ number of data to write/read.
58-
_Params_ (optional) if `SPI_LAST` CS pin is reset, `SPI_CONTINUE` the CS pin is kept enabled.
45+
[[/img/Warning-icon.png|alt="Warning"]] **Have to be called before `begin()`.**
5946
60-
### Example
47+
* `void setMISO(uint32_t miso)`
48+
* `void setMOSI(uint32_t mosi)`
49+
* `void setSCLK(uint32_t sclk)`
50+
* `void setSSEL(uint32_t ssel)`
51+
* `void setMISO(PinName miso)`
52+
* `void setMOSI(PinName mosi)`
53+
* `void setSCLK(PinName sclk)`
54+
* `void setSSEL(PinName ssel)`
6155
62-
This is an example of the use of the CS pin management:
56+
**_Note 1_** Using `setSSEL()` allows to enable hardware CS pin management linked to the SPI peripheral.
6357
58+
##### Example:
6459
```C++
65-
SPI.begin(2); //Enables the SPI instance with default settings and attaches the CS pin
66-
SPI.beginTransaction(1, settings); //Attaches another CS pin and configure the SPI instance with other settings
67-
SPI.transfer(1, 0x52); //Transfers data to the first device
68-
SPI.transfer(2, 0xA4); //Transfers data to the second device. The SPI instance is configured with the right settings
69-
SPI.end() //SPI instance is disabled
60+
SPI.setMISO(PC_4); // using pin name PY_n
61+
SPI.setMOSI(PC2); // using pin number PYn
62+
SPI.begin(2);
7063
```

‎libraries/SPI/src/SPI.cpp

+70-289
Large diffs are not rendered by default.

‎libraries/SPI/src/SPI.h

+117-185
Original file line numberDiff line numberDiff line change
@@ -38,76 +38,115 @@ extern "C" {
3838
#define SPI_CLOCK_DIV64 64
3939
#define SPI_CLOCK_DIV128 128
4040

41-
// SPI mode parameters for SPISettings
42-
#define SPI_MODE0 0x00
43-
#define SPI_MODE1 0x01
44-
#define SPI_MODE2 0x02
45-
#define SPI_MODE3 0x03
46-
4741
#define SPI_TRANSMITRECEIVE 0x0
4842
#define SPI_TRANSMITONLY 0x1
4943

50-
// Transfer mode
51-
enum SPITransferMode {
52-
SPI_CONTINUE, /* Transfer not finished: CS pin kept active */
53-
SPI_LAST /* Transfer ended: CS pin released */
54-
};
55-
56-
// Indicates the user controls himself the CS pin outside of the spi class
57-
#define CS_PIN_CONTROLLED_BY_USER NUM_DIGITAL_PINS
58-
59-
// Indicates there is no configuration selected
60-
#define NO_CONFIG ((int16_t)(-1))
61-
6244
// Defines a default timeout delay in milliseconds for the SPI transfer
6345
#ifndef SPI_TRANSFER_TIMEOUT
6446
#define SPI_TRANSFER_TIMEOUT 1000
6547
#endif
6648

67-
/*
68-
* Defines the number of settings saved per SPI instance. Must be in range 1 to 254.
69-
* Can be redefined in variant.h
70-
*/
71-
#ifndef NB_SPI_SETTINGS
72-
#define NB_SPI_SETTINGS 4
73-
#endif
74-
7549
class SPISettings {
7650
public:
77-
constexpr SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, bool noRecv = SPI_TRANSMITRECEIVE)
78-
: pinCS(-1),
79-
clk(clock),
80-
bOrder(bitOrder),
81-
dMode((spi_mode_e)(
82-
(SPI_MODE0 == dataMode) ? SPI_MODE_0 :
83-
(SPI_MODE1 == dataMode) ? SPI_MODE_1 :
84-
(SPI_MODE2 == dataMode) ? SPI_MODE_2 :
85-
(SPI_MODE3 == dataMode) ? SPI_MODE_3 :
86-
SPI_MODE0
87-
)),
88-
noReceive(noRecv)
89-
{ }
90-
constexpr SPISettings()
91-
: pinCS(-1),
92-
clk(SPI_SPEED_CLOCK_DEFAULT),
93-
bOrder(MSBFIRST),
94-
dMode(SPI_MODE_0),
95-
noReceive(SPI_TRANSMITRECEIVE)
96-
{ }
51+
SPISettings(uint32_t clock, BitOrder bitOrder, SPIMode dataMode, bool skipRecv = SPI_TRANSMITRECEIVE)
52+
{
53+
if (__builtin_constant_p(clock)) {
54+
init_AlwaysInline(clock, bitOrder, dataMode, skipRecv);
55+
} else {
56+
init_MightInline(clock, bitOrder, dataMode, skipRecv);
57+
}
58+
}
59+
60+
SPISettings(uint32_t clock, BitOrder bitOrder, int dataMode, bool skipRecv = SPI_TRANSMITRECEIVE)
61+
{
62+
if (__builtin_constant_p(clock)) {
63+
init_AlwaysInline(clock, bitOrder, (SPIMode)dataMode, skipRecv);
64+
} else {
65+
init_MightInline(clock, bitOrder, (SPIMode)dataMode, skipRecv);
66+
}
67+
}
68+
69+
// Default speed set to 4MHz, SPI mode set to MODE 0 and Bit order set to MSB first.
70+
SPISettings()
71+
{
72+
init_AlwaysInline(SPI_SPEED_CLOCK_DEFAULT, MSBFIRST, SPI_MODE0, SPI_TRANSMITRECEIVE);
73+
}
74+
75+
bool operator==(const SPISettings &rhs) const
76+
{
77+
if ((this->clockFreq == rhs.clockFreq) &&
78+
(this->bitOrder == rhs.bitOrder) &&
79+
(this->dataMode == rhs.dataMode) &&
80+
(this->skipRecv == rhs.skipRecv)) {
81+
return true;
82+
}
83+
return false;
84+
}
85+
86+
bool operator!=(const SPISettings &rhs) const
87+
{
88+
return !(*this == rhs);
89+
}
90+
91+
uint32_t getClockFreq() const
92+
{
93+
return clockFreq;
94+
}
95+
SPIMode getDataMode() const
96+
{
97+
return dataMode;
98+
}
99+
BitOrder getBitOrder() const
100+
{
101+
return (bitOrder);
102+
}
103+
bool getSkipRecv() const
104+
{
105+
return skipRecv;
106+
}
107+
108+
void setClockFreq(uint32_t clkFreq)
109+
{
110+
clockFreq = clkFreq;
111+
}
112+
void setDataMode(SPIMode mode)
113+
{
114+
dataMode = mode;
115+
}
116+
void setBitOrder(BitOrder order)
117+
{
118+
bitOrder = order;
119+
}
120+
void setSkipRecv(bool skip)
121+
{
122+
skipRecv = skip;
123+
}
124+
97125
private:
98-
int16_t pinCS; //CS pin associated to the configuration
99-
uint32_t clk; //specifies the spi bus maximum clock speed
100-
BitOrder bOrder; //bit order (MSBFirst or LSBFirst)
101-
spi_mode_e dMode; //one of the data mode
102-
//Mode Clock Polarity (CPOL) Clock Phase (CPHA)
103-
//SPI_MODE0 0 0
104-
//SPI_MODE1 0 1
105-
//SPI_MODE2 1 0
106-
//SPI_MODE3 1 1
107-
friend class SPIClass;
108-
bool noReceive;
126+
void init_MightInline(uint32_t clock, BitOrder bitOrder, SPIMode dataMode, bool skipRecv)
127+
{
128+
init_AlwaysInline(clock, bitOrder, dataMode, skipRecv);
129+
}
130+
131+
// Core developer MUST use an helper function in beginTransaction() to use this data
132+
void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, SPIMode dataMode, bool skipRecv) __attribute__((__always_inline__))
133+
{
134+
this->clockFreq = clock;
135+
this->dataMode = dataMode;
136+
this->bitOrder = bitOrder;
137+
this->skipRecv = skipRecv;
138+
}
139+
140+
uint32_t clockFreq;
141+
SPIMode dataMode;
142+
BitOrder bitOrder;
143+
bool skipRecv;
144+
145+
friend class HardwareSPI;
109146
};
110147

148+
const SPISettings DEFAULT_SPI_SETTINGS = SPISettings();
149+
111150
class SPIClass {
112151
public:
113152
SPIClass();
@@ -148,79 +187,33 @@ class SPIClass {
148187
_spi.pin_ssel = (ssel);
149188
};
150189

151-
virtual void begin(uint8_t _pin = CS_PIN_CONTROLLED_BY_USER);
190+
virtual void begin(void);
152191
void end(void);
153192

154193
/* This function should be used to configure the SPI instance in case you
155194
* don't use default parameters.
156-
* You can attach another CS pin to the SPI instance and each CS pin can be
157-
* attach with specific SPI settings.
158195
*/
159-
virtual void beginTransaction(uint8_t pin, SPISettings settings);
160-
void beginTransaction(SPISettings settings)
161-
{
162-
beginTransaction(CS_PIN_CONTROLLED_BY_USER, settings);
163-
}
164-
165-
void endTransaction(uint8_t pin);
166-
void endTransaction(void)
167-
{
168-
endTransaction(CS_PIN_CONTROLLED_BY_USER);
169-
}
196+
void beginTransaction(SPISettings settings);
197+
virtual void endTransaction(void);
170198

171199
/* Transfer functions: must be called after initialization of the SPI
172200
* instance with begin() or beginTransaction().
173-
* You can specify the CS pin to use.
174201
*/
175-
virtual byte transfer(uint8_t pin, uint8_t _data, SPITransferMode _mode = SPI_LAST);
176-
virtual uint16_t transfer16(uint8_t pin, uint16_t _data, SPITransferMode _mode = SPI_LAST);
177-
virtual void transfer(uint8_t pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST);
178-
virtual void transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST);
179-
180-
// Transfer functions when user controls himself the CS pin.
181-
byte transfer(uint8_t _data, SPITransferMode _mode = SPI_LAST)
182-
{
183-
return transfer(CS_PIN_CONTROLLED_BY_USER, _data, _mode);
184-
}
185-
186-
uint16_t transfer16(uint16_t _data, SPITransferMode _mode = SPI_LAST)
187-
{
188-
return transfer16(CS_PIN_CONTROLLED_BY_USER, _data, _mode);
189-
}
190-
191-
void transfer(void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST)
192-
{
193-
transfer(CS_PIN_CONTROLLED_BY_USER, _buf, _count, _mode);
194-
}
195-
196-
void transfer(void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST)
197-
{
198-
transfer(CS_PIN_CONTROLLED_BY_USER, _bufout, _bufin, _count, _mode);
199-
}
202+
virtual uint8_t transfer(uint8_t _data);
203+
virtual uint16_t transfer16(uint16_t _data);
204+
virtual void transfer(void *buf, size_t count);
200205

201206
/* These methods are deprecated and kept for compatibility.
202207
* Use SPISettings with SPI.beginTransaction() to configure SPI parameters.
203208
*/
204-
void setBitOrder(uint8_t _pin, BitOrder);
205-
void setBitOrder(BitOrder _order)
206-
{
207-
setBitOrder(CS_PIN_CONTROLLED_BY_USER, _order);
208-
}
209-
210-
void setDataMode(uint8_t _pin, uint8_t);
211-
void setDataMode(uint8_t _mode)
212-
{
213-
setDataMode(CS_PIN_CONTROLLED_BY_USER, _mode);
214-
}
215-
216-
void setClockDivider(uint8_t _pin, uint8_t);
217-
void setClockDivider(uint8_t _div)
218-
{
219-
setClockDivider(CS_PIN_CONTROLLED_BY_USER, _div);
220-
}
221-
222-
// Not implemented functions. Kept for backward compatibility.
223-
void usingInterrupt(uint8_t interruptNumber);
209+
void setBitOrder(BitOrder);
210+
void setDataMode(uint8_t);
211+
void setDataMode(SPIMode);
212+
void setClockDivider(uint8_t);
213+
214+
// Not implemented functions. Kept for compatibility.
215+
void usingInterrupt(int interruptNumber);
216+
void notUsingInterrupt(int interruptNumber);
224217
void attachInterrupt(void);
225218
void detachInterrupt(void);
226219

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

237230
private:
238-
/* Contains various spiSettings for the same spi instance. Each spi spiSettings
239-
is associated to a CS pin. */
240-
SPISettings spiSettings[NB_SPI_SETTINGS];
241-
242-
// Use to know which configuration is selected.
243-
int16_t _CSPinConfig;
244-
245-
typedef enum {
246-
GET_IDX = 0,
247-
ADD_NEW_PIN = 1
248-
} pin_option_t;
249-
250-
uint8_t pinIdx(uint8_t _pin, pin_option_t option)
251-
{
252-
uint8_t i;
253-
254-
if ((_pin > NUM_DIGITAL_PINS) && (!digitalPinIsValid(_pin))) {
255-
return NB_SPI_SETTINGS;
256-
}
257-
258-
for (i = 0; i < NB_SPI_SETTINGS; i++) {
259-
if (_pin == spiSettings[i].pinCS) {
260-
return i;
261-
}
262-
}
263-
264-
if (option == ADD_NEW_PIN) {
265-
for (i = 0; i < NB_SPI_SETTINGS; i++) {
266-
if (spiSettings[i].pinCS == -1) {
267-
spiSettings[i].pinCS = _pin;
268-
return i;
269-
}
270-
}
271-
}
272-
return i;
273-
}
274-
275-
void RemovePin(uint8_t _pin)
276-
{
277-
if ((_pin > NUM_DIGITAL_PINS) && (!digitalPinIsValid(_pin))) {
278-
return;
279-
}
280-
281-
for (uint8_t i = 0; i < NB_SPI_SETTINGS; i++) {
282-
if (spiSettings[i].pinCS == _pin) {
283-
spiSettings[i].pinCS = -1;
284-
spiSettings[i].clk = SPI_SPEED_CLOCK_DEFAULT;
285-
spiSettings[i].bOrder = MSBFIRST;
286-
spiSettings[i].dMode = SPI_MODE_0;
287-
}
288-
}
289-
}
290-
291-
void RemoveAllPin(void)
292-
{
293-
for (uint8_t i = 0; i < NB_SPI_SETTINGS; i++) {
294-
spiSettings[i].pinCS = -1;
295-
spiSettings[i].clk = SPI_SPEED_CLOCK_DEFAULT;
296-
spiSettings[i].bOrder = MSBFIRST;
297-
spiSettings[i].dMode = SPI_MODE_0;
298-
}
299-
}
231+
/* Current SPISettings */
232+
SPISettings _spiSettings = DEFAULT_SPI_SETTINGS;
300233
};
301234

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

312-
void begin(uint8_t _pin = CS_PIN_CONTROLLED_BY_USER);
313-
void beginTransaction(uint8_t pin, SPISettings settings);
314-
byte transfer(uint8_t pin, uint8_t _data, SPITransferMode _mode = SPI_LAST);
315-
uint16_t transfer16(uint8_t pin, uint16_t _data, SPITransferMode _mode = SPI_LAST);
316-
void transfer(uint8_t pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST);
317-
void transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST);
245+
void begin();
246+
void beginTransaction(SPISettings settings);
247+
byte transfer(uint8_t _data);
248+
uint16_t transfer16(uint16_t _data);
249+
void transfer(void *_buf, size_t _count);
318250
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);
319251

320252
using SPIClass::beginTransaction;

‎libraries/SPI/src/utility/spi_com.c

+9-22
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ static uint32_t compute_disable_delay(spi_t *obj)
227227
* @param msb : set to 1 in msb first
228228
* @retval None
229229
*/
230-
void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb)
230+
void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb)
231231
{
232232
if (obj == NULL) {
233233
return;
@@ -313,13 +313,13 @@ void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb)
313313

314314
handle->Init.Direction = SPI_DIRECTION_2LINES;
315315

316-
if ((mode == SPI_MODE_0) || (mode == SPI_MODE_2)) {
316+
if ((mode == SPI_MODE0) || (mode == SPI_MODE2)) {
317317
handle->Init.CLKPhase = SPI_PHASE_1EDGE;
318318
} else {
319319
handle->Init.CLKPhase = SPI_PHASE_2EDGE;
320320
}
321321

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

499-
/**
500-
* @brief This function is implemented by user to send data over SPI interface
501-
* @param obj : pointer to spi_t structure
502-
* @param Data : data to be sent
503-
* @param len : length in bytes of the data to be sent
504-
* @param Timeout: Timeout duration in tick
505-
* @retval status of the send operation (0) in case of error
506-
*/
507-
spi_status_e spi_send(spi_t *obj, uint8_t *Data, uint16_t len, uint32_t Timeout)
508-
{
509-
return spi_transfer(obj, Data, Data, len, Timeout, 1 /* SPI_TRANSMITONLY */);
510-
}
511-
512499
/**
513500
* @brief This function is implemented by user to send/receive data over
514501
* SPI interface
515502
* @param obj : pointer to spi_t structure
516-
* @param tx_buffer : tx data to send before reception
517-
* @param rx_buffer : data to receive
503+
* @param buffer : tx data to send before reception
518504
* @param len : length in byte of the data to send and receive
519505
* @param Timeout: Timeout duration in tick
520506
* @param skipReceive: skip receiving data after transmit or not
521507
* @retval status of the send operation (0) in case of error
522508
*/
523-
spi_status_e spi_transfer(spi_t *obj, uint8_t *tx_buffer, uint8_t *rx_buffer,
524-
uint16_t len, uint32_t Timeout, bool skipReceive)
509+
spi_status_e spi_transfer(spi_t *obj, uint8_t *buffer, uint16_t len,
510+
uint32_t Timeout, bool skipReceive)
525511
{
526512
spi_status_e ret = SPI_OK;
527513
uint32_t tickstart, size = len;
528514
SPI_TypeDef *_SPI = obj->handle.Instance;
515+
uint8_t *tx_buffer = buffer;
529516

530-
if ((obj == NULL) || (len == 0) || (Timeout == 0U)) {
517+
if ((len == 0) || (Timeout == 0U)) {
531518
return Timeout > 0U ? SPI_ERROR : SPI_TIMEOUT;
532519
}
533520
tickstart = HAL_GetTick();
@@ -553,7 +540,7 @@ spi_status_e spi_transfer(spi_t *obj, uint8_t *tx_buffer, uint8_t *rx_buffer,
553540
#else
554541
while (!LL_SPI_IsActiveFlag_RXNE(_SPI));
555542
#endif
556-
*rx_buffer++ = LL_SPI_ReceiveData8(_SPI);
543+
*buffer++ = LL_SPI_ReceiveData8(_SPI);
557544
}
558545
if ((Timeout != HAL_MAX_DELAY) && (HAL_GetTick() - tickstart >= Timeout)) {
559546
ret = SPI_TIMEOUT;

‎libraries/SPI/src/utility/spi_com.h

+9-9
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,13 @@ typedef struct spi_s spi_t;
8585
//SPI_MODE2 1 0
8686
//SPI_MODE3 1 1
8787
//enum definitions coming from SPI.h of SAM
88+
// SPI mode parameters for SPISettings
8889
typedef enum {
89-
SPI_MODE_0 = 0x00,
90-
SPI_MODE_1 = 0x01,
91-
SPI_MODE_2 = 0x02,
92-
SPI_MODE_3 = 0x03
93-
} spi_mode_e;
90+
SPI_MODE0 = 0,
91+
SPI_MODE1 = 1,
92+
SPI_MODE2 = 2,
93+
SPI_MODE3 = 3,
94+
} SPIMode;
9495

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

102103
/* Exported functions ------------------------------------------------------- */
103-
void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb);
104+
void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb);
104105
void spi_deinit(spi_t *obj);
105-
spi_status_e spi_send(spi_t *obj, uint8_t *Data, uint16_t len, uint32_t Timeout);
106-
spi_status_e spi_transfer(spi_t *obj, uint8_t *tx_buffer,
107-
uint8_t *rx_buffer, uint16_t len, uint32_t Timeout, bool skipReceive);
106+
spi_status_e spi_transfer(spi_t *obj, uint8_t *buffer, uint16_t len,
107+
uint32_t Timeout, bool skipReceive);
108108
uint32_t spi_getClkFreq(spi_t *obj);
109109

110110
#ifdef __cplusplus

0 commit comments

Comments
 (0)
Please sign in to comment.