Skip to content

Commit

Permalink
feat: add SPI master for mcu stm32wba (#343)
Browse files Browse the repository at this point in the history
* Add support for SPI in wba family

* fix code review
  • Loading branch information
cassio-lazaro authored Jun 26, 2024
1 parent df738e9 commit 8115ac1
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 91 deletions.
2 changes: 2 additions & 0 deletions hal_st/stm32fxxx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ target_sources(hal_st.stm32fxxx PRIVATE
$<$<STREQUAL:${TARGET_MCU},stm32g474>:DefaultClockNucleoG474RE.hpp>
$<$<STREQUAL:${TARGET_MCU},stm32wb55>:DefaultClockNucleoWB55RG.cpp>
$<$<STREQUAL:${TARGET_MCU},stm32wb55>:DefaultClockNucleoWB55RG.hpp>
$<$<STREQUAL:${TARGET_MCU},stm32wba52>:DefaultClockNucleoWBA52CG.cpp>
$<$<STREQUAL:${TARGET_MCU},stm32wba52>:DefaultClockNucleoWBA52CG.hpp>
DigitalToAnalogPinStm.cpp
DigitalToAnalogPinStm.hpp
$<$<NOT:$<STREQUAL:${TARGET_MCU_FAMILY},stm32g0xx>>:DmaStm.cpp>
Expand Down
11 changes: 7 additions & 4 deletions hal_st/stm32fxxx/DefaultClockNucleoWBA52CG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,27 @@ void ConfigureDefaultClockNucleoWBA52CG()
/* Activate PLL with HSE as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEDiv = RCC_HSE_DIV1;
RCC_OscInitStruct.PLL1.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL1.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL1.PLLFractional = 0;
RCC_OscInitStruct.PLL1.PLLM = 4;
RCC_OscInitStruct.PLL1.PLLN = 25; /* VCO = HSE/M * N = 32 / 4 * 25 = 200 MHz */
RCC_OscInitStruct.PLL1.PLLR = 2; /* PLLSYS = 200 MHz / 2 = 100 MHz */
RCC_OscInitStruct.PLL1.PLLP = 2;
RCC_OscInitStruct.PLL1.PLLQ = 1;
RCC_OscInitStruct.PLL1.PLLQ = 2;
RCC_OscInitStruct.PLL1.PLLFractional = 0;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

/* Select PLL as system clock source and configure the HCLK, PCLK1, PCLK2 and PCLK7
clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 |
RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_PCLK7);
RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_PCLK7 | RCC_CLOCKTYPE_HCLK5);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB7CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4);
RCC_ClkInitStruct.AHB5_PLL1_CLKDivider = RCC_SYSCLK_PLL1_DIV4;
RCC_ClkInitStruct.AHB5_HSEHSI_CLKDivider = RCC_SYSCLK_HSEHSI_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3);
}
73 changes: 48 additions & 25 deletions hal_st/stm32fxxx/SpiMasterStm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace hal
{
EnableClockSpi(spiInstance);

SPI_HandleTypeDef spiHandle;
SPI_HandleTypeDef spiHandle{};
spiHandle.Instance = peripheralSpi[spiInstance];
spiHandle.Init.Mode = SPI_MODE_MASTER;
spiHandle.Init.Direction = SPI_DIRECTION_2LINES;
Expand All @@ -27,19 +27,41 @@ namespace hal
spiHandle.Init.TIMode = SPI_TIMODE_DISABLED;
spiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
spiHandle.Init.CRCPolynomial = 1;
#if defined(STM32F0) || defined(STM32F1) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB)

#ifdef SPI_CRC_LENGTH_DATASIZE
spiHandle.Init.CRCLength = SPI_CRC_LENGTH_8BIT;
#endif
#ifdef SPI_NSS_PULSE_DISABLE
spiHandle.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
#endif
#ifdef SPI_CFG2_RDIMM
spiHandle.Init.ReadyMasterManagement = SPI_RDY_MASTER_MANAGEMENT_INTERNALLY;
#endif
#ifdef SPI_CFG2_RDIOP
spiHandle.Init.ReadyPolarity = SPI_RDY_POLARITY_HIGH;
#endif
#ifdef SPI_CFG1_FTHLV
spiHandle.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
#endif
#ifdef SPI_CR1_MASRX
spiHandle.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
#endif

HAL_SPI_Init(&spiHandle);

#if defined(STM32F0) || defined(STM32F1) || defined(STM32F3) || defined(STM32F7)
#if defined(SPI_CR2_FRXTH)
peripheralSpi[spiInstance]->CR2 |= SPI_RXFIFO_THRESHOLD_QF;
#endif

__HAL_SPI_ENABLE(&spiHandle);
}

SpiMasterStm::~SpiMasterStm()
{
peripheralSpi[spiInstance]->CR1 &= ~SPI_CR1_SPE;
DisableClockSpi(spiInstance);
}

void SpiMasterStm::SendAndReceive(infra::ConstByteRange sendData, infra::ByteRange receiveData, SpiAction nextAction, const infra::Function<void()>& onDone)
{
this->onDone = onDone;
Expand All @@ -64,12 +86,12 @@ namespace hal
HandleInterrupt();
});

#if !defined(STM32WBA)
peripheralSpi[spiInstance]->CR2 |= SPI_IT_TXE;
peripheralSpi[spiInstance]->CR2 |= SPI_IT_RXNE;
#ifdef SPI_IER_RXPIE
peripheralSpi[spiInstance]->IER |= SPI_IER_TXPIE;
peripheralSpi[spiInstance]->IER |= SPI_IER_RXPIE;
#else
peripheralSpi[spiInstance]->CR2 |= SPI_IT_TXP;
peripheralSpi[spiInstance]->CR2 |= SPI_IT_RXP;
peripheralSpi[spiInstance]->CR2 |= SPI_CR2_TXEIE;
peripheralSpi[spiInstance]->CR2 |= SPI_CR2_RXNEIE;
#endif
}

Expand All @@ -95,15 +117,15 @@ namespace hal
void SpiMasterStm::HandleInterrupt()
{
uint32_t status = peripheralSpi[spiInstance]->SR;
#if !defined(STM32WBA)
if ((status & SPI_FLAG_RXNE) != 0)
#ifdef SPI_SR_RXNE
if ((status & SPI_SR_RXNE) != 0)
#else
if ((status & SPI_FLAG_RXWNE) != 0)
if ((status & SPI_SR_RXP) != 0)
#endif
{
if (dummyToReceive != 0)
{
#if !defined(STM32WBA)
#ifdef SPI_DR_DR
(void)peripheralSpi[spiInstance]->DR;
#else
(void)peripheralSpi[spiInstance]->RXDR;
Expand All @@ -112,7 +134,7 @@ namespace hal
}
else if (receiving)
{
#if !defined(STM32WBA)
#ifdef SPI_DR_DR
receiveData.front() = peripheralSpi[spiInstance]->DR;
#else
receiveData.front() = peripheralSpi[spiInstance]->RXDR;
Expand All @@ -123,21 +145,21 @@ namespace hal
receiving &= !receiveData.empty();

if (dummyToReceive == 0 && !receiving)
#if !defined(STM32WBA)
peripheralSpi[spiInstance]->CR2 &= ~SPI_IT_RXNE;
#ifdef SPI_CR2_RXNEIE
peripheralSpi[spiInstance]->CR2 &= ~SPI_CR2_RXNEIE;
#else
peripheralSpi[spiInstance]->CR2 &= ~SPI_IT_RXP;
peripheralSpi[spiInstance]->IER &= ~SPI_IER_RXPIE;
#endif
}
#if !defined(STM32WBA)
if ((status & SPI_FLAG_TXE) != 0)
#ifdef SPI_SR_TXE
if ((status & SPI_SR_TXE) != 0)
#else
if ((status & SPI_FLAG_TXC) != 0)
if ((status & SPI_SR_TXP) != 0)
#endif
{
if (dummyToSend != 0)
{
#if !defined(STM32WBA)
#ifdef SPI_DR_DR
reinterpret_cast<volatile uint8_t&>(peripheralSpi[spiInstance]->DR) = 0;
#else
reinterpret_cast<volatile uint8_t&>(peripheralSpi[spiInstance]->TXDR) = 0;
Expand All @@ -146,10 +168,11 @@ namespace hal
}
else if (sending)
{
#if !defined(STM32WBA)
#ifdef SPI_DR_DR
reinterpret_cast<volatile uint8_t&>(peripheralSpi[spiInstance]->DR) = sendData.front();
#else
reinterpret_cast<volatile uint8_t&>(peripheralSpi[spiInstance]->TXDR) = sendData.front();
peripheralSpi[spiInstance]->CR1 |= SPI_CR1_CSTART;
#endif
sendData.pop_front();
}
Expand All @@ -158,14 +181,14 @@ namespace hal

// After the first transmit, disable interrupt on transmit buffer empty,
// so that a receive is done before each transmit
#if !defined(STM32WBA)
peripheralSpi[spiInstance]->CR2 &= ~SPI_IT_TXE;
#ifdef SPI_CR2_TXEIE
peripheralSpi[spiInstance]->CR2 &= ~SPI_CR2_TXEIE;
#else
peripheralSpi[spiInstance]->CR2 &= ~SPI_IT_TXP;
peripheralSpi[spiInstance]->IER &= ~SPI_IER_TXPIE;
#endif
}

really_assert(!(peripheralSpi[spiInstance]->SR & SPI_FLAG_OVR));
really_assert(!(peripheralSpi[spiInstance]->SR & SPI_SR_OVR));

spiInterruptRegistration->ClearPending();

Expand Down
1 change: 1 addition & 0 deletions hal_st/stm32fxxx/SpiMasterStm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace hal
};

SpiMasterStm(uint8_t oneBasedSpiIndex, GpioPinStm& clock, GpioPinStm& miso, GpioPinStm& mosi, const Config& config = Config(), GpioPinStm& slaveSelect = dummyPinStm);
~SpiMasterStm();

void SendAndReceive(infra::ConstByteRange sendData, infra::ByteRange receiveData, SpiAction nextAction, const infra::Function<void()>& onDone) override;
void SetChipSelectConfigurator(ChipSelectConfigurator& configurator) override;
Expand Down
89 changes: 54 additions & 35 deletions hal_st/stm32fxxx/SpiMasterStmDma.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,50 +9,68 @@ namespace hal
, miso(miso, PinConfigTypeStm::spiMiso, oneBasedSpiIndex)
, mosi(mosi, PinConfigTypeStm::spiMosi, oneBasedSpiIndex)
, slaveSelect(slaveSelect, PinConfigTypeStm::spiSlaveSelect, oneBasedSpiIndex)
#if defined(STM32WBA)
#ifdef SPI_TXDR_TXDR
, tx(transmitStream, &peripheralSpi[spiInstance]->TXDR, 1, [this]()
{
SendDone();
})
, rx(receiveStream, &peripheralSpi[spiInstance]->RXDR, 1, [this]()
{
ReceiveDone();
})
#else
, tx(transmitStream, &peripheralSpi[spiInstance]->DR, 1, [this]()
#endif
{
SendDone();
})
#ifdef SPI_RXDR_RXDR
, rx(receiveStream, &peripheralSpi[spiInstance]->RXDR, 1, [this]()
#else
, rx(receiveStream, &peripheralSpi[spiInstance]->DR, 1, [this]()
#endif
{
ReceiveDone();
})
#endif
{
EnableClockSpi(spiInstance);

SPI_HandleTypeDef hspi;
SPI_HandleTypeDef hspi{};
hspi.Instance = peripheralSpi[spiInstance];
hspi.Init.Mode = SPI_MODE_MASTER;
hspi.Init.Direction = SPI_DIRECTION_2LINES;
hspi.Init.DataSize = SPI_DATASIZE_8BIT;
hspi.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi.Init.CLKPolarity = config.polarityLow ? SPI_POLARITY_LOW : SPI_POLARITY_HIGH;
hspi.Init.CLKPhase = config.phase1st ? SPI_PHASE_1EDGE : SPI_PHASE_2EDGE;
hspi.Init.NSS = SPI_NSS_SOFT;
#if defined(STM32F0) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) || defined(STM32G4)
hspi.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
#endif
hspi.Init.BaudRatePrescaler = config.baudRatePrescaler;
hspi.Init.FirstBit = config.msbFirst ? SPI_FIRSTBIT_MSB : SPI_FIRSTBIT_LSB;
hspi.Init.TIMode = SPI_TIMODE_DISABLED;
hspi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
hspi.Init.CRCPolynomial = 1;

#ifdef SPI_CRC_LENGTH_DATASIZE
hspi.Init.CRCLength = SPI_CRC_LENGTH_8BIT;
#endif
#ifdef SPI_NSS_PULSE_DISABLE
hspi.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
#endif
#ifdef SPI_CFG2_RDIMM
hspi.Init.ReadyMasterManagement = SPI_RDY_MASTER_MANAGEMENT_INTERNALLY;
#endif
#ifdef SPI_CFG2_RDIOP
hspi.Init.ReadyPolarity = SPI_RDY_POLARITY_HIGH;
#endif
#ifdef SPI_CFG1_FTHLV
hspi.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
#endif
#ifdef SPI_CR1_MASRX
hspi.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
#endif
HAL_SPI_Init(&hspi);

__HAL_SPI_ENABLE(&hspi);
EnableDma();
}

SpiMasterStmDma::~SpiMasterStmDma()
{
peripheralSpi[spiInstance]->CR1 &= ~SPI_CR1_SPE;
DisableClockSpi(spiInstance);
}

void SpiMasterStmDma::SendAndReceive(infra::ConstByteRange sendData, infra::ByteRange receiveData, SpiAction nextAction, const infra::Function<void()>& onDone)
{
this->onDone = onDone;
Expand Down Expand Up @@ -112,6 +130,11 @@ namespace hal
}
else
std::abort();

#ifdef SPI_CR1_CSTART
peripheralSpi[spiInstance]->CR1 |= SPI_CR1_CSTART;
#endif
peripheralSpi[spiInstance]->CR1 |= SPI_CR1_SPE;
}

void SpiMasterStmDma::SetChipSelectConfigurator(ChipSelectConfigurator& configurator)
Expand All @@ -136,39 +159,35 @@ namespace hal

void SpiMasterStmDma::SetDataSize(uint8_t dataSizeInBits)
{
DisableDma();
peripheralSpi[spiInstance]->CR1 &= ~SPI_CR1_SPE;
DisableDma();

tx.SetPeripheralTransferSize(dataSizeInBits <= 8 ? 1 : 2);
rx.SetPeripheralTransferSize(dataSizeInBits <= 8 ? 1 : 2);

#if defined(STM32F0) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) || defined(STM32G4)
#if defined(SPI_CR2_DS)
assert(dataSizeInBits >= 4 && dataSizeInBits <= 16);
peripheralSpi[spiInstance]->CR2 = (peripheralSpi[spiInstance]->CR2 & ~SPI_CR2_DS) | ((dataSizeInBits - 1) << POSITION_VAL(SPI_CR2_DS)) | (dataSizeInBits <= 8 ? SPI_CR2_FRXTH : 0);
#elif defined(STM32WBA)
assert(dataSizeInBits == 8 || dataSizeInBits == 16);
peripheralSpi[spiInstance]->CR1 = peripheralSpi[spiInstance]->CR1 & ~SPI_CR1_SPE | (dataSizeInBits == 16 ? SPI_CR1_SPE : 0);
#elif defined(SPI_CFG1_DSIZE)
assert(dataSizeInBits >= 4 || dataSizeInBits <= 32);
peripheralSpi[spiInstance]->CFG1 = (peripheralSpi[spiInstance]->CFG1 & ~SPI_CFG1_DSIZE) | ((dataSizeInBits - 1) << POSITION_VAL(SPI_CFG1_DSIZE));
#else
assert(dataSizeInBits == 8 || dataSizeInBits == 16);
peripheralSpi[spiInstance]->CR1 = peripheralSpi[spiInstance]->CR1 & ~SPI_CR1_DFF | (dataSizeInBits == 16 ? SPI_CR1_DFF : 0);
#endif

peripheralSpi[spiInstance]->CR1 |= SPI_CR1_SPE;

EnableDma();
peripheralSpi[spiInstance]->CR1 |= SPI_CR1_SPE;
}

uint8_t SpiMasterStmDma::DataSize() const
{
#if defined(STM32F0) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) || defined(STM32G4)
#if defined(SPI_CR2_DS)
return ((peripheralSpi[spiInstance]->CR2 & SPI_CR2_DS) >> POSITION_VAL(SPI_CR2_DS)) + 1;
#elif defined(SPI_CFG1_DSIZE)
return ((peripheralSpi[spiInstance]->CFG1 & SPI_CFG1_DSIZE) >> POSITION_VAL(SPI_CFG1_DSIZE)) + 1;
#else
#if !defined(STM32WBA)
if ((peripheralSpi[spiInstance]->CR1 & SPI_CR1_DFF) != 0)
#else
if ((peripheralSpi[spiInstance]->CR1 & SPI_CR1_SPE) != 0)

#endif
return 16;
else
return 8;
Expand Down Expand Up @@ -206,23 +225,23 @@ namespace hal

void SpiMasterStmDma::EnableDma()
{
#if !defined(STM32WBA)
#ifdef SPI_CR2_RXDMAEN
peripheralSpi[spiInstance]->CR2 |= SPI_CR2_RXDMAEN;
peripheralSpi[spiInstance]->CR2 |= SPI_CR2_TXDMAEN;
#else
peripheralSpi[spiInstance]->CR2 |= SPI_CFG1_RXDMAEN;
peripheralSpi[spiInstance]->CR2 |= SPI_CFG1_TXDMAEN;
peripheralSpi[spiInstance]->CFG1 |= SPI_CFG1_RXDMAEN;
peripheralSpi[spiInstance]->CFG1 |= SPI_CFG1_TXDMAEN;
#endif
}

void SpiMasterStmDma::DisableDma()
{
#if !defined(STM32WBA)
#ifdef SPI_CR2_TXDMAEN
peripheralSpi[spiInstance]->CR2 &= ~SPI_CR2_TXDMAEN;
peripheralSpi[spiInstance]->CR2 &= ~SPI_CR2_RXDMAEN;
#else
peripheralSpi[spiInstance]->CR2 &= ~SPI_CFG1_TXDMAEN;
peripheralSpi[spiInstance]->CR2 &= ~SPI_CFG1_RXDMAEN;
peripheralSpi[spiInstance]->CFG1 &= ~SPI_CFG1_TXDMAEN;
peripheralSpi[spiInstance]->CFG1 &= ~SPI_CFG1_RXDMAEN;
#endif
}
}
Loading

0 comments on commit 8115ac1

Please sign in to comment.