2024-04-09 01:41 AM - edited 2024-04-09 01:55 AM
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:
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)) {
}
Solved! Go to Solution.
2024-04-09 05:22 AM
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.
2024-04-09 05:22 AM
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.
2024-04-09 07:43 AM
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.
2024-04-09 09:16 AM
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 :)