Kinetis DSPI...undocumented behaviour?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Kinetis DSPI...undocumented behaviour?

759 Views
DustyStew
Contributor V

I am doing some experimenting, trying to get the DSPI on the K20 to behave like the documentation says it should. It doesn't seem to work as documented. I am monitoring the registers in debug, in CW 10.4.

The DSPI is being run in master mode. There is are two FIFOs, transmit and receive, each 4 words deep. The transmit FIFO has both command and data fields. I am setting the command field to select CTAR0, which is specifying 8 bits etc. The chip select field is being set to a known-good value. The MSB of the command field has been alternately set to 1 and 0, with no change in behaviour.

The two FIFOs are empty. I write 4 values into the tx FIFO. Now I presume this will generate the clocks required for 4 values to be received, and so the receive FIFO should therefore be full, some time after the 4 are written to the tx FIFO. As well, the FIFO counters in the status register should change to reflect the same. So at the end of this (with a little waiting perhaps, depending on the clock frequency setting), the rx counter should have the value 4.

That doesn't happen. The first word is written to the tx FIFO, and the rx counter shows 1. Then it shows 0, and stays there. It's almost as if the DMA is sneaking in and grabbing data out of the register, but the DMA should not be enabled. There a known-good PE interrupt handler that would steal the rx data, so I am disabling that first thing.

Here's the code. It uses macros from PE, which are also used in known-good PE code.

void sd_read4(uint8_t *buffer)

{

    byte i;

    uint16_t d;

   

    SPI_PDD_DisableDmasInterrupts(SPI0_BASE_PTR, SPI_PDD_RX_FIFO_DRAIN_INT_DMA); // don't let the interrupt handler steal the rx data

    SPI0_SR |= SPI_SR_RFDF_MASK;          // clear drain flag (for laughs)

    // fill the tx FIFO

  SPI_PDD_WriteMasterPushTxFIFOReg(SPI0_BASE_PTR, (uint32_t)0x040100ffU); // first one clears the tx counter, for laughs

  SPI_PDD_WriteMasterPushTxFIFOReg(SPI0_BASE_PTR, (uint32_t)0x000100ffU);

  SPI_PDD_WriteMasterPushTxFIFOReg(SPI0_BASE_PTR, (uint32_t)0x000100ffU);

  SPI_PDD_WriteMasterPushTxFIFOReg(SPI0_BASE_PTR, (uint32_t)0x000100ffU);

  // I presume the same number of bytes should come back?

    for(i = 0;i < 4;i++)

    {

        while(!(SPI0_SR & SPI_SR_RXCTR_MASK))  // wait til something in rx FIFO (NOTE: THIS HANGS)

            ;

     d = (uint16_t)SPI_PDD_ReadPopRxFIFOReg(SPI0_BASE_PTR); // read the rx FIFO

     *buffer = (uint8_t)d; // save the data (this casting matches the PE code that works)

     buffer++;

    }

    SPI_PDD_ClearInterruptFlags(SPI0_BASE_PTR,SPI_PDD_RX_FIFO_DRAIN_INT_DMA);          // makes sure no interrupt is generated

    SPI_PDD_EnableDmasInterrupts(SPI0_BASE_PTR, SPI_PDD_RX_FIFO_DRAIN_INT_DMA);   // restore interrupts so the other SPI code still works

}

Truth is though --- nowhere in the DPSI docs for this processor does it say that you need to write the tx FIFO in order to cause a byte to be received. You've got to wonder. Astounding, really, and omission of that magnitude. Yet the working code in all cases writes a byte then reads a byte.

0 Kudos
4 Replies

394 Views
DustyStew
Contributor V

I think the DMA must be enabled because the rx FIFO pointer keeps incrementing (even though the count remains the same at 1, then goes to 0...as if someone is reading the FIFO)

0 Kudos

394 Views
DustyStew
Contributor V

DMA appears to be disabled, though it's PE code that is configuring the MCU, and Lord Knows what that is doing. SPI0_RSER is 0x00000000 (no interrupts, no DMA).

I can blast through the 4 tx FIFO writes, and see the rx counter get up to 4...then instantly those disappear.

Put a watchpoint on the rx FIFO pop register reads...and this only breaks in my code (so no other code is reading the rx FIFO, apparently).

0 Kudos

394 Views
DustyStew
Contributor V

OK got it. This is covered in another thread. CW's debugger is set up to read the registers, if they are being viewed. In doing so, it screws up the program being debugged by stealing the data out of the rx FIFO.

So it's a bug in CW (as far as I am concerned). Somewhere in the CW code there is an array that defines the register set, and the rx FIFO should be left off this list. Or information displayed to indicate it cannot be read. If there is a setting to disable this, then it should be disabled by default.

0 Kudos

394 Views
Monica
Senior Contributor III

Hello Thomas!

Thank you very much for sharing your work and the results, is greatly valuable for Community.

You rock! :smileywink:

Best regards,

Monica

0 Kudos