This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSPM0G3507: Managing RX FIFO and SPI RX DMA

Part Number: MSPM0G3507

Tool/software:

Hello.

I have the SPI RX and TX DMA working simultaneously..

It seems to essentially function as I would like it to but I have clearly got an error I'm my received data from I think a RX FIFO and DMA issue.

A RPI is polling the MCU, by sending 0x8000 continuously.

When the MCU gets POLL, it responds with POLL and then TX data via DMA. This works well.

And since SPI is duplex I RX data at the same time via DMA.

The data RX data is fixed at 0xf0f0 so I can see what is going on.

However, the first two packets of the RX data are "corrupted" by "POLL" ??

The RPI is sending the correct data as I can see this on a logic analyser, see snip.

NB - I change SPI clock speed between POLL and data for various reasons and this all works fine.

Setup below and two snips.

NB - MOSI has a glitch that is not real data after last poll (it's 10 ns wide and has no effect).

Any clues ?? Seems to be close, as always.....

--

Phil

// Wait for RPI to send "POLL"
DL_SPI_drainRXFIFO16(SPI_0_INST,spi_rx_buffer,4);

while((spi_rx_buffer[0]=DL_SPI_receiveDataBlocking16(SPI_0_INST))!=POLL)
;
// Got "POLL" from RPI

// Acknowledge POLL with POLL !
DL_SPI_transmitDataBlocking16(SPI_0_INST,POLL);
while (!DL_SPI_isTXFIFOEmpty(SPI_0_INST))
;

// Empty RX
DL_SPI_drainRXFIFO16(SPI_0_INST,spi_rx_buffer,4);

// Enable DMA interrupt
DL_SPI_clearDMAReceiveEventStatus(SPI_0_INST, DL_SPI_DMA_INTERRUPT_RX);
DL_SPI_enableDMAReceiveEvent(SPI_0_INST, DL_SPI_DMA_INTERRUPT_RX);

// Wait for TX and RX to end
DL_DMA_enableChannel(DMA, DMA_SPI_TX_CHAN_ID);
DL_DMA_enableChannel(DMA, DMA_SPI_RX_CHAN_ID);
while(DL_DMA_isChannelEnabled(DMA,DMA_SPI_TX_CHAN_ID)==true)
;
while(DL_DMA_isChannelEnabled(DMA,DMA_SPI_RX_CHAN_ID)==true)
;

  • I should add that boxer I POLL I try to disable all SPI DMA activity:

    // Initialise pointers to buffers
    // Note 16 bit since SPI TX/RX is 16 bit
    ptr16_buffer_start = (unsigned short *) buffer;
    ptr16_buffer_actuate = (unsigned short *) buffer_actuate;

    // "size" is a single line, 1
    //65 words = 130 bytes = single column
    size=size*65;


    // TX DMA
    DL_DMA_disableChannel(DMA, DMA_SPI_TX_CHAN_ID);
    DL_DMA_setTransferSize(DMA, DMA_SPI_TX_CHAN_ID , (uint16_t) size); //
    DL_DMA_setSrcAddr(DMA, DMA_SPI_TX_CHAN_ID, (uint32_t) ptr16_buffer_start);
    DL_DMA_setDestAddr(DMA, DMA_SPI_TX_CHAN_ID, (uint32_t) (&SPI_0_INST->TXDATA));
    // RX DMA
    DL_DMA_disableChannel(DMA, DMA_SPI_RX_CHAN_ID);
    DL_DMA_setTransferSize(DMA, DMA_SPI_RX_CHAN_ID , (uint16_t) size); //
    DL_DMA_setSrcAddr(DMA, DMA_SPI_RX_CHAN_ID, (uint32_t) (&SPI_0_INST->RXDATA) );
    DL_DMA_setDestAddr(DMA, DMA_SPI_RX_CHAN_ID, (uint32_t) (ptr16_buffer_actuate));
    DL_SPI_clearDMAReceiveEventStatus(SPI_0_INST, DL_SPI_DMA_INTERRUPT_RX);

    // Wait for RPI to send "POLL"
    DL_SPI_drainRXFIFO16(SPI_0_INST,spi_rx_buffer,4);
  • Some observations:

    1) The TRM doesn't say, but I expect that the frame is not clocked out directly from the FIFO, but rather from a shift register in the "Transmit/Receive Logic" [Ref TRM Fig 19-1]. That would imply that the FIFO goes empty pretty much immediately after writing the first (only) POLL-ack frame; this probably isn't visible for a Master, since the clocks start immediately, but there could be a noticeable delay for a Slave as it waits for the Master to send some SCKs. A premature FIFO-empty indication could mean you'd see the second POLL after emptying the Rx FIFO.

    You might do better with something like DL_SPI_isBusy() rather than  DL_SPI_isTXFIFOEmpty() [Ref TRM Table 19-61, where BUSY also includes FIFO-not-empty].

    2) Looking at your trace, it seems as though your Analyzer is at the edge of its resolution, since not all the SCKs are visible individually. If I squint just right, the "glitch" you mention could look rather like another POLL frame.

    Does your Analyzer have more channels? /CS and MISO (to see exactly when the POLL-ack is delivered) might be informative. Alternatively, maybe have the POLL word cycle over 0x8000-0x800F or something.

    [Edit: If your Slave is using 4-wire (/CS) mode, it seems like "cheap insurance" against glitches to set CTL0:CSCLR=1 (DL_SPI_enablePeripheralAlignDataOnChipSelect()) [Ref TRM Sec 19.2.2.1.1 ].]

  • As ever, a great observation:

    You might do better with something like DL_SPI_isBusy() rather than  DL_SPI_isTXFIFOEmpty() [Ref TRM Table 19-61, where BUSY also includes FIFO-not-empty].

    This worked, appreciated.