Skip to content

Commit 15bba59

Browse files
committed
added uint16_t support to Spi::transfer(...) for STM32 and AVR
1 parent 6057873 commit 15bba59

15 files changed

+501
-201
lines changed

src/modm/platform/dma/stm32/dma.hpp.in

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,34 @@ public:
189189
ChannelHal::setPeripheralAddress(address);
190190
}
191191

192+
static void
193+
setMemoryDataSize(MemoryDataSize memoryDataSize)
194+
{
195+
ChannelHal::setMemoryDataSize(memoryDataSize);
196+
}
197+
198+
static void
199+
setPeripheralDataSize(PeripheralDataSize peripheralDataSize)
200+
{
201+
ChannelHal::setPeripheralDataSize(peripheralDataSize);
202+
}
203+
204+
template<std::unsigned_integral T>
205+
static void
206+
configureDataSize() {
207+
if constexpr(std::is_same<T, uint8_t>::value) {
208+
ChannelHal::setMemoryDataSize(DmaBase::MemoryDataSize::Byte);
209+
ChannelHal::setPeripheralDataSize(DmaBase::PeripheralDataSize::Byte);
210+
}
211+
else if constexpr(std::is_same<T, uint16_t>::value) {
212+
ChannelHal::setMemoryDataSize(DmaBase::MemoryDataSize::HalfWord);
213+
ChannelHal::setPeripheralDataSize(DmaBase::PeripheralDataSize::HalfWord);
214+
} else if constexpr(std::is_same<T, uint32_t>::value) {
215+
ChannelHal::setMemoryDataSize(DmaBase::MemoryDataSize::Word);
216+
ChannelHal::setPeripheralDataSize(DmaBase::PeripheralDataSize::Word);
217+
}
218+
}
219+
192220
/**
193221
* Enable/disable memory increment
194222
*

src/modm/platform/dma/stm32/dma_base.hpp.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ public:
152152
Bit16 = HalfWord,
153153
Word = {{ reg_prefix }}_MSIZE_1,
154154
Bit32 = Word,
155+
All = DMA_CCR_MSIZE_0 | DMA_CCR_MSIZE_1
155156
};
156157

157158
enum class
@@ -163,6 +164,7 @@ public:
163164
Bit16 = HalfWord,
164165
Word = {{ reg_prefix }}_PSIZE_1,
165166
Bit32 = Word,
167+
All = DMA_CCR_PSIZE_0 | DMA_CCR_PSIZE_1
166168
};
167169

168170
enum class

src/modm/platform/dma/stm32/dma_hal.hpp.in

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,22 @@ public:
200200
Base->CPAR = address;
201201
}
202202

203+
static void
204+
setMemoryDataSize(MemoryDataSize memoryDataSize)
205+
{
206+
DMA_Channel_TypeDef *Base = (DMA_Channel_TypeDef *) CHANNEL_BASE;
207+
Base->CCR &= ~uint32_t(MemoryDataSize::All);
208+
Base->CCR |= uint32_t(memoryDataSize);
209+
}
210+
211+
static void
212+
setPeripheralDataSize(PeripheralDataSize peripheralDataSize)
213+
{
214+
DMA_Channel_TypeDef *Base = (DMA_Channel_TypeDef *) CHANNEL_BASE;
215+
Base->CCR &= ~uint32_t(PeripheralDataSize::All);
216+
Base->CCR |= uint32_t(peripheralDataSize);
217+
}
218+
203219
/**
204220
* Enable/disable memory increment
205221
*
@@ -240,9 +256,11 @@ public:
240256

241257
/**
242258
* Set length of data to transfer
259+
*
260+
* @param lenght range: 0-65535
243261
*/
244262
static void
245-
setDataLength(std::size_t length)
263+
setDataLength(uint16_t length)
246264
{
247265
DMA_Channel_TypeDef *Base = (DMA_Channel_TypeDef *) CHANNEL_BASE;
248266
Base->CNDTR = length;

src/modm/platform/spi/at90_tiny_mega/module.lb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class Instance(Module):
5050

5151
env.template("spi.hpp.in", "spi{}.hpp".format(self.instance))
5252
env.template("spi_master.hpp.in", "spi_master{}.hpp".format(self.instance))
53+
env.template("spi_master_impl.hpp.in", "spi_master{}_impl.hpp".format(self.instance))
5354
env.template("spi_master.cpp.in", "spi_master{}.cpp".format(self.instance))
5455

5556
def init(module):
@@ -88,5 +89,6 @@ def build(env):
8889

8990
if "instance" not in driver:
9091
env.template("spi_master.hpp.in")
92+
env.template("spi_master_impl.hpp.in")
9193
env.template("spi_master.cpp.in")
9294
env.template("spi.hpp.in")

src/modm/platform/spi/at90_tiny_mega/spi_master.cpp.in

Lines changed: 68 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,16 @@
1919
#include <modm/math/utils/bit_constants.hpp>
2020
#include <modm/architecture/interface/atomic_lock.hpp>
2121

22-
// bit 7 (0x80) is used for transfer 1 byte
23-
// bit 6 (0x40) is used for transfer multiple byte
24-
// bit 5-0 (0x3f) are used to store the acquire count
22+
// bit 7 (0x80) is used for transfer 2nd byte
23+
// bit 6 (0x40) is used for transfer 1th byte
24+
// bit 5 (0x20) is used for transfer multiple T
25+
// bit 4-0 (0x1f) are used to store the acquire count
2526
uint8_t
2627
modm::platform::SpiMaster{{ id }}::state(0);
2728

29+
uint8_t
30+
modm::platform::SpiMaster::read(0);
31+
2832
void *
2933
modm::platform::SpiMaster{{ id }}::context(nullptr);
3034

@@ -39,7 +43,7 @@ modm::platform::SpiMaster{{ id }}::initialize(Prescaler prescaler)
3943

4044
SPCR{{ id }} = (1 << SPE{{ id }}) | (1 << MSTR{{ id }}) | (static_cast<uint8_t>(prescaler) & ~0x80);
4145
SPSR{{ id }} = (static_cast<uint8_t>(prescaler) & 0x80) ? (1 << SPI2X{{ id }}) : 0;
42-
state &= 0x3f;
46+
state &= 0x1f;
4347
}
4448
// ----------------------------------------------------------------------------
4549

