cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H743 does not set EOT-Bit when SCK is to high

Vin.CE
Associate II

Hello STM community,

I am currently trying to get my Nucleo STM32H743ZI2 to send data via SPI to a different chip.

Im using CubeMX to generate a lot of the setup code as I´m pretty new to this chip. For the same reason, I use the HAL.

The basic configuration is:

  • The STM32H7 is the master
  • I'm using SPI1 with SCK on PB3 and MOSI on PB5
  • 2 Line TxOnly
  • Data Size 8 Bits
  • NSS disabled
  • spi_ker_ck = 80 Mhz, coming from PLL1 DivQ
  • AXI Peripheral Clock = 200 Mhz
  • APB1/2 Peripheral Clock = 100Mhz

My main loop just tries to send out data repeatedly

status = HAL_SPI_Transmit(&hspi1, &buffer, 8, 1);
HAL_Delay(1);

If I set my prescaler to, lets say 8, I can see the data being transmitted with my logic analyzer without a problem. I can also see the EOT bit getting set in the SPI2S_SR register.

If I set my prescaler any higher though problems occur. I can still see the transmissions on my logic analyzer. The timing is much worse though.

After some investigating, I found the function

SPI_WaitOnFlagUntilTimeout(hspi, SPI_FLAG_EOT, RESET, tickstart, Timeout)

in stm32h7xx_hal_spi.c which is the culprit. The library tries to busy wait for the EOT flag to get set which does no longer happen when i choose any prescaler >=8.

If I use the Interrupt or DMA mode to get around the busy waiting, I can only transmit once. Afterwards the functions returns HAL_BUSY. I think this supports that the EOT bit is not getting set.

What I have done:

  • I have tried to increase the spi_pclk, in case the register access is to slow
  • I confirmed that the peripheral clocks are active both for GPIOB (AHB3ENR bit 1) and SPI1 (ABP2ENR bit 12)
  • I tried out normal Full Duplex Mode with no change.
  • I tried to write a smaller value into the SPI_CR2->TSIZE field. This resulted in fewer bytes being transmitted. The problem was still the same, EOT bit was not getting set
  • I´ve tried to use a completely new project with only the SPI1 interface activated. This did also not change anything.
  • A whole lot of trial and error, mostly error.

I also found the stm32h47s errata sheet where 2.14.2 sounded like it could be related, but the clocks are pretty much the other way around.

What my questions are:

  • Am I mistaken about which clock in CubeMx ends up as spi_ker_ck?

0693W00000BbC8eQAF.png

  • Is there anything that I am missing, as to why the EOT bit might not get set?

For completeness sake, here are my init functions (CubeMx generated)

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 
  /** Supply configuration update enable
  */
  HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
 
  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 400;
  RCC_OscInitStruct.PLL.PLLP = 2;
  RCC_OscInitStruct.PLL.PLLQ = 5;
  RCC_OscInitStruct.PLL.PLLR = 2;
  RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1;
  RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  RCC_OscInitStruct.PLL.PLLFRACN = 0;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                              |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV2;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES_TXONLY;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 0x0;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
  hspi1.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
  hspi1.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
  hspi1.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
  hspi1.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
  hspi1.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
  hspi1.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
  hspi1.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
  hspi1.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
  hspi1.Init.IOSwap = SPI_IO_SWAP_DISABLE;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }

Thanks for your help

-Vincent

7 REPLIES 7
TDK
Guru

Try using a 1000ms timeout. The 1ms min timeout value could be messing with the logic.

Monitor the return value and do something useful about it when it's not HAL_OK to reduce debugging time.

If you feel a post has answered your question, please click "Accept as Solution".
Pavel A.
Evangelist III

There's some errata for the EOT behavior, maybe it applies to your case.

Vin.CE
Associate II

Thanks for the reply. I forgot to add that to the list of things i´ve tried.

Due to the EOT flag not being set, the SPI_WaitOnFlagUntilTimeout func actually blocks the CPU for the entire timeout length. If I set it to 1000ms, I am blocked for 1000ms.

The behavior does not change.

Hey, thanks.

Are you referring to the stm32h743´s "silicon" errata (especially the 2.14.2) or is there some other sheet I have missed?

I can't see anything else wrong with it. The errata is not applicable in this case as I interpret it.

If you feel a post has answered your question, please click "Accept as Solution".

Yes, this. I had to use workaround #3, could not get EOT reliably.

lordinarynathan
Associate

Came across this post while debugging something very similar today.  In my case, I found out that the EOT bit wasn't getting flipped because SCK wasn't toggling, and SCK wasn't toggling because the GPIO "Maximum output speed" on the SPI pins was still set to "Low" and needed to be changed to "Very High".

It'd be a nice feature if STMCubeMX would cross-check the SPI clocks - it already has this in the Baud Rate field - and make sure the GPIO output speeds are configured to match.