semf
stm32spislave.cpp
Go to the documentation of this file.
1
12
13#if defined(STM32) && defined(HAL_SPI_MODULE_ENABLED)
14namespace semf
15{
16LinkedQueue<Stm32SpiSlave> Stm32SpiSlave::m_queue;
17
18Stm32SpiSlave::Stm32SpiSlave(SPI_HandleTypeDef& hwHandle)
19: m_hwHandle{&hwHandle}
20{
21 m_queue.push(*this);
22 aborted.connect(m_abortedSlot);
23}
24
26{
27 auto state = HAL_SPI_Init(m_hwHandle);
28 if (state != HAL_OK)
29 {
30 if (state == HAL_ERROR)
31 {
32 SEMF_ERROR("hal error");
33 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::Init_HalError)));
34 }
35 else if (state == HAL_BUSY)
36 {
37 SEMF_ERROR("hal busy");
38 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::Init_HalBusy)));
39 }
40 else if (state == HAL_TIMEOUT)
41 {
42 SEMF_ERROR("hal timeout");
43 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::Init_HalTimeout)));
44 }
45 return;
46 }
47 setBusy(false);
48}
50{
51 auto state = HAL_SPI_DeInit(m_hwHandle);
52 if (state != HAL_OK)
53 {
54 if (state == HAL_ERROR)
55 {
56 SEMF_ERROR("hal error");
57 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::Deinit_HalError)));
58 }
59 else if (state == HAL_BUSY)
60 {
61 SEMF_ERROR("hal busy");
62 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::Deinit_HalBusy)));
63 }
64 else if (state == HAL_TIMEOUT)
65 {
66 SEMF_ERROR("hal timeout");
67 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::Deinit_HalError)));
68 }
69 return;
70 }
71 setBusy(false);
72}
73
74void Stm32SpiSlave::systemIsrRead(SPI_HandleTypeDef& hwHandle)
75{
76 for (auto& handle : m_queue)
77 {
78 if (handle.m_hwHandle == &hwHandle)
79 handle.onDataAvailable();
80 }
81}
82
83void Stm32SpiSlave::systemIsrWritten(SPI_HandleTypeDef& hwHandle)
84{
85 for (auto& handle : m_queue)
86 {
87 if (handle.m_hwHandle == &hwHandle)
88 handle.onDataWritten();
89 }
90}
91
92void Stm32SpiSlave::systemIsrWrittenAndRead(SPI_HandleTypeDef& hwHandle)
93{
94 for (auto& handle : m_queue)
95 {
96 if (handle.m_hwHandle == &hwHandle)
97 handle.onReadWrittenHardware();
98 }
99}
100
101void Stm32SpiSlave::systemIsrError(SPI_HandleTypeDef& hwHandle)
102{
103 for (auto& handle : m_queue)
104 {
105 if (handle.m_hwHandle == &hwHandle)
106 handle.onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::SystemIsrError_Isr)));
107 }
108}
109
110void Stm32SpiSlave::systemIsrAbort(SPI_HandleTypeDef& hwHandle)
111{
112 for (auto& handle : m_queue)
113 {
114 if (handle.m_hwHandle == &hwHandle)
115 handle.onAbortedHardware();
116 }
117}
118
119void Stm32SpiSlave::writeHardware(const uint8_t data[], size_t dataSize)
120{
121 __HAL_UNLOCK(m_hwHandle);
122 auto state = HAL_SPI_Transmit_IT(m_hwHandle, const_cast<uint8_t*>(data), static_cast<uint16_t>(dataSize));
123 if (state != HAL_OK)
124 {
125 if (state == HAL_ERROR)
126 {
127 SEMF_ERROR("hal error");
128 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::WriteHardware_HalError)));
129 }
130 else if (state == HAL_BUSY)
131 {
132 SEMF_ERROR("hal busy");
133 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::WriteHardware_HalBusy)));
134 }
135 else if (state == HAL_TIMEOUT)
136 {
137 SEMF_ERROR("hal timeout");
138 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::WriteHardware_HalTimeout)));
139 }
140 return;
141 }
142}
143
144void Stm32SpiSlave::readHardware(uint8_t buffer[], size_t bufferSize)
145{
146 __HAL_UNLOCK(m_hwHandle);
147 auto state = HAL_SPI_Receive_IT(m_hwHandle, buffer, static_cast<uint16_t>(bufferSize));
148 if (state != HAL_OK)
149 {
150 if (state == HAL_ERROR)
151 {
152 SEMF_ERROR("hal error");
153 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::ReadHardware_HalError)));
154 }
155 else if (state == HAL_BUSY)
156 {
157 SEMF_ERROR("hal busy");
158 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::ReadHardware_HalBusy)));
159 }
160 else if (state == HAL_TIMEOUT)
161 {
162 SEMF_ERROR("hal timeout");
163 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::ReadHardware_HalTimeout)));
164 }
165 return;
166 }
167}
168
169void Stm32SpiSlave::writeReadHardware(const uint8_t writeData[], uint8_t readBuffer[], size_t size)
170{
171 m_writeData = const_cast<uint8_t*>(writeData);
172 m_readBuffer = readBuffer;
173 m_writeDataSize = size;
174
175 __HAL_UNLOCK(m_hwHandle);
176 auto state = HAL_SPI_TransmitReceive_IT(m_hwHandle, const_cast<uint8_t*>(writeData), readBuffer, 1);
177 if (state != HAL_OK)
178 {
179 if (state == HAL_ERROR)
180 {
181 SEMF_ERROR("hal error");
182 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::WriteReadHardware_HalError)));
183 }
184 else if (state == HAL_BUSY)
185 {
186 SEMF_ERROR("hal busy");
187 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::WriteReadHardware_HalBusy)));
188 }
189 else if (state == HAL_TIMEOUT)
190 {
191 SEMF_ERROR("hal timeout");
192 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::WriteReadHardware_HalTimeout)));
193 }
194 return;
195 }
196}
197
199{
200 m_abortedSlot.setObject(readStopped);
201 __HAL_UNLOCK(m_hwHandle);
202 auto state = HAL_SPI_Abort(m_hwHandle);
203 if (state != HAL_OK)
204 {
205 if (state == HAL_ERROR)
206 {
207 SEMF_ERROR("hal error");
208 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::StopReadHardware_HalError)));
209 }
210 else if (state == HAL_BUSY)
211 {
212 SEMF_ERROR("hal busy");
213 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::StopReadHardware_HalBusy)));
214 }
215 else if (state == HAL_TIMEOUT)
216 {
217 SEMF_ERROR("hal timeout");
218 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::StopReadHardware_HalTimeout)));
219 }
220 return;
221 }
222}
223
225{
226 m_abortedSlot.setObject(writeStopped);
227 __HAL_UNLOCK(m_hwHandle);
228 auto state = HAL_SPI_Abort(m_hwHandle);
229 if (state != HAL_OK)
230 {
231 if (state == HAL_ERROR)
232 {
233 SEMF_ERROR("hal error");
234 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::StopWriteHardware_HalError)));
235 }
236 else if (state == HAL_BUSY)
237 {
238 SEMF_ERROR("hal busy");
239 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::StopWriteHardware_HalBusy)));
240 }
241 else if (state == HAL_TIMEOUT)
242 {
243 SEMF_ERROR("hal timeout");
244 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::StopWriteHardware_HalTimeout)));
245 }
246 return;
247 }
248}
249
251{
252 SEMF_INFO("read written");
253 setBusy(false);
255}
256
258{
259 m_writeData++;
260 m_readBuffer++;
261 m_writeDataSize--;
262 if (m_writeDataSize != 0)
263 {
264 writeReadHardware(m_writeData, m_readBuffer, m_writeDataSize);
265 }
266 else
267 {
269 }
270}
271
273{
274 setBusy(false);
275 aborted();
276}
277
279{
280 if (bits == 8)
281 m_hwHandle->Init.DataSize = SPI_DATASIZE_8BIT;
282 else if (bits == 16)
283 m_hwHandle->Init.DataSize = SPI_DATASIZE_16BIT;
284 else
285 {
286 SEMF_ERROR("%d bits not supported");
287 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::SetFormatHardware_BitsNotSupported)));
288 return;
289 }
290
291 switch (transmission)
292 {
294 m_hwHandle->Init.CLKPolarity = SPI_POLARITY_LOW;
295 m_hwHandle->Init.CLKPhase = SPI_PHASE_1EDGE;
296 break;
298 m_hwHandle->Init.CLKPolarity = SPI_POLARITY_LOW;
299 m_hwHandle->Init.CLKPhase = SPI_PHASE_2EDGE;
300 break;
302 m_hwHandle->Init.CLKPolarity = SPI_POLARITY_HIGH;
303 m_hwHandle->Init.CLKPhase = SPI_PHASE_1EDGE;
304 break;
306 m_hwHandle->Init.CLKPolarity = SPI_POLARITY_HIGH;
307 m_hwHandle->Init.CLKPhase = SPI_PHASE_2EDGE;
308 break;
309 }
310
311 switch (wire)
312 {
315 m_hwHandle->Init.Direction = SPI_DIRECTION_2LINES;
316 break;
318 m_hwHandle->Init.Direction = SPI_DIRECTION_1LINE;
319 break;
321 m_hwHandle->Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
322 break;
323 }
324}
325} // namespace semf
326#endif
Class for representing errors. Every error should have a unique source code. As a user feel encourage...
Definition: error.h:22
void connect(SlotBase< Arguments... > &slot)
Connect a method to the signal.
Definition: signal.h:94
WireMode
Definition: spi.h:37
@ WriteOnlyWires
CLK and MOSI pins used (no master receive)
@ ReadOnlyWires
CLK and MISO pins used (no master write)
@ FullDuplexWires
CLK, MISO and MOSI pins used.
@ HalfDuplexWires
CLK, MISO / MOSI pins used (MISO and MOSI pin is shared)
TransmissionMode
Definition: spi.h:29
@ Mode2
POL is high, PHA is low.
@ Mode0
POL is low, PHA is low.
@ Mode1
POL is low, PHA is high.
@ Mode3
POL is high, PHA is high.
void onError(Error thrown)
Error routine, emits the error signal.
void setBusy(bool busy)
Sets the flag m_isBusy.
static void systemIsrWrittenAndRead(SPI_HandleTypeDef &hwHandle)
Handles the global receive transmit complete callback.
static void systemIsrError(SPI_HandleTypeDef &hwHandle)
Handles the global error callback.
static void systemIsrAbort(SPI_HandleTypeDef &hwHandle)
Handles the global abort callback.
static void systemIsrRead(SPI_HandleTypeDef &hwHandle)
Handles the global receive complete callback.
void writeReadHardware(const uint8_t writeData[], uint8_t readBuffer[], size_t size) override
Accesses the spi hardware in order to perform a full duplex read/write.
Stm32SpiSlave(SPI_HandleTypeDef &hwHandle)
Constructor.
void readHardware(uint8_t buffer[], size_t bufferSize) override
Accesses the spi hardware in order to read bufferSize bytes and stores them in buffer.
void deinit() override
void writeHardware(const uint8_t data[], size_t dataSize) override
Accesses the spi hardware in order to write dataSize bytes of data.
static void systemIsrWritten(SPI_HandleTypeDef &hwHandle)
Handles the global transmit complete callback.
void setFormatHardware(uint8_t bits, TransmissionMode transmission, WireMode wire) override
Configures the hardware for insuring the given configuration.
void stopWriteHardware() override
void init() override
void stopReadHardware() override
#define SEMF_ERROR(...)
Definition: debug.h:39
#define SEMF_INFO(...)
Definition: debug.h:41