Skip to content

Commit 8bca76e

Browse files
Rework SPI to include async operation; reshuffle DMA assignments
1 parent 77783de commit 8bca76e

File tree

22 files changed

+694
-673
lines changed

22 files changed

+694
-673
lines changed

libraries/SPI/keywords.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,17 @@ SPI KEYWORD1
1414

1515
begin KEYWORD2
1616
end KEYWORD2
17+
usingInterrupt KEYWORD2
18+
notUsingInterrupt KEYWORD2
19+
beginTransaction KEYWORD2
20+
endTransaction KEYWORD2
1721
transfer KEYWORD2
1822
transfer16 KEYWORD2
19-
transfer32 KEYWORD2
2023
setBitOrder KEYWORD2
2124
setDataMode KEYWORD2
2225
setClockDivider KEYWORD2
26+
cancel KEYWORD2
27+
done KEYWORD2
2328

2429

2530
#######################################

libraries/SPI/src/SPI.cpp

Lines changed: 65 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016-2018 Thomas Roell. All rights reserved.
2+
* Copyright (c) 2016-2020 Thomas Roell. All rights reserved.
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a copy
55
* of this software and associated documentation files (the "Software"), to
@@ -53,9 +53,8 @@ SPIClass::SPIClass(struct _stm32l0_spi_t *spi, const struct _stm32l0_spi_params_
5353
_clock = 4000000;
5454
_option = STM32L0_SPI_OPTION_MODE_0 | STM32L0_SPI_OPTION_MSB_FIRST;
5555

56-
_transferRoutine = SPIClass::_transferSelect;
56+
_transfer8Routine = SPIClass::_transfer8Select;
5757
_transfer16Routine = SPIClass::_transfer16Select;
58-
_transfer32Routine = SPIClass::_transfer32Select;
5958

6059
_spi_class[spi->instance] = this;
6160
}
@@ -70,9 +69,8 @@ void SPIClass::end()
7069
if (_active) {
7170
stm32l0_spi_release(_spi);
7271

73-
_transferRoutine = SPIClass::_transferSelect;
72+
_transfer8Routine = SPIClass::_transfer8Select;
7473
_transfer16Routine = SPIClass::_transfer16Select;
75-
_transfer32Routine = SPIClass::_transfer32Select;
7674

7775
_active = false;
7876
}
@@ -108,18 +106,16 @@ void SPIClass::beginTransaction(SPISettings settings)
108106

109107
_active = true;
110108

111-
_transferRoutine = stm32l0_spi_data;
109+
_transfer8Routine = stm32l0_spi_data8;
112110
_transfer16Routine = stm32l0_spi_data16;
113-
_transfer32Routine = stm32l0_spi_data32;
114111
}
115112

116113
void SPIClass::endTransaction(void)
117114
{
118115
stm32l0_spi_release(_spi);
119116

120-
_transferRoutine = SPIClass::_transferSelect;
117+
_transfer8Routine = SPIClass::_transfer8Select;
121118
_transfer16Routine = SPIClass::_transfer16Select;
122-
_transfer32Routine = SPIClass::_transfer32Select;
123119

124120
_active = false;
125121
}
@@ -129,9 +125,8 @@ void SPIClass::setBitOrder(BitOrder bitOrder)
129125
if (_active) {
130126
stm32l0_spi_release(_spi);
131127

132-
_transferRoutine = SPIClass::_transferSelect;
128+
_transfer8Routine = SPIClass::_transfer8Select;
133129
_transfer16Routine = SPIClass::_transfer16Select;
134-
_transfer32Routine = SPIClass::_transfer32Select;
135130

136131
_active = false;
137132
}
@@ -144,9 +139,8 @@ void SPIClass::setDataMode(uint8_t dataMode)
144139
if (_active) {
145140
stm32l0_spi_release(_spi);
146141

147-
_transferRoutine = SPIClass::_transferSelect;
142+
_transfer8Routine = SPIClass::_transfer8Select;
148143
_transfer16Routine = SPIClass::_transfer16Select;
149-
_transfer32Routine = SPIClass::_transfer32Select;
150144

151145
_active = false;
152146
}
@@ -159,9 +153,8 @@ void SPIClass::setClockDivider(uint8_t divider)
159153
if (_active) {
160154
stm32l0_spi_release(_spi);
161155

162-
_transferRoutine = SPIClass::_transferSelect;
156+
_transfer8Routine = SPIClass::_transfer8Select;
163157
_transfer16Routine = SPIClass::_transfer16Select;
164-
_transfer32Routine = SPIClass::_transfer32Select;
165158

166159
_active = false;
167160
}
@@ -171,21 +164,6 @@ void SPIClass::setClockDivider(uint8_t divider)
171164
}
172165
}
173166

