cancel
Showing results for 
Search instead for 
Did you mean: 

How do I get 32Mbps SPI?

ASmit.4
Associate II

I’m using the nucleo board, and I’ve got SPI working correctly (mostly) with default settings using CubeIDE. However, the data sheets stated that SPI can run at 32 Mbps, and I’m only getting half that rate.

The SPI Prescaler is set to the minimum value of /2, so I’m guessing I need to change my clock configurations to get up to the max rate?

What do I need to do to get the max SPI rate; because I’m not getting with default settings?

9 REPLIES 9
Remi QUINTIN
ST Employee

What is the source of your system clock?

Could you send a picture of your clock system configuration from CubeMX?

ASmit.4
Associate II

HSE_SYS is the current source of my system clock. I’ve cross posted this question, which includes a pictute of the clock configuration, here:

https://www.reddit.com/r/embedded/comments/g2gigh/how_to_configure_stm32wb_for_maximum_spi_data_rate/?utm_source=share&utm_medium=ios_app&utm_name=iossmf

You'd need to be running AHB/APB clocks at 64 MHz

Probably want to be using DMA, although not sure where you're going to sink that amount of data

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

OK, I've changed my System Clock Mux to PLLCLK, and now my SPI Clock is where I expect it to be. However, I see that my interval between transmitted bytes is 11us. How can I shorten that timing? 0693W000000Vy3vQAC.png

Send larger blocks, use DMA?

What are you sending the data too? Does it need -CS for every byte?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

It does not need CS for every byte. I'm sending data to the ST7789V TFT driver. Thats clearly something I need to look into, but I don't think that should be making the period between bytes so long. Right now I am sending data this way:

/**
 * @brief Write data to ST7789 controller
 * @param buff -> pointer of data buffer
 * @param buff_size -> size of the data buffer
 * @return none
 */
void ST7789_WriteData(uint8_t *buff, size_t buff_size)
{
	ST7789_Select();
	ST7789_DC_Set();
 
	// split data in small chunks because HAL can't send more than 64K at once
 
	while (buff_size > 0) {
		unsigned short chunk_size = buff_size > 65535 ? 65535 : buff_size;
		HAL_SPI_Transmit(&ST7789_SPI_PORT, buff, chunk_size, HAL_MAX_DELAY);
		buff += chunk_size;
		buff_size -= chunk_size;
	}
 
	ST7789_UnSelect();
}

 EDIT: I switched to using the default pins and software enabled NSS, and that trimmed about 2 us off the period, but I'm still dealing with a 9 us period between transmits. The NSS line is switching automatically between transmits, and I don't think that adequately explains the delay.

> HAL_SPI_Transmit

Write your own. Maybe you'll find the explanation for the delays between the frames.

JW

Just a quick follow up here. I checked the timings on the HAL_SPI_Transmit() function, and it appears most of the overhead comes from the HAL function pre and post checking. There's at least 2us burned from the time you enter the function until the first bit is transmitted. I'm going to try a Low Layer SPI implementation and see what that improves.

Once you have your own low level implementation of the SPI routines, try to use DMA, as @Community member​ suggested.

Maybe there are also HAL with DMA routines ?