#include #ifdef STA_STM32_SPI_ENABLED #include #include #include #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(&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(&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(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(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(&dummy), 1, timeout) == HAL_OK; } } } STM32SPIDevice::STM32SPIDevice(STM32SPI * intf, STM32GpioPin * csPin) : SPIDevice(intf, csPin) {} } // namespace sta #endif // STA_STM32_SPI_ENABLED