Skip to main content
Associate
April 9, 2024
Solved

SPI by hand/prerequisites for SPI

Hi,

I've been trying to adapt the current SPI driver in RIOT OS to support the U5 series(STM32U585AI), due to my lack of success I've been trying to sidestep RIOT for a moment and try to do must of the setup manually. But so far I have not been able to get SPI3 to output anything, not even an SCLK signal, leading me to believe that I've just missed something simple like some clock domain etc. 

 

My approach so far:

  1. enable HSI clock
  2. enable VddIO2
  3. select HSI timer for SPI3
  4. enable SPI3 peripheral
  5. enable GPIO ports B & G
  6. reset SPI3 CR1
  7. write SPI3 CFG1, CFG2, CR2
  8. set SPE, SSI bits in CR1
  9. set CSTART in CR1
  10. read write to TXDR, RXDR

However step 8, specifically setting the SPE is where the problem becomes apparent, the SPE bit does not stay enabled. Does anyone have any hints on where to look to get this running?

 

Snippiet I've been using so far, spi_init* and stmclk_enable* are provied by RIOT:

 

 

 stmclk_enable_hsi();
 stmclk_enable_lfclk();
 // spi_init(0);
 // spi_init_pins(0);
 // spi_acquire(0, spi_config[0].cs_pin, SPI_MODE_0, SPI_CLK_10MHZ);
 // spi_transfer_bytes(0, spi_config[0].cs_pin, false, "Hello World", NULL,
 // strlen("Hello World")); spi_release(0);

 // enable vddio2
 PWR->SVMCR |= PWR_SVMCR_IO2SV;

 // set SPI3 clk to HSI
 RCC->CCIPR3 &= ~RCC_CCIPR3_SPI3SEL_Msk;
 RCC->CCIPR3 |= RCC_SPI3CLKSOURCE_HSI;
 assume(RCC->CCIPR3 & RCC_SPI3CLKSOURCE_HSI);

 // enable peripheral
 RCC->APB3ENR |= RCC_APB3ENR_SPI3EN;
 assume(RCC->APB3ENR & RCC_APB3ENR_SPI3EN);

 RCC->APB3RSTR &= ~RCC_APB3ENR_SPI3EN;
 // enable GPIO ports
 RCC->AHB2ENR1 |= RCC_AHB2ENR1_GPIOGEN | RCC_AHB2ENR1_GPIOBEN;
 assume(RCC->AHB2ENR1 & (RCC_AHB2ENR1_GPIOGEN | RCC_AHB2ENR1_GPIOBEN));

 spi_init_pins(0);
 assume(spi_init_cs(0, spi_config[0].cs_pin) == SPI_OK);

 const char *MSG = "Hello World";
 const int MSG_LEN = strlen(MSG);
 volatile char recv_buf[MSG_LEN];

 // reset SPI
 SPI3->CR1 = 0;
 {
 // SPE must be 0 to write CFG{1,2}
 assume((SPI3->CR1 & SPI_CR1_SPE) == 0);
 SPI3->CFG1 = 0b1100000000000000111 | (3 << 29);
 SPI3->CFG2 = 0b1000100010000000000000000000000;

 SPI3->CR2 = (uint16_t)MSG_LEN;
 }
 SPI3->CR1 |= SPI_CR1_SPE | SPI_CR1_SSI;
 assume(SPI3->CR1 & SPI_CR1_SPE);
 SPI3->CR1 |= SPI_CR1_CSTART;

 volatile uint8_t *TXDR = (uint8_t *)&SPI3->TXDR;
 volatile uint8_t *RXDR = (uint8_t *)&SPI3->RXDR;

 for (uint16_t rx_rem = strlen(MSG), tx_rem = strlen(MSG);
 rx_rem > 0 && tx_rem > 0 && !(SPI3->SR & SPI_SR_EOT);) {
 if (SPI3->SR & SPI_SR_TXP && tx_rem) {
 *TXDR = MSG[MSG_LEN - tx_rem];
 tx_rem--;
 }
 if (SPI3->SR & SPI_SR_RXP && rx_rem) {
 recv_buf[MSG_LEN - rx_rem] = *RXDR;
 rx_rem--;
 }
 }
 while (!(SPI3->SR & SPI_SR_EOT)) {
 }

 

 

 

This topic has been closed for replies.
Imen.DBest answer
ST Technical Moderator
April 9, 2024

Hello @mdr and welcome to the Community :)

It seems you have encountered the condition when "SPE may not be cleared upon MODF event".

Please check the STM32U585xx errata sheet  (2.22.5 section) for more details.

ImenD_0-1712664810487.png

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks

3 replies

Imen.DBest answer
ST Technical Moderator
April 9, 2024

Hello @mdr and welcome to the Community :)

It seems you have encountered the condition when "SPE may not be cleared upon MODF event".

Please check the STM32U585xx errata sheet  (2.22.5 section) for more details.

ImenD_0-1712664810487.png

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
mdrAuthor
Associate
April 9, 2024

Thanks for the swift reply, putting an 

while (SPI3->SR & SPI_SR_MODF) { SPI3->IFCR |= SPI_IFCR_MODFC;}

before writing the SPE bit solved the issue :)

gbm
Super User
April 9, 2024

You need to set GPIO AFR and MODER registers correctly to route SPI signals to port pins. See the RefMan and Data Sheet AFN table.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice