cancel
Showing results for 
Search instead for 
Did you mean: 

SPI DMA Multi-master

MBohm
Associate II

Hello

Im trying to implement the SPI "multimaster" functionality described in this_doc.

SPI networks can operate in a multi-master environment.  This mode is used to connect two master nodes exclusively. When either node is not active, they are by default in a slave mode. When one node wants to take control of the bus, it switches itself into Master mode and asserts the Slave Select signal on the other node through a GPIO pin. Both Slave Select NSS pins work as a hardware input to detect potential bus collisions between nodes as only one can master the SPI bus at a single time.  After the session is done, the active node master releases the Slave Select signal and returns back to passive slave mode waiting for the next session start

I wonder what they mean by "switching to master mode"?

Do I use seperate handles for slave and master?

Or how is this done in practice?

What about open DMA jobs? Should a slave job be active at all times? And when "switching to master" should the slave DMA job be aborted?

Does anyone have any experience with this?

Thank you in advance!

BR Mikael

2 REPLIES 2
TDK
Guru

The SPI_CR1_MSTR bit is used to switch between master/slave mode.

HAL is set up to use only a single handle per peripheral. You could deinit, change settings, and reinit the peripheral, or roll your own software.

DMA jobs definitely need stopped when you switch modes. Presumably, you are changing what data is sent.

If you feel a post has answered your question, please click "Accept as Solution".
MBohm
Associate II
while(1)
{
    HAL_SPI_Receive_DMA(&SpiHandleSlave,(uint8_t*)aRxBuffer, BUFFERSIZE);
 
 
    while (HAL_SPI_GetState(&SpiHandleSlave) == HAL_SPI_STATE_BUSY_RX)
    {
      if (mastersendtrigger) {
        if (HAL_GPIO_ReadPin(SPI_CS_Port, SPI_CS_Pin) ==GPIO_PIN_RESET) {
          
          HAL_GPIO_WritePin(SPI_MASTER_TRIG_Port, SPI_MASTER_TRIG_Pin, GPIO_PIN_SET);
 
          //are all of these necessary? Thinking that the dma channels and pins needs to be "unlinked" from Spi slave handle?
          status = HAL_SPI_DMAStop(&SpiHandleSlave) ;
          status = HAL_SPI_Abort(&SpiHandleSlave);
          status = HAL_SPI_DeInit(&SpiHandleSlave) ;
 
          setupSpiHandle(&SpiHandleMaster) ;
          SpiHandleMaster.Init.Mode = SPI_MODE_MASTER;
          if(HAL_SPI_Init(&SpiHandleMaster) != HAL_OK)
          {
            // Initialization Error
          }
 
          status = HAL_SPI_Transmit_DMA(&SpiHandleMaster, (uint8_t*)aTxBuffer, BUFFERSIZE) ;
          if( status != HAL_OK)
          {
            // Transfer error in transmission process
 
          }
 
          while((HAL_SPI_GetState(&SpiHandleMaster) == (HAL_SPI_STATE_BUSY_TX))){
          }
 
          //HAL_SPI_DMAStop(&SpiHandleMaster) ;
          HAL_SPI_Abort(&SpiHandleMaster);
 
          HAL_SPI_DeInit(&SpiHandleMaster) ;
          HAL_GPIO_WritePin(SPI_MASTER_TRIG_Port, SPI_MASTER_TRIG_Pin, GPIO_PIN_RESET);
          setupSpiHandle(&SpiHandleSlave) ;
          SpiHandleSlave.Init.Mode = SPI_MODE_SLAVE;
          if(HAL_SPI_Init(&SpiHandleSlave) != HAL_OK)
          {
            // Initialization Error
 
          }
        }
      }
}

Thank you for your response, Ive just pasted a section of the code here which I use only to test the procedure, but Im not sure what parts I need to abort/stop/deinit