1

I'm working on SPI communication between two Nucleo-H743ZI boards. I'm using ST's HAL, and the SPI polling API HAL_SPI_TransmitReceive.

It's working fine until a bandwith of 12Mbits/s (SPI kernel clock at 200Mhz and prescaler 16, the CPU is always at 400Mhz) but fails above (smaller prescaler).

I want to understand since 24 or 48 Mbits/s doesn't seem much even in polling with a poor quality software.

With prescaler set to 8, I don't have SPI error like overrun or other (I checked directly in registers), however the data are not correct. looking closer to the data, I've noticed that there is only a shift of one bit.

More precisely I should receive (in hexa ): 0x30 0x31 0x32 ... And I receive 0x18 0x18 0x99...

In binary:

  • expected 0011 0000 0011 0001 0011 0010...

  • received 0001 1000 0001 1000 1001 1001...

If I shift the received bitstream to the left I get exactly the right result.

Does it ring something to you ? Could it be due to a bad configuration ?

Obviously master and slave have the same configuration regarding phase and polarity (and everything else since the source code is mostly identical).

Guillaume Petitjean
  • 2,408
  • 1
  • 21
  • 47
  • Such a bit shift could indicate that you the SPI master or slave is not operating in the correct SPI mode. The SPI mode defines clock polarity and phase. If they aren't matching between slave and master, you can get data shifted by one bit. – Codo Jun 18 '19 at 13:10
  • You're right but as I've written, the SPI initialisation code is the same for slave and master. I just double checked, Phase and polarity are the same for both. And it's working anyway at slower frequencies. – Guillaume Petitjean Jun 18 '19 at 13:13
  • 1
    How could we guess if you don't **show the code**? What are the relevant `GPIO` register values, in particular `OTYPER`, `OSPEEDR`, `PUPDR` *at the time of the transmission*? – followed Monica to Codidact Jun 18 '19 at 13:26
  • 2
    Does the master or the slave have trouble receiving data? And it would probably be helpful if you could capture the signals with an oscilloscope and add a screenshot to the question. The problem could be at the hardware level. – Codo Jun 18 '19 at 13:30
  • @codo Good remark. Actually the slave receives correctly, the error is only at master side.Communication is full duplex. I agree about the benefit of a scope capture but I don't have one. I will try to set the slave in DMA mode, in case it is not fast enough to receive and send. – Guillaume Petitjean Jun 18 '19 at 13:55
  • @berendi for the SPI GPIO (SCK, MISO and MOSI) they are in alternate function mode, and their OTYPER is 0 (output push pull) , PUPDR is 0 (no pull up or pull down) and OSPEED is also 0 (low speed). The latter might be the issue ? – Guillaume Petitjean Jun 18 '19 at 14:16
  • @berendi, I confirmed that the GPIO speed was set to "low" in STMicro's code and increasing the GPIO speed fixed the issue. Thank you. – Guillaume Petitjean Jun 18 '19 at 14:30

2 Answers2

2

Check the Output timing characteristics table in the datasheet.

The binary number in the leftmost column is the value that goes in GPIO->OSPEEDR. At VDD=3.3V (That's what the Nucleo board uses), value 00 would work up to 12 MHz, that's exactly where your signal is starting to break down. Just turn it up to the maximal value, it doesn't hurt. (Well, it might overload something if you toggle lots of pins at once.)

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
0

48mbits means 6MB per second. Even if your uC is 400MHz you have only 50 clocks per byte. It is far not enough. For the higher speeds only DMA is possible definitely not the polling especially using HAL libraries.

48MHz cablewise is not easy as well.

0___________
  • 60,014
  • 4
  • 34
  • 74
  • Well as far as I understood the SPI can work on 32 bits granularity which means the CPU would have to process less than 2 words per us ie. 2 words in 400 cycles. Doesn't seem impossible. – Guillaume Petitjean Jun 19 '19 at 07:00
  • Using HAL? Very unlikely – 0___________ Jun 19 '19 at 07:20
  • @GuillaumePetitjean don't ever underestimate the [amount of overhead in HAL](https://stackoverflow.com/questions/56440516/stm32-spi-slow-compute). – followed Monica to Codidact Jun 19 '19 at 07:46
  • Why dv by the way? – 0___________ Jun 19 '19 at 07:59
  • For the record I could communicate up to 95Mhz (which is close to the theoretical maximum on this product I think ?) using the HAL HAL_SPI_Transmit on one side and HAL_SPI_Receive on the other side. There were many bugs in the HAL but in terms of performance it's not so bad, at least the software is not the bottleneck. In real fullduplex mode (API HAL_SPI_TransmitReceive), it works only up to 24MHz. – Guillaume Petitjean Jun 19 '19 at 09:16
  • @GuillaumePetitjean the communication itself (from the moment when you load the data to the data register does not have anything in common with the HAL. I think you should read more about how this SPI works. – 0___________ Jun 19 '19 at 09:22
  • Thank you for the kind words (once again...). In polling when you exit from function HAL_SPI_Transmit, it means EOT has been set, meaning (to quote the ref manual) "TSIZE number of data have been transmitted on SPI". So it indeed measures the duration of the communication (with the overhead of the function initialisation). For DMA or IT API obvisouly the duration of functions has nothing to do with the duration of the communication itself. – Guillaume Petitjean Jun 19 '19 at 09:37