mirror of
https://git.intern.spaceteamaachen.de/ALPAKA/sta-core.git
synced 2025-06-12 01:25:59 +00:00
166 lines
5.1 KiB
C++
166 lines
5.1 KiB
C++
#include <sta/devices/stm32/bus/spi.hpp>
|
|
#ifdef STA_STM32_SPI_ENABLED
|
|
|
|
#include <sta/debug/assert.hpp>
|
|
#include <sta/endian.hpp>
|
|
#include <sta/lang.hpp>
|
|
|
|
|
|
#ifdef STA_MCU_LITTLE_ENDIAN
|
|
# define STA_STM32_SPI_REVERSE_BIT_ORDER SPIBitOrder::MSB
|
|
#elif STA_MCU_BIG_ENDIAN
|
|
# define STA_STM32_SPI_REVERSE_BIT_ORDER SPIBitOrder::LSB
|
|
#endif
|
|
|
|
|
|
namespace sta
|
|
{
|
|
static SPISettings getSPISettings(SPI_HandleTypeDef * handle, uint32_t pclkFreq)
|
|
{
|
|
SPISettings settings;
|
|
|
|
settings.mode = getSPIMode(
|
|
(handle->Init.CLKPolarity == SPI_POLARITY_LOW) ? SPIClkPolarity::LOW : SPIClkPolarity::HIGH,
|
|
(handle->Init.CLKPhase == SPI_PHASE_1EDGE) ? SPIClkPhase::EDGE_1 : SPIClkPhase::EDGE_2
|
|
);
|
|
settings.dataSize = (handle->Init.DataSize == SPI_DATASIZE_8BIT) ? SPIDataSize::SIZE_8 : SPIDataSize::SIZE_16;
|
|
settings.bitOrder = (handle->Init.FirstBit == SPI_FIRSTBIT_MSB) ? SPIBitOrder::MSB : SPIBitOrder::LSB;
|
|
|
|
uint32_t prescaler = 1;
|
|
switch (handle->Init.BaudRatePrescaler)
|
|
{
|
|
case SPI_BAUDRATEPRESCALER_2:
|
|
prescaler = 2;
|
|
break;
|
|
case SPI_BAUDRATEPRESCALER_4:
|
|
prescaler = 4;
|
|
break;
|
|
case SPI_BAUDRATEPRESCALER_8:
|
|
prescaler = 8;
|
|
break;
|
|
case SPI_BAUDRATEPRESCALER_16:
|
|
prescaler = 16;
|
|
break;
|
|
case SPI_BAUDRATEPRESCALER_32:
|
|
prescaler = 32;
|
|
break;
|
|
case SPI_BAUDRATEPRESCALER_64:
|
|
prescaler = 64;
|
|
break;
|
|
case SPI_BAUDRATEPRESCALER_128:
|
|
prescaler = 128;
|
|
break;
|
|
case SPI_BAUDRATEPRESCALER_256:
|
|
prescaler = 256;
|
|
break;
|
|
default:
|
|
// Unreachable case
|
|
STA_ASSERT_MSG(false, "Case for SPI_BAUDRATEPRESCALER not handled");
|
|
STA_UNREACHABLE();
|
|
}
|
|
|
|
// SPI clock speed is based of PCLK
|
|
settings.clkSpeed = pclkFreq / prescaler;
|
|
|
|
return settings;
|
|
}
|
|
|
|
|
|
STM32SPI::STM32SPI(SPI_HandleTypeDef * handle, uint32_t pclkFreq, Mutex * mutex)
|
|
: SPI(getSPISettings(handle, pclkFreq), mutex), handle_{handle}
|
|
{
|
|
STA_ASSERT(handle != nullptr);
|
|
}
|
|
|
|
STM32SPI::STM32SPI(const Info & info, Mutex * mutex /* = nullptr */)
|
|
: STM32SPI(info.handle, info.pclkFreq, mutex)
|
|
{}
|
|
|
|
|
|
bool STM32SPI::transfer(uint8_t value, uint32_t timeout /* = STA_MAX_TIMEOUT */)
|
|
{
|
|
if (settings().dataSize == SPIDataSize::SIZE_8)
|
|
{
|
|
return HAL_SPI_Transmit(handle_, &value, 1, timeout) == HAL_OK;
|
|
}
|
|
else
|
|
{
|
|
// Required since tx buffer is cast to uint16_t * internally
|
|
uint16_t dummy = value;
|
|
return HAL_SPI_Transmit(handle_, reinterpret_cast<uint8_t *>(&dummy), 1, timeout) == HAL_OK;
|
|
}
|
|
}
|
|
|
|
bool STM32SPI::transfer16(uint16_t value, uint32_t timeout /* = STA_MAX_TIMEOUT */)
|
|
{
|
|
uint16_t size = 1;
|
|
|
|
// Send as two bytes if data size is 8-bit
|
|
if (settings().dataSize == SPIDataSize::SIZE_8)
|
|
{
|
|
size = 2;
|
|
|
|
if (settings().bitOrder == STA_STM32_SPI_REVERSE_BIT_ORDER)
|
|
{
|
|
// Reverse byte order from internal representation
|
|
value = STA_UINT16_SWAP_BYTE_ORDER(value);
|
|
}
|
|
}
|
|
|
|
return HAL_SPI_Transmit(handle_, reinterpret_cast<uint8_t *>(&value), size, timeout) == HAL_OK;
|
|
}
|
|
|
|
bool STM32SPI::transfer(const uint8_t * buffer, size_t size, uint32_t timeout /* = STA_MAX_TIMEOUT */)
|
|
{
|
|
STA_ASSERT(buffer != nullptr);
|
|
STA_ASSERT(size != 0);
|
|
|
|
return HAL_SPI_Transmit(handle_, const_cast<uint8_t *>(buffer), size, timeout) == HAL_OK;
|
|
}
|
|
|
|
bool STM32SPI::transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size, uint32_t timeout /* = STA_MAX_TIMEOUT */)
|
|
{
|
|
STA_ASSERT(txBuffer != nullptr);
|
|
STA_ASSERT(rxBuffer != nullptr);
|
|
STA_ASSERT(size != 0);
|
|
|
|
return HAL_SPI_TransmitReceive(handle_, const_cast<uint8_t *>(txBuffer), rxBuffer, size, timeout) == HAL_OK;
|
|
}
|
|
|
|
bool STM32SPI::receive(uint8_t * buffer, size_t size, uint32_t timeout /* = STA_MAX_TIMEOUT */)
|
|
{
|
|
STA_ASSERT(buffer != nullptr);
|
|
|
|
return HAL_SPI_Receive(handle_, buffer, size, timeout) == HAL_OK;
|
|
}
|
|
|
|
bool STM32SPI::fill(uint8_t value, size_t count, uint32_t timeout /* = STA_MAX_TIMEOUT */)
|
|
{
|
|
STA_ASSERT(count != 0);
|
|
|
|
if (settings().dataSize == SPIDataSize::SIZE_8)
|
|
{
|
|
for (size_t i = 0; i < count; ++i)
|
|
{
|
|
return HAL_SPI_Transmit(handle_, &value, 1, timeout) == HAL_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Required since tx buffer is cast to uint16_t * internally
|
|
uint16_t dummy = value;
|
|
for (size_t i = 0; i < count; ++i)
|
|
{
|
|
return HAL_SPI_Transmit(handle_, reinterpret_cast<uint8_t *>(&dummy), 1, timeout) == HAL_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
STM32SPIDevice::STM32SPIDevice(STM32SPI * intf, STM32GpioPin * csPin)
|
|
: SPIDevice(intf, csPin)
|
|
{}
|
|
} // namespace sta
|
|
|
|
|
|
#endif // STA_STM32_SPI_ENABLED
|