cancel
Showing results for 
Search instead for 
Did you mean: 

strange behaviour of SPI2 of STM32H745I-DISCO board

DR77
Visitor

Hi, guys,

     I've bought STM32H745I-DISCO board to make an EtherCAT master, so I successfully employ EtherNet controller, USART3 for debugging but SPI2 has a problem. (I'm mostly novice fir H745)

     I decided to use SPI2 for communication with external STM32F4xx controller, which exchanges 26 16-bit words with H745 board within 10kHz time frame, so it's a bit loaded communication. The attached picture renders the snapshot from logical analyser. 4 upper lines are SPI lines, other 3 lines are GPIOs used for debugging purposes - to show interrupt work.
    The picture clearly shows that physical lines exchange data - I see expected 26 16-bit words from F4xx and data sent from H745 - in all cycles the picture is the same. But in reality I see only one time words from 4 to 22 in receive buffer (other appears to be zero), after that they are not updated at all. So receive is fault always. SPI2 is used in DMA mode via library function (code is below), also the picture shows that the output buffer is sent correctly. After 26 words reception I have an interrupt from SPI (lower right corner on picture). Each 10kHz I have strobe interrupt from F4xx, which is also properly serviced (lower left part of picture).
      For SPI pins D10-D13 are used  at "Arduino slot"

      So I definitely need some kind advice where I'm wrong. The code was in part generated by Cube IDE. Initially it was a (working) TCP/IP example, redone for (working) EtherCAT stack, so I've added USART3 for debugging (works well) and SPI2. I have checked the pins assignment, do not see problems, GPIO for SPI2 looks also be well configured. Clock sub-system looks to be identical. DMA works to send data in proper way. I will try another board tomorrow for any chance....


     The strobe interrupt code:

void slave_cb(void)
{
	HAL_StatusTypeDef spi_status;
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET); // arduino pin d5
	if (1)
	{
		pin2_3_cnt[0]++; // statistics
		if (1 != G_DR)
		{  // error
			HAL_GPIO_WritePin(GPIOI, GPIO_PIN_8, GPIO_PIN_SET); // arduino pin d7
			spi_status = HAL_SPI_TransmitReceive_DMA(&hspi2, (uint8_t*)TX_SPI_data, (uint8_t*)RX_SPI_data, TRANSFER_LEN*2);
			if (HAL_OK == spi_status)
			{  HAL_GPIO_WritePin(GPIOE, GPIO_PIN_6, GPIO_PIN_SET);  } // pin D6
			else {  HAL_GPIO_WritePin(GPIOE, GPIO_PIN_6, GPIO_PIN_RESET);  }
			HAL_GPIO_WritePin(GPIOI, GPIO_PIN_8, GPIO_PIN_RESET); // arduino pin d7
		}
		G_DR = 0;
	}
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); // arduino pin d5
	HAL_GPIO_WritePin(GPIOE, GPIO_PIN_6, GPIO_PIN_RESET); // D6
}

 The picture shows that D6 line is set after correct exit from HAL_SPI_TransmitReceive_DMA() function
The SPI receive buffer interrupt code:

void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
	HAL_GPIO_WritePin(GPIOE, GPIO_PIN_6, GPIO_PIN_SET); // arduino pin d6
    no_recv++;
	if (HAL_SPI_ERROR_NONE != hspi->ErrorCode)
	{   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET); // arduino pin d5
		G_DR = -1;
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); // arduino pin d5
	}
	else
	{
		uint32_t psum = 0;
		// check control sum
		// uint32_t* b32p = (uint32_t*)RX_SPI_data;
		for(int ii=0; ii<TRANSFER_LEN-1; ii++)  {  psum += RX_SPI_data[ii];    } 
		int idx = ((psum != RX_SPI_data[TRANSFER_LEN-1]) ? 1 : 0); // 1 on error 
		if (1 == idx) // only for Breakpoint
		{ 	HAL_GPIO_WritePin(GPIOI, GPIO_PIN_8, GPIO_PIN_SET); // D7
		    G_DR = 0;
		    for (int ii=0; ii<TRANSFER_LEN-2; ii++)  {  RX_SPI_data[ii] = 0x0; } }
		    RX_SPI_data[TRANSFER_LEN-2] = no_recv;
		    RX_SPI_data[TRANSFER_LEN-1] = 0xAA55AA55;
		    HAL_GPIO_WritePin(GPIOI, GPIO_PIN_8, GPIO_PIN_RESET); // D7
		} // error
		else
		{	corr_rcv[idx]++;
			G_DR = 1; // received state OK
			G_RCV = 1; // received status
			HAL_GPIO_WritePin(GPIOE, GPIO_PIN_6, GPIO_PIN_RESET); // arduino pin d6
			spi_status = HAL_SPI_TransmitReceive_DMA(&hspi2, (uint8_t*)TX_SPI_data, (uint8_t*)RX_SPI_data, TRANSFER_LEN*2);
		    HAL_GPIO_WritePin(GPIOE, GPIO_PIN_6, GPIO_PIN_SET); // arduino pin d6
		}
	}
	HAL_GPIO_WritePin(GPIOE, GPIO_PIN_6, GPIO_PIN_RESET); // arduino pin d6
}

 This code computes the control sum but it is never OK
 Code to init GPIO (external interrupt and "debugging" pins)

