Skip to content

Commit 19e740a

Browse files
committed
all Spi::transfer(...) received bit-resolution
1 parent 6057873 commit 19e740a

File tree

12 files changed

+383
-132
lines changed

12 files changed

+383
-132
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2021, Thomas Sommer
3+
*
4+
* This file is part of the modm project.
5+
*
6+
* This Source Code Form is subject to the terms of the Mozilla Public
7+
* License, v. 2.0. If a copy of the MPL was not distributed with this
8+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
// ----------------------------------------------------------------------------
11+
12+
#pragma once
13+
14+
#include <limits>
15+
#include <type_traits>
16+
17+
#include <cmath>
18+
namespace modm
19+
{
20+
template <int Bits>
21+
struct uint_t
22+
{
23+
using least = std::conditional_t<
24+
(Bits <= 8),uint8_t, std::conditional_t<
25+
(Bits <= 16), uint16_t, std::conditional_t<
26+
(Bits <= 32), uint32_t, std::enable_if_t<
27+
(Bits <= 64), uint64_t>>>>;
28+
};
29+
30+
template<int Bits>
31+
using least_uint = typename modm::uint_t<Bits>::least;
32+
}

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/stm32/module.lb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ class Instance(Module):
2929
module.description = "Instance {}".format(self.instance)
3030

3131
def prepare(self, module, options):
32-
module.depends(":platform:spi")
32+
module.depends(
33+
":platform:spi",
34+
":math:utils"
35+
)
3336
return True
3437

3538
def build(self, env):
@@ -43,6 +46,7 @@ class Instance(Module):
4346
env.template("spi_hal_impl.hpp.in", "spi_hal_{}_impl.hpp".format(self.instance))
4447
env.template("spi_master.hpp.in", "spi_master_{}.hpp".format(self.instance))
4548
env.template("spi_master.cpp.in", "spi_master_{}.cpp".format(self.instance))
49+
env.template("spi_master_impl.hpp.in", "spi_master_{}_impl.hpp".format(self.instance))
4650
if env.has_module(":platform:dma"):
4751
env.template("spi_master_dma.hpp.in", "spi_master_{}_dma.hpp".format(self.instance))
4852
env.template("spi_master_dma_impl.hpp.in", "spi_master_{}_dma_impl.hpp".format(self.instance))

src/modm/platform/spi/stm32/spi_hal.hpp.in

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright (c) 2013-2018, Niklas Hauser
44
* Copyright (c) 2014, Daniel Krebs
55
* Copyright (c) 2020, Mike Wolfram
6+
* Copyright (c) 2021, Thomas Sommer
67
*
78
* This file is part of the modm project.
89
*
@@ -65,6 +66,10 @@ public:
6566
static void
6667
setDataSize(DataSize dataSize);
6768

69+
template<int Bits = 8>
70+
static void
71+
setDataSize();
72+
6873
static void
6974
setMasterSelection(MasterSelection masterSelection);
7075

@@ -82,24 +87,24 @@ public:
8287
isTransmitRegisterEmpty();
8388

8489
/**
85-
* Write up to 16 Bit to the data register
90+
* Write up to 8 Bit to the data register
8691
*
8792
* @warning This method does NOT do any sanity checks!!
8893
* It is your responsibility to check if the register
8994
* is empty!
9095
*/
9196
static void
92-
write(uint16_t data);
97+
write(uint8_t data);
9398

9499
/**
95-
* Write 8 Bit to the data register
100+
* Write up to 16 Bit to the data register
96101
*
97102
* @warning This method does NOT do any sanity checks!!
98103
* It is your responsibility to check if the register
99104
* is empty!
100105
*/
101106
static void
102-
write(uint8_t data);
107+
write(uint16_t data);
103108