@@ -49,7 +53,7 @@ modm::platform::SpiMaster{{ id }}::acquire(void *ctx, ConfigurationHandler handl
4953
if (context == nullptr)
5054
{
5155
context = ctx;
52-
state = (state & ~0x3f) | 1;
56+
state = (state & ~0x1f) | 1;
5357
// if handler is not nullptr and is different from previous configuration
5458
if (handler and configuration != handler) {
5559
configuration = handler;
@@ -59,7 +63,7 @@ modm::platform::SpiMaster{{ id }}::acquire(void *ctx, ConfigurationHandler handl
5963
}
6064

6165
if (ctx == context)
62-
return (++state & 0x3f);
66+
return (++state & 0x1f);
6367

6468
return 0;
6569
}
@@ -69,15 +73,15 @@ modm::platform::SpiMaster{{ id }}::release(void *ctx)
6973
{
7074
if (ctx == context)
7175
{
72-
if ((--state & 0x3f) == 0)
76+
if ((--state & 0x1f) == 0)
7377
context = nullptr;
7478
}
75-
return (state & 0x3f);
79+
return (state & 0x1f);
7680
}
7781
// ----------------------------------------------------------------------------
7882

7983
modm::ResumableResult<uint8_t>
80-
modm::platform::SpiMaster{{ id }}::transfer(uint8_t data)
84+
modm::platform::SpiMaster{{ id }}::transfer(const uint8_t data)
8185
{
8286
%% if options["busywait"]
8387
SPDR{{ id }} = data;
@@ -95,75 +99,82 @@ modm::platform::SpiMaster{{ id }}::transfer(uint8_t data)
9599
// 1. waiting to start, and
96100
// 2. waiting to finish.
97101

98-
// MSB != Bit7 ?
99-
if ( !(state & Bit7) )
102+
// MSB != Bit6 ?
103+
if ( !(state & Bit6) )
100104
{
101105
// start transfer by copying data into register
102106
SPDR{{ id }} = data;
103107

104-
// set MSB = Bit7
105-
state |= Bit7;
108+
// set MSB = Bit6
109+
state |= Bit6;
106110
}
107111

108112
// wait for transfer to finish
109113
if (!(SPSR{{ id }} & (1 << SPIF{{ id }})))
110114
return {modm::rf::Running};
111115

112-
data = SPDR{{ id }};
113-
state &= ~Bit7;
114-
return {modm::rf::Stop, data};
116+
state &= ~Bit6;
117+
return {modm::rf::Stop, SPDR{{ id }}};
115118
%% endif
116119
}
117120

118-
modm::ResumableResult<void>
119-
modm::platform::SpiMaster{{ id }}::transfer(const uint8_t *tx, uint8_t *rx, std::size_t length)
121+
modm::ResumableResult<uint16_t>
122+
modm::platform::SpiMaster{{ id }}::transfer(const uint16_t data)
120123
{
121124
%% if options["busywait"]
122-
for (std::size_t index = 0; index < length; index++)
123-
{
124-
modm::ResumableResult<uint8_t> result = transfer(tx ? tx[index] : 0);
125-
if (rx) rx[index] = result.getResult();
126-
}
127-
return {modm::rf::Stop};
125+
SPDR{{ id }} = data >> 8;
126+
127+
// wait for 1rd byte to finish
128+
while (!(SPSR{{ id }} & (1 << SPIF{{ id }})))
129+
;
130+
131+
read = SPDR{{ id }} << 8;
132+
133+
SPDR{{ id }} = data;
134+
135+
// wait for 2nd byte to finish
136+
while (!(SPSR{{ id }} & (1 << SPIF{{ id }})))
137+
;
138+
139+
return {modm::rf::Stop, (uint16_t(read) << 8) | SPDR{{ id }}};
128140
%% else
129141
// this is a manually implemented "fast resumable function"
130142
// there is no context or nesting protection, since we don't need it.
131-
// there are only two states encoded into 1 bit (Bit6 of state):
132-
// 1. initialize index, and
133-
// 2. wait for 1-byte transfer to finish.
143+
// there are only three states encoded into 1 bit (LSB of state):
144+
// 1. waiting to start, and
145+
// 2. waiting to finish.
134146

135-
// we need to globally remember which byte we are currently transferring
136-
static std::size_t index = 0;
147+
// MSB != Bit6 ?
148+
if ( !(state & Bit6) )
149+
{
150+
// start transfer by copying data into register
151+
SPDR{{ id }} = data >> 8;
137152

138-
// we are only interested in Bit6
139-
switch(state & Bit6)
153+
// set MSB = Bit6
154+
state |= Bit6;
155+
}
156+
// MSB != Bit7 ?
157+
if ( !(state & Bit7) )
140158
{
141-
case 0:
142-
// we will only visit this state once
143-
state |= Bit6;
144-
145-
// initialize index and check range
146-
index = 0;
147-
while (index < length)
148-
{
149-
default:
150-
{
151-
// call the resumable function
152-
modm::ResumableResult<uint8_t> result = transfer(tx ? tx[index] : 0);
153-
154-
// if the resumable function is still running, so are we
155-
if (result.getState() > modm::rf::NestingError)
156-
return {modm::rf::Running};
157-
158-
// if rx != 0, we copy the result into the array
159-
if (rx) rx[index] = result.getResult();
160-
}
161-
index++;
162-
}
159+
// wait for 1rd byte to finish
160+
if (!(SPSR{{ id }} & (1 << SPIF{{ id }})))
161+
return {modm::rf::Running};
163162

164-
// clear the state
165-
state &= ~Bit6;
166-
return {modm::rf::Stop};
163+
// store 1rd received byte
164+
read = SPDR;
165+
166+
// start transfer by copying data into register
167+
SPDR{{ id }} = data;
168+
169+
// set MSB = Bit7
170+
state |= Bit7;
167171
}
172+
173+
// wait for 2nd byte to finish
174+
if (!(SPSR{{ id }} & (1 << SPIF{{ id }})))
175+
return {modm::rf::Running};
176+
177+
state &= ~(Bit7 | Bit6);
178+
return {modm::rf::Stop, (uint16_t(read) << 8) | SPDR{{ id }}};
168179
%% endif
169-
}
180+
}

src/modm/platform/spi/at90_tiny_mega/spi_master.hpp.in

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ namespace platform
5353
class SpiMaster{{ id }} : public ::modm::SpiMaster, private Spi
5454
{
5555
static uint8_t state;
56+
static uint8_t read;
5657
static void *context;
5758
static ConfigurationHandler configuration;
5859
public:
@@ -129,8 +130,9 @@ public:
129130
release(void *ctx);
130131

131132

132-
static uint8_t
133-
transferBlocking(uint8_t data)
133+
template <std::unsigned_integral T>
134+
static T
135+
transferBlocking(const T data)
134136
{
135137
%% if options["busywait"]
136138
return transfer(data).getResult();
@@ -139,22 +141,27 @@ public:
139141
%% endif
140142
}
141143

144+
template <std::unsigned_integral T>
142145
static void
143-
transferBlocking(const uint8_t *tx, uint8_t *rx, std::size_t length)
146+
transferBlocking(const T *tx, T *rx, std::size_t length)
144147
{
145148
%% if options["busywait"]
146149
transfer(tx, rx, length);
147150
%% else
148-
RF_CALL_BLOCKING(transfer(tx, rx, length));
151+
RF_CALL_BLOCKING(transfer<T>(tx, rx, length));
149152
%% endif
150153
}
151154

152155

153156
static modm::ResumableResult<uint8_t>
154-
transfer(uint8_t data);
157+
transfer(const uint8_t data);
158+
159+
static modm::ResumableResult<uint16_t>
160+
transfer(const uint16_t data);
155161

162+
template <std::unsigned_integral T>
156163
static modm::ResumableResult<void>
157-
transfer(const uint8_t *tx, uint8_t *rx, std::size_t length);
164+
transfer(const T *tx, T *rx, std::size_t length);
158165
// end documentation inherited
159166

160167
protected:
@@ -166,4 +173,6 @@ protected:
166173

167174
} // namespace modm
168175

176+
#include "spi_master_impl.hpp"
177+
169178
#endif // MODM_AVR_SPI_MASTER_HPP

0 commit comments

Comments
 (0)