static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  GPIO_InitTypeDef GPIO_InitStruct_D5 = {0};
  GPIO_InitTypeDef GPIO_InitStruct_D6 = {0};
  GPIO_InitTypeDef GPIO_InitStruct_D7 = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  // ABCxExGHIxK
  __HAL_RCC_GPIOG_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOE_CLK_ENABLE();
  __HAL_RCC_GPIOI_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOK_CLK_ENABLE();

  /*Configure GPIO pin : intr_spi_Pin */
  GPIO_InitStruct.Pin = intr_spi_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(intr_spi_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : D5 (PA8) */
  GPIO_InitStruct_D5.Pin = GPIO_PIN_8;
  GPIO_InitStruct_D5.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct_D5.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct_D5);

  /*Configure GPIO pin : D6 (PE6) */
  GPIO_InitStruct_D6.Pin = GPIO_PIN_6;
  GPIO_InitStruct_D6.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct_D6.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct_D6);

  /*Configure GPIO pin : D7 (PI8) */
  GPIO_InitStruct_D7.Pin = GPIO_PIN_8;
  GPIO_InitStruct_D7.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct_D7.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOI, &GPIO_InitStruct_D7);

  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI1_IRQn);

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

 Code to init SPI2:

static void MX_SPI2_Init(void)
{
  hspi2.Instance = SPI2;
  hspi2.Init.Mode = SPI_MODE_SLAVE;
  hspi2.Init.Direction = SPI_DIRECTION_2LINES;
  hspi2.Init.DataSize = SPI_DATASIZE_16BIT;
  hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
  hspi2.Init.NSS = SPI_NSS_SOFT ; // SPI_NSS_HARD_INPUT;
  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi2.Init.CRCPolynomial = 0x0;
  hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
  hspi2.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
  hspi2.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
  hspi2.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
  hspi2.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
  hspi2.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
  hspi2.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
  hspi2.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
  hspi2.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
  hspi2.Init.IOSwap = SPI_IO_SWAP_DISABLE;
  if (HAL_SPI_Init(&hspi2) != HAL_OK)
  {
    Error_Handler();
  }

}

 Code to init DMA channels and map SPI2 pins to proper pins on board:

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  // HAL_DMA_MuxSyncConfigTypeDef pSyncConfig;
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  if(hspi->Instance==SPI2)
  {
  /** Initializes the peripherals clock
  */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI2;
    PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
      Error_Handler();
    }

    /* Peripheral clock enable */
    __HAL_RCC_SPI2_CLK_ENABLE();

    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOD_CLK_ENABLE();
    __HAL_RCC_GPIOI_CLK_ENABLE();
    /**SPI2 GPIO Configuration
    PB4 (NJTRST)     ------> SPI2_NSS
    PD3     ------> SPI2_SCK
    PI2     ------> SPI2_MISO
    PB15     ------> SPI2_MOSI
    */
    GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_SPI2;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_15;
    GPIO_InitStruct.Mode = MODE_AF;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* SPI2 DMA Init */
    /* SPI2_RX Init */
    hdma_spi2_rx.Instance = DMA1_Stream0;
    hdma_spi2_rx.Init.Request = DMA_REQUEST_SPI2_RX;
    hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_spi2_rx.Init.Mode = DMA_NORMAL; // CIRCULAR;
    hdma_spi2_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
    hdma_spi2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_spi2_rx) != HAL_OK)
    {
      Error_Handler();
    }
   
    __HAL_LINKDMA(hspi,hdmarx,hdma_spi2_rx);

    /* SPI2_TX Init */
    hdma_spi2_tx.Instance = DMA1_Stream1;
    hdma_spi2_tx.Init.Request = DMA_REQUEST_SPI2_TX;
    hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_spi2_tx.Init.Mode = DMA_NORMAL; // CIRCULAR;
    hdma_spi2_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
    hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK)
    {
      Error_Handler();
    }

     __HAL_LINKDMA(hspi,hdmatx,hdma_spi2_tx);

    /* SPI2 interrupt Init */
    HAL_NVIC_SetPriority(SPI2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(SPI2_IRQn);

  }

}

 Additional DMA interrupts init:

static void MX_DMA_Init(void)
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
  /* DMA1_Stream1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
}

 

1 REPLY 1
TDK
Guru

> But in reality I see only one time words from 4 to 22 in receive buffer (other appears to be zero), after that they are not updated at all.

Where are you seeing these exactly? With execution paused in debugging mode?

You have no cache management calls, so ensure data cache is disabled.

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