Skip to main content
FDomi.1
Associate
April 15, 2021
Question

Changing from SPI Slave to Master during runtime STM32F4 using HAL

  • April 15, 2021
  • 0 replies
  • 1668 views

I am trying to make two STM32F4 with HAL communicate through SPI Simplex mode by changing who is the master node when it's ready to send a message. Both of the platforms start as a slave and they change to master to send a message and then go back to slave.

while (1)
 {
 configSlave();
 
 while(HAL_SPI_GetState(&hspi1) == HAL_SPI_STATE_BUSY_RX);
 HAL_SPI_Receive(&hspi1, (uint8_t *)buff, 13, 1000); /* Including this line generates the issue */
 
 HAL_Delay(10);
 
 configMaster();
 
 HAL_Delay(10);
 
 sendHelloWorld();
 HAL_Delay(10);
 }

Changing the SPI configuration using configMaster() after configSlave() without calling the receive routine HAL_SPI_Receive() works great. However, my problem comes if I add the receive routine in between.

If I add the HAL_SPI_Receive() in between the configurations when I change the node to master the node will then start sending a constant clock through the CLK pin and bring low the DATA pin until I send the Hello World message. So why could this be happening? Is it a deinitialization problem?

I made sure to deinitialize the SPI peripheral before reconfiguring to each mode and went through the debug mode to check that the SPI register was 0 during deinitialization. Similarly, I made sure to reset to 0 every time the global SPI handler so it would not keep some config from the other mode.

0693W000008zf4NQAQ.pngFor reference, these are my configMaster() and configSlave() routines:

static void configMaster(void)
{
 if(HAL_SPI_DeInit(&hspi1) != HAL_ERROR)
 {
 memset(&hspi1, 0, sizeof(SPI_HandleTypeDef));
 
 /* SPI1 parameter configuration*/
 hspi1.Instance = SPI1;
 hspi1.Init.Mode = SPI_MODE_MASTER;
 hspi1.Init.Direction = SPI_DIRECTION_2LINES;
 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_256;
 hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
 hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
 hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
 hspi1.Init.CRCPolynomial = 10;
 
 if (HAL_SPI_Init(&hspi1) != HAL_OK)
 {
 Error_Handler();
 }
 }
}
 
static void configSlave(void)
{
 if(HAL_SPI_DeInit(&hspi1) != HAL_ERROR)
 {
 /* SPI1 parameter configuration*/
 hspi1.Instance = SPI1;
 hspi1.Init.Mode = SPI_MODE_SLAVE;
 hspi1.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
 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.FirstBit = SPI_FIRSTBIT_MSB;
 hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
 hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
 hspi1.Init.CRCPolynomial = 10;
 
 if (HAL_SPI_Init(&hspi1) != HAL_OK)
 {
 Error_Handler();
 }
 
 }
}

Also the exact point where the master starts sending the clock happens here: HAL_SPI_Init()

 /*----------------------- SPIx CR1 & CR2 Configuration ---------------------*/
 /* Configure : SPI Mode, Communication Mode, Data size, Clock polarity and phase, NSS management,
 Communication speed, First bit and CRC calculation state */
 WRITE_REG(hspi->Instance->CR1, (hspi->Init.Mode | hspi->Init.Direction | hspi->Init.DataSize |
 hspi->Init.CLKPolarity | hspi->Init.CLKPhase | (hspi->Init.NSS & SPI_CR1_SSM) |
 hspi->Init.BaudRatePrescaler | hspi->Init.FirstBit | hspi->Init.CRCCalculation));

Any suggestion is welcomed. Thanks

This topic has been closed for replies.