cancel
Showing results for 
Search instead for 
Did you mean: 

SPI slave mode send data after transaction complete

Lee3
Associate III

I'm trying to send a fixed length packet in SPI slave mode from the STM32 via DMA. The SPI master may send/recv longer than that fixed length packet. It would be nice if the STM32 just sends 0 one the transactions is complete, but it seems to want to send 0x02 or 0x80. I'm wondering where this is coming from and if there are any ways to get it to send 0.

    init_struct_.txDmaChannel->CCR &= ~DMA_CCR_EN;
    init_struct_.txDmaChannel->CNDTR = descriptor.length;
    init_struct_.txDmaChannel->CMAR = (uint32_t)descriptor.txBuffer;
    init_struct_.txDmaChannel->CCR |= DMA_CCR_EN;

dma configuration

  init_struct_.txDmaChannel->CPAR = (uint32_t)&init_struct_.spi->DR;
  init_struct_.txDmaChannel->CNDTR = 0;
  init_struct_.txDmaChannel->CCR = DMA_CCR_DIR | DMA_CCR_MINC;
  init_struct_.txDmaMuxChannel->CCR = init_struct_.txDmaMuxId;

Lee3_0-1709843401327.png

 

 

4 REPLIES 4
Lee3
Associate III

I guess I see that 0x02 and 0x80 are 3 and 4 bytes ahead of the end. I added 4 zeros to the outgoing packet and that makes following bytes all 0. Is there any other solution for this?

When the master reads data, the SPI hardware will send whatever is in its data register.  If you don't write new data, it will re-send the existing data.  If the master is trying to read more data than you want to send and you want the extra bytes zero-filled, then you need to write zero to the data register (once) at the end of your real data.  You can either pad the data in the DMA buffer with a zero byte, or manually write a zero in the "SPI transfer complete" callback (I think - I haven't tried this).

> I added 4 zeros to the outgoing packet and that makes following bytes all 0. Is there any other solution for this?

This is probably the most elegant one.

For SPI in older STM32, without FIFO, there was a confirmation from ST here, that underflown slave transmits the last frame over and over. Here, the FIFO makes it more complex and it makes sense to fill all of it with 0 just to be sure.

As an alternative, you can switch over the MISO pin to GPIO Out set to 0, for example, if it suits you.

JW

PS.

Note, that at least the old SPI I was talking about, has the nasty property in the slave setting with continuous clock from master, that a byte written at the first half of the first bit (i.e. when transmitting a frame has already started but did not progress beyond the first half bit, or, in other words, between the first and second clock transition of a frame) is output immediately to MISO, potentially causing the appropriate bit (MSB in the usual SPI setting) to change before the second clock transition, which in turn may violate setup requirement on the master side thus master may read that bit incorrectly.

I found the thread with ST confirming the SPI behaviour at slave underrun, here.

It also says that the SPI with FIFO at slave underrun transmits the oldest item in FIFO, which matches your observation.

JW

(Btw. IIRC the newest SPI in 'H7 does have a switch which controls the behaviour at underrun explicitly, but that SPI is a hard to use overcomplicated piece too).