cancel
Showing results for 
Search instead for 
Did you mean: 

Extra bits in SPI Slave DMA

PCarn.1
Associate III

I'm working on a SPI slave right now and found some weird behavior in the peripheral on a STM32g441. The following code is within a GPIO interrupt that's triggered by the CS pin rising. The peripheral clock is 160 MHz and sclk is 1.3 MHz. The spi mode is correct.

__HAL_DMA_DISABLE(hspi1.hdmarx);
 
__HAL_DMA_DISABLE(hspi1.hdmatx);
 
__HAL_SPI_DISABLE(&hspi1);
 
  // Get the command by reading from head index to the DMA count
 
  uint32_t uiRxSize = XSPI_RX_TX_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(hspi1.hdmarx);
 
 
  // Pull out the command information
 
  if (uiRxSize <= 0)
 
  {
 
    // The command does not have any data. Reset and re-enable the DMA
 
    // Move the rx/tx DMA buffer back to the beginning of the buffer to fully reset everything
 
    hspi1.hdmarx->Instance->CNDTR = XSPI_RX_TX_BUFFER_SIZE;
 
    hspi1.hdmatx->Instance->CNDTR = XSPI_RX_TX_BUFFER_SIZE;
    __HAL_DMA_ENABLE(hspi1.hdmarx);
 
    __HAL_DMA_ENABLE(hspi1.hdmatx);
 
    __HAL_SPI_ENABLE(&hspi1);
 
    return;
 
  }
 
  auto eAddress = static_cast<exSPIAddress_t>(pucRxBuffer[0] & XSPI_ADDRESS_Msk);
 
  bool bRead = (pucRxBuffer[0] & XSPI_READ_WRITE_Msk);
 
 
//switch statement to handle read/write operation that reads from an array in RAM and is //populated by the DMA
 
 
  // Move the rx/tx DMA buffer back to the beginning of the buffer to fully reset everything
 
  hspi1.hdmarx->Instance->CNDTR = XSPI_RX_TX_BUFFER_SIZE;
 
  hspi1.hdmatx->Instance->CNDTR = XSPI_RX_TX_BUFFER_SIZE;
 
 
 
__HAL_DMA_ENABLE(hspi1.hdmarx);
 
__HAL_DMA_ENABLE(hspi1.hdmatx);
 
__HAL_SPI_ENABLE(&hspi1);

I've found that the spi works well most of the time. But when I send a command from master before SPI is re-enabled then the array in RAM will be shifted 2 to 4 bits to the right. In other words, there's 2 to 4 extra bits on the most significant side of DMA. An example is, I expect to have 0xD1 in the 0 index of my array but instead I have 0x1A and all of the following bytes in the array are corrupted in the same way.

I don't understand why anything would be read into the SPI shift register if SPI is disabled. I also don't fully understand what disabling the SPI->CR1->SPE bit does to the SPI. Any help understand would be appreciated.

3 REPLIES 3

> I also don't fully understand what disabling the SPI->CR1->SPE bit does to the SPI.

In slave mode it ignores SCK and MOSI, and MISO is threestated.

> But when I send a command from master before SPI [in slave] is re-enabled

Well, slave does not know about those clocks which were issued by master during the time slave was disabled.

> I don't understand why anything would be read into the SPI shift register if SPI is disabled.

Master reads whatever random value is on MOSI.

Try to draw yourself a timing diagram of a "normal" transaction (use pencil and paper). Now imagine you are the slave which starts to observe SCK a couple of clocks later than master starts to transmit them; draw yourself the state of both master's and slave's shift register at the respective time points and then again at the moment when a full frame is transferred, at both sides (which is at a different time point/SCK clock number).

JW

So you think the slave SPI is disabled, then master starts sending the 8 bites, then the slave SPI gets enabled in the middle of the message? So the slave SPI only catches the least significant part of the byte? I know that is not the case because I can see the most significant bits are acquired but they are in the wrong position. For 0xd0 (1101 0000) the value in DMA turns into 0x1a (00011010). Given that I'm sending MSB first, this would suggest there's extra clock cycles before the MOSI line is active. But I can see on the oscilloscope that this is not the case. The values being sent are exactly what we would expect.

I don't think there's much value in trying to interpret results from errorneous operation. If you desire to do so, you are mostly on your own, so formulate hypotheses and devise experiments to prove or disprove them.

Clearing SPE may have less effect than you'd expect it to have. Maybe not much more beyong what I've written above. It may even not reset the bit counters (NSS does this for slave), and I faintly recall people reporting that it does not reset the FIFOs in the newer SPIs which do have FIFO (as is your case too).

JW