104109
/**
105110
* Returns the value of the data register

src/modm/platform/spi/stm32/spi_hal_impl.hpp.in

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright (c) 2013-2017, Niklas Hauser
44
* Copyright (c) 2014, Daniel Krebs
55
* Copyright (c) 2020, Mike Wolfram
6+
* Copyright (c) 2021, Thomas Sommer
67
*
78
* This file is part of the modm project.
89
*
@@ -90,6 +91,15 @@ modm::platform::SpiHal{{ id }}::setDataSize(DataSize dataSize)
9091
%% endif
9192
}
9293

94+
template<int Bits>
95+
void
96+
modm::platform::SpiHal{{ id }}::setDataSize()
97+
{
98+
static_assert(Bits >= 4, "Spi DataSize requires at least 4 bits (on this MCU)");
99+
static_assert(Bits <= 16, "Spi DataSize is limited to 16 bits (on this MCU)");
100+
setDataSize((SpiBase::DataSize)((Bits - 1) << 8));
101+
}
102+
93103
void inline
94104
modm::platform::SpiHal{{ id }}::setMasterSelection(MasterSelection masterSelection)
95105
{
@@ -119,12 +129,6 @@ modm::platform::SpiHal{{ id }}::isTransmitRegisterEmpty()
119129
return static_cast<bool>(getInterruptFlags() & InterruptFlag::TxBufferEmpty);
120130
}
121131

122-
void inline
123-
modm::platform::SpiHal{{ id }}::write(uint16_t data)
124-
{
125-
SPI{{ id }}->DR = data;
126-
}
127-
128132
void inline
129133
modm::platform::SpiHal{{ id }}::write(uint8_t data)
130134
{
@@ -136,6 +140,12 @@ modm::platform::SpiHal{{ id }}::write(uint8_t data)
136140

137141
}
138142

143+
void inline
144+
modm::platform::SpiHal{{ id }}::write(uint16_t data)
145+
{
146+
SPI{{ id }}->DR = data;
147+
}
148+
139149
void inline
140150
modm::platform::SpiHal{{ id }}::read(uint8_t &data)
141151
{

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

Lines changed: 5 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Copyright (c) 2012-2017, Niklas Hauser
66
* Copyright (c) 2013, Kevin Läufer
77
* Copyright (c) 2014, Sascha Schade
8+
* Copyright (c) 2021, Thomas Sommer
89
*
910
* This file is part of the modm project.
1011
*
@@ -24,6 +25,9 @@ modm::platform::SpiMaster{{ id }}::state(0);
2425
uint8_t
2526
modm::platform::SpiMaster{{ id }}::count(0);
2627

28+
std::size_t
29+
modm::platform::SpiMaster{{ id }}::index(0);
30+
2731
void *
2832
modm::platform::SpiMaster{{ id }}::context(nullptr);
2933

@@ -61,85 +65,4 @@ modm::platform::SpiMaster{{ id }}::release(void *ctx)
6165
context = nullptr;
6266
}
6367
return count;
64-
}
65-
// ----------------------------------------------------------------------------
66-
67-
modm::ResumableResult<uint8_t>
68-
modm::platform::SpiMaster{{ id }}::transfer(uint8_t data)
69-
{
70-
// this is a manually implemented "fast resumable function"
71-
// there is no context or nesting protection, since we don't need it.
72-
// there are only two states encoded into 1 bit (LSB of state):
73-
// 1. waiting to start, and
74-
// 2. waiting to finish.
75-
76-
// LSB != Bit0 ?
77-
if ( !(state & Bit0) )
78-
{
79-
// wait for previous transfer to finish
80-
if (!SpiHal{{ id }}::isTransmitRegisterEmpty())
81-
return {modm::rf::Running};
82-
83-
// start transfer by copying data into register
84-
SpiHal{{ id }}::write(data);
85-
86-
// set LSB = Bit0
87-
state |= Bit0;
88-
}
89-
90-
if (!SpiHal{{ id }}::isReceiveRegisterNotEmpty())
91-
return {modm::rf::Running};
92-
93-
SpiHal{{ id }}::read(data);
94-
95-
// transfer finished
96-
state &= ~Bit0;
97-
return {modm::rf::Stop, data};
98-
}
99-
100-
modm::ResumableResult<void>
101-
modm::platform::SpiMaster{{ id }}::transfer(
102-
const uint8_t * tx, uint8_t * rx, std::size_t length)
103-
{
104-
// this is a manually implemented "fast resumable function"
105-
// there is no context or nesting protection, since we don't need it.
106-
// there are only two states encoded into 1 bit (Bit1 of state):
107-
// 1. initialize index, and
108-
// 2. wait for 1-byte transfer to finish.
109-
110-
// we need to globally remember which byte we are currently transferring
111-
static std::size_t index = 0;
112-
113-
// we are only interested in Bit1
114-
switch(state & Bit1)
115-
{
116-
case 0:
117-
// we will only visit this state once
118-
state |= Bit1;
119-
120-
// initialize index and check range
121-
index = 0;
122-
while (index < length)
123-
{
124-
default:
125-
{
126-
// if tx == 0, we use a dummy byte 0x00
127-
// else we copy it from the array
128-
// call the resumable function
129-
modm::ResumableResult<uint8_t> result = transfer(tx ? tx[index] : 0);
130-
131-
// if the resumable function is still running, so are we
132-
if (result.getState() > modm::rf::NestingError)
133-
return {modm::rf::Running};
134-
135-
// if rx != 0, we copy the result into the array
136-
if (rx) rx[index] = result.getResult();
137-
}
138-
index++;
139-
}
140-
141-
// clear the state
142-
state &= ~Bit1;
143-
return {modm::rf::Stop};
144-
}
145-
}
68+
}

0 commit comments

Comments
 (0)