cancel
Showing results for 
Search instead for 
Did you mean: 

I am trying to use a nucleo-f746zg as a slave using SPI6, but it seems to be dropping the first bit.

CFlec
Associate II

Hey guys,

As I said in the title, I am using SPI6 on my nucleo-f746zg board as a slave. I have it set up to interrupt when a GPIO is low and then it it tries to receive/transmit using the HAL_SPI_TransmitReceive_IT function, but it seems to always interrupt as soon as I call that, instead of waiting for the actual SPI transaction. This is causing one bit to be lost at the beginning. I tried switching it out with the polling version, HAL_SPI_TransmitReceive, and with just a receive, HAL_SPI_Receive, and they both have the same problem. How do I tell the SPI bus to wait until there is an actual SPI transaction? Here are some snippits of my code:

// Set up SPI 6
/**
  * @brief SPI6 Initialization Function
  * @param None
  * @retval None
  */
static void MX_SPI6_Init(void)
{
 
  /* USER CODE BEGIN SPI6_Init 0 */
  // Initialize the Linux SPI.
  g_linux_spi_ptr = LINUX_SPI::GetInstance();
  g_linux_spi_ptr->init();
  g_linux_spi_ptr->config();
 
  /* USER CODE END SPI6_Init 0 */
 
  /* USER CODE BEGIN SPI6_Init 1 */
 
  /* USER CODE END SPI6_Init 1 */
  /* SPI6 parameter configuration*/
  hspi6.Instance = SPI6;
  hspi6.Init.Mode = SPI_MODE_SLAVE;
  hspi6.Init.Direction = SPI_DIRECTION_2LINES;
  hspi6.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi6.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi6.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi6.Init.NSS = SPI_NSS_SOFT;
  hspi6.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi6.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi6.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi6.Init.CRCPolynomial = 7;
  hspi6.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi6.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
  if (HAL_SPI_Init(&hspi6) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI6_Init 2 */
 
  /* USER CODE END SPI6_Init 2 */
}
 
// When a GPIO interrupt is detected on the NSS line, we call this callback.
void LINUX_SPI::linux_spi_int_handler(void)
{
    HAL_SPI_TransmitReceive_IT(&hspi6, &m_transmit_data[0], &m_receive_data[0], m_data_length);
}

What is the proper method of setting up this board as a SPI slave? I must be missing something.

Thanks in advance!!

Charles

3 REPLIES 3
TDK
Guru

If you're reacting to the CS going low, rather than it being ready to send before that, ensure there's enough time for the slave to be ready before the clock is sent. A 1ms delay between the CS edge and the first clock edge is probably sufficient.

> but it seems to always interrupt as soon as I call that

When you start the SPI, the TX buffer is empty (TXE flag is set), and the interrupt is called to fill it. This is expected behavior.

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

I tried adding a delay in the interrupt handler, and it still doesn't seem to work. I've attached an image of what I'm seeing, it seems like no matter how large the delay is, that is what my output always looks like. The data the SPI is reading in is also one bit off, I assume for the same reason. Shouldn't it be waiting for the clock to continue sending data? I'm a little confused how this is supposed to work at all.

Note: I am testing using another SPI on this board as the master. Is there any reason that simply wouldn't work?

Thanks again!!

Charles

0693W00000AOgr0QAD.png

CFlec
Associate II

I've resolved the issue, it ended up that I needed a pull-down on the SPI clock to keep it low at startup.

Thanks!!

Charles