AnsweredAssumed Answered

STM32F103 - STM32CubeMX Configured - SPI Slave DMA Problems - Really Slow Init & Odd Behaviors

Question asked by Matt Roybal on Jan 31, 2018

Hello, I have a separate MCU acting as the SPI Master, sending data in multiples of 64 bytes (anywhere from 1x 64 byte group, to 10x 64 byte groups) - all during a single transaction. So NSS goes low, 64 bytes to 640 bytes transfer (small delay between the groups of 64 bytes), NSS goes high. This is running at 4MHz and I verified this piece is working correctly via Oscilloscope. This data is coming over twice per second. The slave also has data to exchange back to the MCU, but I have not got that far yet so its all zeros for now.

 

For the SPI slave, I am using a STM32F103 that I configured using STM32CubeMX - clock running at 64MHz. These are the settings I made for the SPI slave in CubeMX:

  • Mode: Full-Duplex Slave
  • Hardware NSS Input Signal
  • Prescaler (for Baud Rate) = 4 -> This gives 16.0 MBits/s Baud Rate
  • I created both DMAs under "DMA Settings" for "Peripheral To Memory" and "Memory To Peripheral", set both Priority to "Very High"

 

This is what my main loop looks like:

while(true)
{
     if(spiReady)
     {
          spiReady = false;
          InitSPISlave(&hspi1);
     }
}

 

Here is the "InitSPISlave":

const short MAX_DEVICES_TRACKED = 10;
uint8_t txData[MAX_DEVICES_TRACKED * 64];
uint8_t rxData[MAX_DEVICES_TRACKED * 64];

 

void InitSPISlave( SPI_HandleTypeDef *spiHandler )
{
     HAL_SPI_TransmitReceive_DMA(spiHandler, txData, rxData, sizeof(txData));
}

 

And here is the interrupt callback handler (I am only displaying the first two 64 byte chunks for now):

void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
     SPISlaveTransferComplete();
     spiReady = true;
}

 

void SPISlaveTransferComplete( void )
{
     printf("SP1 Data Received: ");
     for(int i = 0; i < 64; i++)
     {
          printf("%lx ", (long)rxData[i]);
     }
     printf("\n");

     printf("SP1 Data Received: ");
     for(int i = 64; i < 128; i++)
     {
          printf("%lx ", (long)rxData[i]);
     }
     printf("\n \n");

     memset(rxData, 0, sizeof(rxData));
}

 

I am experiencing 2 main problems:

  1. In approximately 1 in 10 SPI transfers, I am missing the first 64 byte chunk. On the Master side, I tried creating a long delay between setting NSS low and between the data transfer starting... this made no difference. This is odd because its always the full 64 bytes... its never a portion of it.
  2. The bigger problem I am experiencing, is that if I set "MAX_DEVICES_TRACKED" to 2 for instance, I get all of the SPI transfers and dump them to the screen (with the occasional first 64 bytes missing). If I start increasing the "MAX_DEVICES_TRACKED" to 5, 10, 20, etc.It creates huge delays and I miss most of the other SPI transfers coming from the Master. At 20, it takes several seconds to re-initialize the SPI and begin a transfer. I timed all of the functions using HAL_GetTicks and nothing is taking that long.... so I don't know why this is happening?

 

I am using the SWO pin, J-link, and "SEGGER J-Link SWO Viewer" to display the "printf"s.

Something else I have tried... I reset the clock settings back to stock, running everything at 8MHz, and I get the exact same delays here. This was my reasoning to up the clock speed to 64MHz (which I verified via oscilloscope by setting PA8 to MCC and I could see the clock cycle.) but this had no effect on the delay I am experiencing.

 

Thanks for taking a look and any help/advice is greatly appreciated!

Outcomes