Showing results for 
Search instead for 
Did you mean: 

[STM32H562RG] Simpler SPI transmission

Associate II


I measured my SPI transmission takes ~600 CPU cycles @ 250MHz, so it's about 2,5us to transmit 2x 8-bit array.
I'm using HAL (cube IDE). How can I speed it up? I need to make 4 transmissions like this, so it's ~10us. I need it to work with I2S, so it consumes half of sample time only for SPI transmissions... SPI runs @ 31MHz and I can't speed it up bacause of periphera's speed.


I'm using STM32H562RG; SPI3, only transmit mode on pins PB3 and PB5. I've read I can make SPI only on registers, but I can't make it working. Any suggestions, please?

Associate II

I tried to use this code:
But, even with those missing lines, seems like it stucks at waiting for EOT flag. Of course I have changed this code to my SPI number and pins.

ST Employee

Hello @sebxx4 ,

Check if this is related to the STM32H562 device errata for EOT behavior, as it may apply to your case.

When your question is answered, please close this topic by clicking "Accept as Solution".

Well, I made both workarounds from the errata, but still no effects... It says I could decrease ratio between PCLK (PCLK1 in my case) and SCK frequencies and add some delay between EOT and SPI disable.

So, first I tried to set APB1 to 62.5MHz (/4 prescaler) and set SPI frequency to 31.5MHz (/2 prescaler).

This is my SPI config (of course it's disabled in CUBE IDE):



  HAL_I2SEx_TransmitReceive_DMA(&hi2s1, txBuf, rxBuf, 2);

  CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
  DWT->CYCCNT = 0;

  //Enable SPI3 clock
  //Set PB3 & PB5 as alternate functions
  GPIOB->MODER  = ( GPIOB->MODER  & 0b11111111111111111111001100111111 ) | 0b00000000000000000000100010000000;
  //PB3 (SCK) as AF6, PB5 (MOSI) as AF7
  GPIOB->AFR[0] = ( GPIOB->AFR[0] & 0b11111111000011110000111111111111 ) | 0b00000000011100000110000000000000;
  //MBR = /2 prescaler, DSIZE = 8-bit
  SPI3->CFG1 = 0b00000000000000000000000000000111;
  //AFCNTR = 1, CPOL = 0, CPHA = 0, MSB first, SPI as master, Motorola protocol, simplex transmitter, no pin swap
  SPI3->CFG2 = 0b10000100010000100000000000000000;
  /* USER CODE END 2 */



Transmit function is used like this:



void writeRam ( uint32_t address, int32_t value )
	address *= 2;
	(void)transmit( ( address >> 8 ) & 0xFF );
	(void)transmit( address & 0xFF );




And the transmit function:



void transmit(uint8_t data)
	SPI3->IFCR |= BIT(3);   // Clear EOT flag.
	SPI3->IFCR |= BIT(4);   // Clear TXTF flag.

	SPI3->CR2 = 1;          // Set transfer size = 1.
	SPI3->CR1 |= BIT(0);    // Enable SPI
	SPI3->CR1 |= BIT(9);    // Transfer start.

	SPI3->TXDR = data;      // Load FIFO.

	for ( uint32_t x = 0; x < 128; x++ )
		asm volatile ("add r0,r0,1":::"memory");
		asm volatile ("sub r0,r0,1":::"memory");
	while ( !( SPI3->SR & BIT(3) ) );	//stuck here :(

	SPI3->CR1 &= ~BIT(0);     // Disable SPI



I don't know what size of delay to add, and where exactly to add it, but I think it's only one right place.


BTW - I also noticed, when I'm using CUBE's SPI coltrol interface and change APB1 speed, the SPI clock's speed is still the same as before (31.25MHz with prescaler /8 when APB1 has 250MHz and 31.25MHz when APB1 speed decreased to 62.5MHz). CubeIDE bug?

Associate II

Can anyone help me?

Associate II

@SofLit maybe you could help, Sir?


are you able to see any bus traffic? Have you checked error flags? If I'm not wrong, you should face MODF error once SPI is enabled as software SS management is applied  (SSM=1) while SSI and SSIOP have the same values at your configuration (see figure Scheme of SS control logic at RM). The SS works as input at your case (SSOE=0) preventing possible bus conflicts at multi-master mode. If it is the case, setting SSOE=1 could help (with no need to apply AF at SS pin - see chapter Slave select (SS) pin management at RM). 

Best regards,


@Petr Sladecek @Imen.D  I will try it, but now I found something else. I've replaced 74HC595 with 74LVC595. It can work with much higher clock frequency (max 180MHz) so I set SPI frequency prescaler to /2 (125MHz), but now it doesn't work even using HAL...


I found some problem. Normally, when SPI prescaler is set to /8, HAL_SPI_Transmit() tooks ~700 CPU cycles to transmit 8 bytes. But when I set prescaler to /4 or /2, it tooks ~249k (!) CPU cycles. Why?

Petr Sladecek
ST Employee

You are at blocking mode. What about the loops testing the flags...