cancel
Showing results for 
Search instead for 
Did you mean: 

Changing from SPI Slave to Master during runtime STM32F4 using HAL

FDomi.1
Associate

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

0 REPLIES 0