174-
void SPIClass::setHalfDuplex(bool enable)
175-
{
176-
if (_active) {
177-
stm32l0_spi_release(_spi);
178-
179-
_transferRoutine = SPIClass::_transferSelect;
180-
_transfer16Routine = SPIClass::_transfer16Select;
181-
_transfer32Routine = SPIClass::_transfer32Select;
182-
183-
_active = false;
184-
}
185-
186-
_option = (_option & ~STM32L0_SPI_OPTION_HALFDUPLEX) | (enable ? STM32L0_SPI_OPTION_HALFDUPLEX : 0);
187-
}
188-
189167
void SPIClass::attachInterrupt()
190168
{
191169
// Should be enableInterrupt()
@@ -196,19 +174,18 @@ void SPIClass::detachInterrupt()
196174
// Should be disableInterrupt()
197175
}
198176

199-
uint8_t SPIClass::_transferSelect(struct _stm32l0_spi_t *spi, uint8_t data)
177+
uint8_t SPIClass::_transfer8Select(struct _stm32l0_spi_t *spi, uint8_t data)
200178
{
201179
SPIClass *spi_class = _spi_class[spi->instance];
202180

203181
stm32l0_spi_acquire(spi, spi_class->_clock, spi_class->_option);
204182

205183
spi_class->_active = true;
206184

207-
spi_class->_transferRoutine = stm32l0_spi_data;
185+
spi_class->_transfer8Routine = stm32l0_spi_data8;
208186
spi_class->_transfer16Routine = stm32l0_spi_data16;
209-
spi_class->_transfer32Routine = stm32l0_spi_data32;
210187

211-
return (*spi_class->_transferRoutine)(spi, data);
188+
return (*spi_class->_transfer8Routine)(spi, data);
212189
}
213190

214191
uint16_t SPIClass::_transfer16Select(struct _stm32l0_spi_t *spi, uint16_t data)
@@ -219,56 +196,85 @@ uint16_t SPIClass::_transfer16Select(struct _stm32l0_spi_t *spi, uint16_t data)
219196

220197
spi_class->_active = true;
221198

222-
spi_class->_transferRoutine = stm32l0_spi_data;
199+
spi_class->_transfer8Routine = stm32l0_spi_data8;
223200
spi_class->_transfer16Routine = stm32l0_spi_data16;
224-
spi_class->_transfer32Routine = stm32l0_spi_data32;
225201

226202
return (*spi_class->_transfer16Routine)(spi, data);
227203
}
228204

229-
uint32_t SPIClass::_transfer32Select(struct _stm32l0_spi_t *spi, uint32_t data)
205+
void SPIClass::transfer(const void *txBuffer, void *rxBuffer, size_t count)
230206
{
231-
SPIClass *spi_class = _spi_class[spi->instance];
232-
233-
stm32l0_spi_acquire(spi, spi_class->_clock, spi_class->_option);
207+
if (!_active)
208+
{
209+
stm32l0_spi_acquire(_spi, _clock, _option);
210+
211+
_active = true;
212+
213+
_transfer8Routine = stm32l0_spi_data8;
214+
_transfer16Routine = stm32l0_spi_data16;
215+
}
234216

235-
spi_class->_active = true;
217+
stm32l0_spi_data(_spi, (const uint8_t*)txBuffer, (uint8_t*)rxBuffer, count);
218+
}
236219

237-
spi_class->_transferRoutine = stm32l0_spi_data;
238-
spi_class->_transfer16Routine = stm32l0_spi_data16;
239-
spi_class->_transfer32Routine = stm32l0_spi_data32;
240-
241-
return (*spi_class->_transfer32Routine)(spi, data);
220+
bool SPIClass::transfer(const void *txBuffer, void *rxBuffer, size_t count, void(*callback)(void))
221+
{
222+
return transfer(txBuffer, rxBuffer, count, Callback(callback));
242223
}
243224

