Skip to main content
Visitor II
April 9, 2024
Solved

SPI by hand/prerequisites for SPI

  • April 9, 2024
  • 2 replies
  • 1159 views

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.
    Best answer by Imen.D

    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

    2 replies

    Imen.DAnswer
    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

    mdrAuthor
    Visitor II
    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 :)

    Graduate
    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.