cancel
Showing results for 
Search instead for 
Did you mean: 

slave spi on stm32f4 receives incorrect data

deep
Associate II

I have an jetson xavier driving STM32F407G-DISC1 on SPI1 default pins : PA4/5/6/7 .
The SPI_FLAG_RXNE flag behaviour is very strange, resulting in wrong values being received.
Config used:

/* SPI1 parameter configuration*/
hspi1.Instance =         SPI1;
hspi1.Init.Mode =        SPI_MODE_SLAVE;
hspi1.Init.Direction =   SPI_DIRECTION_2LINES;
hspi1.Init.DataSize =    SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase =    SPI_PHASE_1EDGE;
hspi1.Init.NSS =         SPI_NSS_HARD_INPUT;
hspi1.Init.FirstBit =    SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode =      SPI_TIMODE_DISABLE;


In these plots CH3 is connected to a gpio that tracks SPI_FLAG_RXNE, while CH4 is connected to !SPI_FLAG_BSY .
What I expect to see is SPI_FLAG_RXNE firing with the rising edge of SCK on the reception of the 8th bit like this:

spi_expected.png

 However with this SPI driver the SPI_FLAG_RXNE signal seems to look like this:

 

spi_actual.png

Result is wrong data received.  This happens independent of SCK speed.  Validated the STM32 slave inputs using a simple bitbang SPI slave, and data is received with no errors.

SPI_FLAG_RXNE and !SPI_FLAG_BSY were brought out to gpio with something like:

volatile uint8_t rxd = 0;
while(true) {
  uint32_t spiFlags = hspi->Instance->SR;
  bool is_free = ! (spiFlags & SPI_FLAG_BSY);
  bool is_rx_buffer_ready = (spiFlags & SPI_FLAG_RXNE);

  set_gpio_led(led_orange, is_free);
  set_gpio_led(led_green, is_rx_buffer_ready);

  if (is_rx_buffer_ready) {
    small_delay();
    rxd = hspi->Instance->DR;
  }
}

16 REPLIES 16

> single bit flip errors

The previous errors looked like bit shifts, and that's definitively caused by the spike in the edge, usually due to reflections. You should've experimented with OSPEEDR settings before adding the serial resistors.

Bit flips, however, are something else.

Ground/return should be every other line in the ribbon cable, and every signal should have its own return. Remeber the 80-wire "high speed" PATA cable?

JW

deep
Associate II

SPI master is Jetson Orin -- which has plenty of power decoupling but no slew rate controls on GPIO.  

The bit flips are always 1->0 

Replaced ribbon cable with shielded ground return pairs with no improvement. 

Couldn't use the 80-wire "high speed" 40-pin cable unfortunately, because I found it has a missing connection:

sata.png

I guess that's how they key it in. too bad

With a target of 2MHz sq wave, we need to 250ns high + 250ns low, so:

98% setting time =>
  4RC = 250ns
   RC = 50ns (about)
 if R = 500ohm => C = 0.1nF
    R = 100ohm => C = 0.5nF

No sure what the existing stm32f407 pcb + package cap is...should be 20-30pF ?

Just to be sure: the bit flips are at MOSI, i.e. Orin->STM32 direction, right?

What are the voltage levels and what's the STM32 VDD?

On the 'F407 Disco, the MEMS accelerometer is connected to PA4..PA7. Make sure it's inactive; or just choose a different set of pins, those which are not connected to on-board devices.

JW

 

deep
Associate II

Yes bit flips are in MOSI (Orin->stm32) direction.  I run an echo server on stm side with something like:

  uint8_t tx = 0xAA;
  uint8_t rx = 0xBB;
  while (true) {
    HAL_SPI_TransmitReceive(&hspi1, &tx, &rx, 1, HAL_MAX_DELAY);
    //printf("slave: tx=%02x rx=%02x\r\n", txd, rxd); // only at slow speeds
    tx = rx;
  }

The slave->master interface seems to work at much higher speeds than master->slave. In any case, the round trip [test value] master -> MOSI -> slave -> MISO -> master [compare value] is used to deduce errors. 

MEMS accelerometer is NOT enabled, and i also tried out hspi3 on different pins with same result--direct connect SPI with slave stm32 spi fails at all freq.  

> In any case, the round trip [test value] master -> MOSI -> slave -> MISO -> master [compare value] is used to deduce errors.

I wonder, how do you distinguish master->slave from slave->master errors in this arrangement.

One possible explanation may be byte shift due to Cube/HAL being slow to fill the slave's Tx buffer.

JW

When I return a known pattern from slave back to master, I still get garbage:

uint8_t txd [] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0x FF};

 

Noise on SCK signal means data is corrupted in both directions, as single posedge clock transitions are counted as multiple...

without_termination.png

termination smoothes out the curves, but limits max speed:

 

 

the swith_termination.png

 

the standalone buffer here is really a level shifter with all VDD connected to 3.3V and and all grounds shorted.  Just used as a proxy for what the SPI SCK input on stm32 might be getting after the first stage of IO.

ONadr.1
Senior III

Are you really sure that the power supply is powerful enough and the decoupling capacitors are sufficient and correctly placed? I've seen exactly that kind of SPI wobble before, and that was the problem.