2024-04-01 07:38 AM - last edited on 2024-04-01 10:55 AM by Peter BENSCH
Hello,
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?
2024-04-02 11:38 PM
I tried to use this code: https://community.st.com/t5/stm32-mcus-products/stm32h563-spi/td-p/586231
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.
2024-04-03 04:01 AM
Hello @sebxx4 ,
Check if this is related to the STM32H562 device errata for EOT behavior, as it may apply to your case.
2024-04-05 12:44 AM - edited 2024-04-05 01:08 AM
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):
/* USER CODE BEGIN 2 */
HAL_I2SEx_TransmitReceive_DMA(&hi2s1, txBuf, rxBuf, 2);
HAL_TIM_Base_Start_IT(&htim15);
HAL_TIM_Base_Start_IT(&htim16);
HAL_TIM_Base_Start_IT(&htim17);
//DWT
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
//SPI3
//Enable SPI3 clock
__HAL_RCC_SPI3_CLK_ENABLE();
//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?
2024-04-07 02:54 AM
Can anyone help me?
2024-04-08 10:31 PM
@SofLit maybe you could help, Sir?
2024-04-10 07:46 AM
Hello,
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
2024-04-15 05:39 AM - edited 2024-04-15 06:16 AM
@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...
EDIT:
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?
2024-04-17 03:44 AM
You are at blocking mode. What about the loops testing the flags...