2024-11-12 12:15 AM
Hello,
I am using the SPI on the STM32H743ZITx as a SPI Master in Full-duplex mode to transfer large data packets (1600 bytes). But instead of seeing the data being transferred in a constant burst, I see it being sent out a byte at a time with gaps in between, apart from a burst at the start of the SPI transaction.
Here is my SPI3 settings in STM32CubeIDE, v1.16.1:
The SPI initialization is the default MX_SPI3_Init() provided by Core/Src/spi.c in STM32CubeIDE.
I am using the interrupt transfer method. My code is as follows:
// TxRx complete callback
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
post_semaphore_from_isr(spi_trans_complete_sem);
}
[...]
// here, size = 1600
spi_transaction(uint8_t * txbuff, uint8_t * rxbuff, uint16_t size)
{
HAL_StatusTypeDef retval = HAL_ERROR;
// code to assert SPI CS (GPIO signal)
retval = HAL_SPI_TransmitReceive_IT(&hspi3, txbuff, rxbuff, size);
// wait for callback for completion
get_semaphore(spi_trans_complete_sem, HAL_MAX_DELAY);
// code to deassert SPI CS (GPIO signal)
return retval;
}
This is what I see on the logic analyzer:
I expect the SPI CLK signal to be continuous during the transfer, instead of a byte-by-byte transfer with gaps in between.
What can I do to push up the performance of the SPI transaction?
2024-11-12 02:12 AM - edited 2024-11-12 02:16 AM
Look at your SPI interrupt handler. Anything causes delays there?
Use DMA instead of interrupt.
Set data width > 8 bits if possible. (for example if data length is always multiple of 4 bytes, set width 32 bits and move data by 32 bits at once).
2024-11-12 02:39 AM
> Look at your SPI interrupt handler. Anything causes delays there?
I'm using the STM32CubeIDE generated Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_spi.c file, so the ISRs in use are the standard SPI_RxISR_8BIT and SPI_TxISR_8BIT defined in that file.
> Use DMA instead of interrupt.
I did try using DMA, but I was not successful in getting the SPI transaction to work. When I enable DMA for SPI Master, are there other settings that must be modified from the default, like using circular DMA, etc?
> Set data width > 8 bits if possible.
I will give this a try.
2024-11-12 02:45 AM
For SPI, DMA is always a way to go, no matter wow small or bi the packets are. To use DMA, make sure that both SPI interrupt and DMA interrupt are enabled.
2024-11-13 02:58 AM
I managed to get DMA working for the SPI.
As I had enabled the data cache, I discovered that I have to use the functions SCB_CleanDCache_by_Addr() and SCB_InvalidateDCache_by_Addr() to send and get the SPI data correctly using DMA. I saw this community post about the data cache:
Is flushing and invalidating the cache the only way to ensure that data is transferred correctly over SPI Full Duplex using DMA?
2024-11-13 03:38 AM
> Is flushing and invalidating the cache the only way to ensure that data is transferred correctly over SPI Full Duplex using DMA?
The other way is (obviously) to define memory used for DMA transfers as shareable & non-cached.