244-
void SPIClass::transfer(const void *txBuffer, void *rxBuffer, size_t count)
225+
bool SPIClass::transfer(const void *txBuffer, void *rxBuffer, size_t count, Callback callback)
245226
{
227+
if (!stm32l0_spi_done(_spi))
228+
{
229+
return false;
230+
}
231+
246232
if (!_active)
247233
{
248234
stm32l0_spi_acquire(_spi, _clock, _option);
249235

250236
_active = true;
251237

252-
_transferRoutine = stm32l0_spi_data;
238+
_transfer8Routine = stm32l0_spi_data8;
253239
_transfer16Routine = stm32l0_spi_data16;
254-
_transfer32Routine = stm32l0_spi_data32;
255240
}
256241

257-
if (txBuffer)
258-
{
259-
if (rxBuffer)
260-
{
261-
stm32l0_spi_transfer(_spi, (const uint8_t*)txBuffer, (uint8_t*)rxBuffer, count);
262-
}
263-
else
264-
{
265-
stm32l0_spi_transmit(_spi, (const uint8_t*)txBuffer, count);
242+
_callback = callback;
243+
244+
if (txBuffer) {
245+
if (rxBuffer) {
246+
if (!stm32l0_spi_transfer(_spi, static_cast<const uint8_t*>(txBuffer), static_cast<uint8_t*>(rxBuffer), count, (stm32l0_spi_done_callback_t)SPIClass::_doneCallback, (void*)this)) {
247+
return false;
248+
}
249+
} else {
250+
if (!stm32l0_spi_transmit(_spi, static_cast<const uint8_t*>(txBuffer), count, (stm32l0_spi_done_callback_t)SPIClass::_doneCallback, (void*)this)) {
251+
return false;
252+
}
266253
}
267254
}
268255
else
269256
{
270-
stm32l0_spi_receive(_spi, (uint8_t*)rxBuffer, count);
257+
if (!stm32l0_spi_receive(_spi, static_cast<uint8_t*>(rxBuffer), count, (stm32l0_spi_done_callback_t)SPIClass::_doneCallback, (void*)this)) {
258+
return false;
259+
}
271260
}
261+
262+
return true;
263+
}
264+
265+
size_t SPIClass::cancel(void)
266+
{
267+
return stm32l0_spi_cancel(_spi);
268+
}
269+
270+
bool SPIClass::done(void)
271+
{
272+
return stm32l0_spi_done(_spi);
273+
}
274+
275+
void SPIClass::_doneCallback(class SPIClass *self)
276+
{
277+
self->_callback.queue();;
272278
}
273279

274280
#if SPI_INTERFACES_COUNT > 0

libraries/SPI/src/SPI.h

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242
class SPISettings {
4343
public:
4444
SPISettings() : _clock(4000000), _option(0) { }
45-
SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, bool halfduplex = false) :
46-
_clock(clock), _option((dataMode & (SPI_CR1_CPHA | SPI_CR1_CPOL)) | ((bitOrder != MSBFIRST) ? SPI_CR1_LSBFIRST : 0) | (halfduplex ? 0x80000000 : 0x00000000)) { }
45+
SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) :
46+
_clock(clock), _option((dataMode & (SPI_CR1_CPHA | SPI_CR1_CPOL)) | ((bitOrder != MSBFIRST) ? SPI_CR1_LSBFIRST : 0)) { }
4747

4848
private:
4949
uint32_t _clock;
@@ -54,61 +54,61 @@ class SPISettings {
5454

5555
class SPIClass {
5656
public:
57-
SPIClass(struct _stm32l0_spi_t *spi, const struct _stm32l0_spi_params_t *params);
57+
SPIClass(struct _stm32l0_spi_t *spi, const struct _stm32l0_spi_params_t *params);
5858

59-
inline uint8_t transfer(uint8_t data) { return _transfer(data); }
60-
inline uint16_t transfer16(uint16_t data) { return _transfer16(data); }
61-
inline void transfer(void *buffer, size_t count) { return transfer(buffer, buffer, count); }
59+
inline uint8_t transfer(uint8_t data) { return _transfer8(data); }
60+
inline uint16_t transfer16(uint16_t data) { return _transfer16(data); }
61+
inline void transfer(void *buffer, size_t count) { return transfer(buffer, buffer, count); }
6262

63-
// Transaction Functions
64-
void usingInterrupt(uint32_t pin);
65-
void notUsingInterrupt(uint32_t pin);
66-
void beginTransaction(SPISettings settings);
67-
void endTransaction(void);
63+
// Transaction Functions
64+
void usingInterrupt(uint32_t pin);
65+
void notUsingInterrupt(uint32_t pin);
66+
void beginTransaction(SPISettings settings);
67+
void endTransaction(void);
6868

69-
// SPI Configuration methods
70-
void attachInterrupt();
71-
void detachInterrupt();
69+
// SPI Configuration methods
70+
void attachInterrupt();
71+
void detachInterrupt();
7272

73-
void begin();
74-
void end();
73+
void begin();
74+
void end();
7575

76-
void setBitOrder(BitOrder bitOrder);
77-
void setDataMode(uint8_t dataMode);
78-
void setClockDivider(uint8_t divider);
79-
void setHalfDuplex(bool enable);
80-
81-
// STM32L0 EXTENSION: transfer of a 32 bit chunk
82-
inline uint32_t transfer32(uint32_t data) { return _transfer32(data); }
83-
84-
// STM32L0 EXTENSION: transfer with separate read/write buffer
85-
void transfer(const void *txBuffer, void *rxBuffer, size_t count);
76+
void setBitOrder(BitOrder bitOrder);
77+
void setDataMode(uint8_t dataMode);
78+
void setClockDivider(uint8_t divider);
8679

80+
// STM32L0 EXTENSION: transfer with separate read/write buffer
81+
void transfer(const void *txBuffer, void *rxBuffer, size_t count);
82+
83+
// STM32L0 EXTENSTION: asynchronous transfer with separate read/write buffer
84+
bool transfer(const void *txBuffer, void *rxBuffer, size_t count, void(*callback)(void));
85+
bool transfer(const void *txBuffer, void *rxBuffer, size_t count, Callback callback);
86+
size_t cancel(void);
87+
bool done(void);
88+
8789
private:
8890
struct _stm32l0_spi_t *_spi;
8991
bool _active;
9092
uint32_t _clock;
9193
uint32_t _option;
9294

93-
uint8_t (*_transferRoutine)(struct _stm32l0_spi_t*, uint8_t);
94-
uint16_t (*_transfer16Routine)(struct _stm32l0_spi_t*, uint16_t);
95-
uint32_t (*_transfer32Routine)(struct _stm32l0_spi_t*, uint32_t);
95+
Callback _callback;
9696

97-
uint8_t _transfer(uint8_t data) __attribute__((__always_inline__)) {
98-
return (*_transferRoutine)(_spi, data);
97+
uint8_t (*_transfer8Routine)(struct _stm32l0_spi_t*, uint8_t);
98+
uint16_t (*_transfer16Routine)(struct _stm32l0_spi_t*, uint16_t);
99+
100+
uint8_t _transfer8(uint8_t data) __attribute__((__always_inline__)) {
101+
return (*_transfer8Routine)(_spi, data);
99102
}
100103

101104
uint16_t _transfer16(uint16_t data) __attribute__((__always_inline__)) {
102105
return (*_transfer16Routine)(_spi, data);
103106
}
104107

105-
uint32_t _transfer32(uint32_t data) __attribute__((__always_inline__)) {
106-
return (*_transfer32Routine)(_spi, data);
107-
}
108-
109-
static uint8_t _transferSelect(struct _stm32l0_spi_t *spi, uint8_t data);
108+
static uint8_t _transfer8Select(struct _stm32l0_spi_t *spi, uint8_t data);
110109
static uint16_t _transfer16Select(struct _stm32l0_spi_t *spi, uint16_t data);
111-
static uint32_t _transfer32Select(struct _stm32l0_spi_t *spi, uint32_t data);
110+
111+
static void _doneCallback(class SPIClass *self);
112112
};
113113

114114
#if SPI_INTERFACES_COUNT > 0

libraries/Wire/src/Wire.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016-2019 Thomas Roell. All rights reserved.
2+
* Copyright (c) 2016-2020 Thomas Roell. All rights reserved.
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a copy
55
* of this software and associated documentation files (the "Software"), to
@@ -607,10 +607,10 @@ bool TwoWireTransaction::submit(class TwoWire &wire, uint8_t address, const uint
607607
_callback = callback;
608608

609609
if (!stm32l0_i2c_submit(wire._i2c, &_transaction)) {
610-
return 1;
610+
return false;
611611
}
612612

613-
return 0;
613+
return true;
614614
}
615615

616616
bool TwoWireTransaction::done()

0 commit comments

Comments
 (0)