15#if defined(STM32) && defined(HAL_SPI_MODULE_ENABLED)
19: m_hwHandle(&hwHandle),
20 m_spiClockFrequencyHz(spiClockFrequencyHz)
28 m_hwHandle(&hwHandle),
29 m_spiClockFrequencyHz(spiClockFrequencyHz)
38 HAL_StatusTypeDef state = HAL_SPI_Init(m_hwHandle);
41 if (state == HAL_ERROR)
46 else if (state == HAL_BUSY)
51 else if (state == HAL_TIMEOUT)
63 HAL_StatusTypeDef state = HAL_SPI_DeInit(m_hwHandle);
66 if (state == HAL_ERROR)
71 else if (state == HAL_BUSY)
76 else if (state == HAL_TIMEOUT)
93 if (m_spiClockFrequencyHz == 0)
100 std::array<uint32_t, 8> frequencies;
102 uint8_t prescaler = 1;
104 std::generate(frequencies.begin(), frequencies.end(),
105 [
this, prescaler]()
mutable
107 uint32_t freq = m_spiClockFrequencyHz / (prescaler + 1);
108 prescaler = static_cast<uint8_t>(prescaler | (prescaler << 1));
112 auto upperIt = std::upper_bound(frequencies.rbegin(), frequencies.rend(), hz);
113 auto lowerIt = std::lower_bound(frequencies.rbegin(), frequencies.rend(), hz);
118 uint32_t upper = upperIt.base() == frequencies.end() ? frequencies.back() : *upperIt;
119 uint32_t lower = lowerIt == frequencies.rend() ? frequencies.front() : *lowerIt;
121 uint32_t best = upper - hz < hz - lower ? upper : lower;
123 SEMF_INFO(
"closest possible frequency is %d Hz", best);
125 auto bestIt = std::find(frequencies.begin(), frequencies.end(), best);
127 if (bestIt - frequencies.begin() == 0)
128 m_hwHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
129 else if (bestIt - frequencies.begin() == 1)
130 m_hwHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
131 else if (bestIt - frequencies.begin() == 2)
132 m_hwHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
133 else if (bestIt - frequencies.begin() == 3)
134 m_hwHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
135 else if (bestIt - frequencies.begin() == 4)
136 m_hwHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
137 else if (bestIt - frequencies.begin() == 5)
138 m_hwHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
139 else if (bestIt - frequencies.begin() == 6)
140 m_hwHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
141 else if (bestIt - frequencies.begin() == 7)
142 m_hwHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
168 i.isrWrittenAndRead(spi);
185 if (&spi != m_hwHandle)
191 if (m_dataIndex < m_dataSize)
205 if (&spi != m_hwHandle)
216 if (&spi != m_hwHandle)
222 if (m_dataIndex < m_dataSize)
237 if (&spi != m_hwHandle)
246 if (&spi != m_hwHandle)
256 SEMF_INFO(
"data %p, size %u", data, dataSize);
257 __HAL_UNLOCK(m_hwHandle);
258 HAL_StatusTypeDef state = HAL_SPI_Transmit_IT(m_hwHandle,
const_cast<uint8_t*
>(data),
static_cast<uint16_t
>(dataSize));
261 if (state == HAL_ERROR)
266 else if (state == HAL_BUSY)
271 else if (state == HAL_TIMEOUT)
282 SEMF_INFO(
"data %p, size %u", buffer, bufferSize);
283 m_readData =
const_cast<uint8_t*
>(buffer);
284 m_dataSize = bufferSize;
291 SEMF_INFO(
"write data %p, read data %p, size %u", writeData, readBuffer, size);
292 m_writeData = writeData;
293 m_readData = readBuffer;
302 m_hwHandle->Init.DataSize = SPI_DATASIZE_8BIT;
304 m_hwHandle->Init.DataSize = SPI_DATASIZE_16BIT;
312 switch (transmission)
315 m_hwHandle->Init.CLKPolarity = SPI_POLARITY_LOW;
316 m_hwHandle->Init.CLKPhase = SPI_PHASE_1EDGE;
319 m_hwHandle->Init.CLKPolarity = SPI_POLARITY_LOW;
320 m_hwHandle->Init.CLKPhase = SPI_PHASE_2EDGE;
323 m_hwHandle->Init.CLKPolarity = SPI_POLARITY_HIGH;
324 m_hwHandle->Init.CLKPhase = SPI_PHASE_1EDGE;
327 m_hwHandle->Init.CLKPolarity = SPI_POLARITY_HIGH;
328 m_hwHandle->Init.CLKPhase = SPI_PHASE_2EDGE;
336 m_hwHandle->Init.Direction = SPI_DIRECTION_2LINES;
339 m_hwHandle->Init.Direction = SPI_DIRECTION_1LINE;
342 m_hwHandle->Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
350 auto state = HAL_SPI_Abort_IT(m_hwHandle);
353 if (state == HAL_ERROR)
358 else if (state == HAL_BUSY)
363 else if (state == HAL_TIMEOUT)
375 auto state = HAL_SPI_Abort_IT(m_hwHandle);
378 if (state == HAL_ERROR)
383 else if (state == HAL_BUSY)
388 else if (state == HAL_TIMEOUT)
397void Stm32SpiMaster::readNext()
400 __HAL_UNLOCK(m_hwHandle);
401 HAL_StatusTypeDef state = HAL_SPI_Receive_IT(m_hwHandle, &m_readData[m_dataIndex], 1);
404 if (state == HAL_ERROR)
409 else if (state == HAL_BUSY)
414 else if (state == HAL_TIMEOUT)
423void Stm32SpiMaster::writeReadNext()
426 __HAL_UNLOCK(m_hwHandle);
427 HAL_StatusTypeDef state = HAL_SPI_TransmitReceive_IT(m_hwHandle,
const_cast<uint8_t*
>(&m_writeData[m_dataIndex]), &m_readData[m_dataIndex], 1);
430 if (state == HAL_ERROR)
435 else if (state == HAL_BUSY)
440 else if (state == HAL_TIMEOUT)
@ FirstAndLast
start AND stop condition
Class for representing errors. Every error should have a unique source code. As a user feel encourage...
Interface class for using a GPIO pin of the microcontroller.
LinkedQueue is an managed single linked queue implementation.
void connect(SlotBase< Arguments... > &slot)
Connect a method to the signal.
@ 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)
@ 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.
Class for using SPI hardware in master mode.
void onError(Error thrown)
Is called if an error occurred by hardware read or write access. Will throw error signal.
CommunicationHardware::Frame frame() const
Returns the actual frame mode setting.
bool isBusyWriting() const override
Communication hardware is busy writing at the moment.
void setBusy(bool isBusy)
Sets the busy flag.
bool isBusyReading() const override
Communication hardware is busy reading at the moment.
SpiMasterHardware implementation for STM32.
void setFrequency(uint32_t hz) override
Sets the speed.
static void systemIsrWrittenAndRead(SPI_HandleTypeDef &spi)
System-wide interrupt service routine for spi receive and transmit.
void isrAborted(SPI_HandleTypeDef &spi)
handles the abort callback
void isrWrittenAndRead(SPI_HandleTypeDef &spi)
Interrupt service routine for spi object receive and transmit.
Stm32SpiMaster(SPI_HandleTypeDef &hwHandle, uint32_t spiClockFrequencyHz=0)
Constructor.
void setFormatHardware(uint8_t bits, TransmissionMode transmission, WireMode wire) override
Configures the hardware for insuring the given configuration.
void writeReadHardware(const uint8_t writeData[], uint8_t readBuffer[], size_t size) override
Hardware will read and write data parallel.
void writeHardware(const uint8_t data[], size_t dataSize) override
Hardware will write data.
static void systemIsrError(SPI_HandleTypeDef &spi)
System-wide interrupt service routine for spi error.
void isrRead(SPI_HandleTypeDef &spi)
Interrupt service routine for spi object receive.
static void systemIsrWritten(SPI_HandleTypeDef &spi)
System-wide interrupt service routine for spi transmit.
static void systemIsrRead(SPI_HandleTypeDef &spi)
System-wide interrupt service routine for spi receive.
void readHardware(uint8_t buffer[], size_t bufferSize) override
Hardware will read data.
static void systemIsrAbort(SPI_HandleTypeDef &spi)
System-wide interrupt service routine for spi abort.
void isrError(SPI_HandleTypeDef &spi)
Interrupt service routine for spi object error.
void isrWritten(SPI_HandleTypeDef &spi)
static LinkedQueue< Stm32SpiMaster > * queue()
Get the list with all spi.
@ StopWriteHardware_HalError
@ SetFrequency_SpiClockIsZero
@ StopReadHardware_HalError
@ StopWriteHardware_HalTimeout
@ StopWriteHardware_HalBusy
@ SetFormatHardware_BitsNotSupported
@ StopReadHardware_HalTimeout
@ StopReadHardware_HalBusy
void stopReadHardware() override
void stopWriteHardware() override