cancel
Showing results for 
Search instead for 
Did you mean: 

SPI multislave implementation - what am i doing wrong ? (solved)

Tom Schrauf
Associate II

Hello community !

The last part needed for my implementation is an MCU to MCU multislave communication.

From a hardware point of view LTC6820 (isoSPI) devices will be used attached to an STM32F4 on the host side and up to 10 STM32F103 as slaves.

The LTC6820 will drive CS low software driven to allow the slaves to wakeup from sleep and have their SPI ports setup (this is done in EXTI ISR).

The master STM32F4 uses DMA buffering for both Xmit and Receive.

In order to analyze the incoming SPI frames i setup the STM32F103 to use interrupts for receiving and start communication in "SPI_Direction_2Lines_RxOnly" Mode (i.e. Bit 10 rxonly is 1). The slaves shall send their response only when addressed (i.e: address matches) and i wanted to use TXDMA (DMA1Channel5). For this reason all slaves have their DMA setup accordingly and whichever of them is addressed starts transmission after the command block was received with the matching address.

So after the command block of 8 bytes the RX ISR switches off Bit 10 and I thought this would trigger transmission but it does not.

I also tried to disable SPI - reset bit - enable SPI again, do a full reinit, reinit DMA ... nothing helped.

In the RM0008 on page 743 it is mentioned that this bit is intended to be used in multislave applications but what am i doing wrong here ? SPI2 is functional and bytes are received as intended only the slave transmission hesitates to start. Which "kick" is necessary to start transmission ?

Thanks, Tom

edit: so the problem was the DMA configuration in my case (Peripherial address). In the RXInterrupt after knowing that the address matches:

            SPI_Cmd( SPI2, DISABLE );

            SPI2->CR1 &= ~SPI_Direction_2Lines_RxOnly;

            DMA_Cmd( SPI2_XMIT_DMA, ENABLE );

            SPI2->CR2 |= 0x0002; // SPI_I2S_DMACmd( SPI2, SPI_I2S_DMAReq_Tx, ENABLE );

            SPI_Cmd( SPI2, ENABLE );

the RDONLY bit is reset and the slave starts responding at the next character.

0693W00000Hq7hdQAB.jpg 

pinConfiguration spi2pinsMasterRole[] = {

   { GPIOB, { GPIO_Pin_12, GPIO_Speed_50MHz, GPIO_Mode_IPU } }          // CR from LTC6820

   ,{ GPIOB, { GPIO_Pin_13, GPIO_Speed_50MHz, GPIO_Mode_AF_PP } }       // SPI2 CLK

   ,{ GPIOB, { GPIO_Pin_14, GPIO_Speed_50MHz, GPIO_Mode_AF_OD } }       // SPI2 MISO

   ,{ GPIOB, { GPIO_Pin_15, GPIO_Speed_50MHz, GPIO_Mode_AF_PP } }       // SPI2 MOSI

};

pinConfiguration spi2pinsSlaveRole[] = {

   { GPIOB, { GPIO_Pin_12, GPIO_Speed_50MHz, GPIO_Mode_IPU } }          // CS from LTC6820

   ,{ GPIOB, { GPIO_Pin_13, GPIO_Speed_50MHz, GPIO_Mode_AF_OD } }       // SPI2 CLK

   ,{ GPIOB, { GPIO_Pin_14, GPIO_Speed_50MHz, GPIO_Mode_AF_OD } }       // SPI2 MISO

   ,{ GPIOB, { GPIO_Pin_15, GPIO_Speed_50MHz, GPIO_Mode_AF_OD } }       // SPI2 MOSI

};

   SPI_StructInit( &SPI_InitStructure );

   SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

   if (!isMaster) {

       initPins( spi2pinsSlaveRole, ARRAY_SIZE(spi2pinsSlaveRole) );

      SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;

       SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_RxOnly;

       SPI_I2S_ITConfig( SPI2, SPI_I2S_IT_RXNE, ENABLE );

       SPI_I2S_DMACmd( SPI2, SPI_I2S_DMAReq_Tx, ENABLE );

       NVIC_SetPriority(SPI2_IRQn, 1); // very high priority

       NVIC_EnableIRQ( SPI2_IRQn );

   }

   else {

        initPins( spi2pinsMasterRole, ARRAY_SIZE(spi2pinsMasterRole) );

        SPI_InitStructure.SPI_BaudRatePrescaler = findSPIPrescaler( 36000, baudKHz ); //

      SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

       SPI_I2S_DMACmd( SPI2, SPI_I2S_DMAReq_Tx, DISABLE );

       SPI_I2S_ITConfig( SPI2, SPI_I2S_IT_RXNE, DISABLE );

       NVIC_DisableIRQ( SPI2_IRQn );

   }

   SPI_Init( SPI2, &SPI_InitStructure );

   RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );

   DMA_InitStructure.DMA_PeripheralBaseAddr = SPI2->DR;

   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

   DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

   DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;

   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

   DMA_Init( SPI2_XMIT_DMA, &DMA_InitStructure );

.......

11 REPLIES 11

Software NSS (i.e. SPI_CR1.SSM=1) from the SPI module's point of view should work in the same way as hardware, i.e. setting SPI_CR1.SSI high then low should reset the slave's shifter.

JW

Thank you Jan that did the trick !