AnsweredAssumed Answered

gHaving trouble getting DSPI working with eDMA.

Question asked by Adam Crowder on Apr 6, 2015
Latest reply on May 26, 2015 by Adam Crowder

Using MCF5441x CPU, I have been working on code to manage an SPI link to another CPU.  I was able to configure the DSPI module to operate with the peer processor (we're the slave in the link), but when I attempt to get DMA to feed its data, nothing happens.  It's as if DMA is not triggered at all.

 

I have to say, this is by far the worst user manual for a CPU that I have ever been subjected to.  I am certainly thankful that this is not my FIRST Coldfire, else I might have thrown in the towel by now.  In the section on DMA, it only acknowledges DMA channels over #15 in a few places (though it's implied that there are 64).

 

In any case, it seems as if this should not be so difficult as it's turning out to be.

 

I have made sure to configure my DMA completely before starting the SPI.  At this point, I expect the Tx DMA to start IMMEDIATELY, but it does not.

 

I think all the relevant code is listed below.  There *are* interrupt routines, but since this won't *start*, they do not execute.

 

Thanks in advance for any advice/info you can provide.

 

--Adam

 

 

This code is called on startup:

 

void PIP_ConfigHdwe( void) // Set up SPI interface

{    // Now configure the SPI interface between the PIP and ourselves:

    // Enable internal clock to DSPI Module:

    MCF_PMM_PPMCR0 = 23;  // Enable DSPI0 (p. 9-7)

    MCF_PMM_PPMCR0 = 17;  // Enable eDMA controller (p. 9-7)

   

    // Configure DSPI (chapter 40)

    // DSPI is interrupt 31 (on INTC0)

    MCF_DSPI0_MCR =  MCF_DSPI_MCR_HALT          +

                     MCF_DSPI_MCR_SMPL_PT_0CLK  + // No modification to sample point

                     MCF_DSPI_MCR_CLR_RXF       + // Okay; clear the FIFOs just this once.

                     MCF_DSPI_MCR_CLR_TXF       +

//                     MCF_DSPI_MCR_DIS_RXF       + // Disable neither FIFO. We like FIFO.

//                     MCF_DSPI_MCR_DIS_TXF       +

//                     MCF_DSPI_MCR_MDIS          + // Enable clocks

                     MCF_DSPI_MCR_PCSIS0        + // Mandatory config for Slave operation

//                     MCF_DSPI_MCR_ROOE          + Overflow bad either way.  We'll just avoid that

//                     MCF_DSPI_MCR_MTFE          +

//                     MCF_DSPI_MCR_FRZ           + // Do not halt serial transfers on DEBUG

                     MCF_DSPI_MCR_DCONF(0)      + // Only valid config

//                     MCF_DSPI_MCR_CONT_SCKE     + Disable continuous clock

//                     MCF_DSPI_MCR_MSTR          + We're a slave

                     0;

                    

// Max Frequency is Fsys / 8 ( Coldfire AC timing specs, per Rocky. )

// Fsys is 250MHz so 31.25MHz s/b our max.

   

    MCF_DSPI0_CTAR0 =  // Omitting a bunch of Master mode settings, all set to zero.

                       MCF_DSPI_CTAR_LSBFE          + // LSB first.  Not sure, but p. 64 of PIP book *suggests* LSB first

                       MCF_DSPI_CTAR_CPHA           + // p. 40-11.  1 = sample on falling edge

//                       MCF_DSPI_CTAR_CPOL           + // p. 40-11.  1 = inactive state is high

// Partner board CLK rests low and changes on rising edge

                       MCF_DSPI_CTAR_FMSZ(7)        + // 8 bits per frame (PIP p. 64)

//                       MCF_DSPI_CTAR_DBR            +

                       0;

   

    MCF_DSPI0_RSER  =  0 +

//                       MCF_DSPI_RSER_RFDF_DIRS  + // For FIRST byte, we want an Interrupt!

                       MCF_DSPI_RSER_RFDF_RE    + // Enable Interrupt/DMA for Rx

//                       MCF_DSPI_RSER_RFOF_RE    + // Don't want overflow Interrupt.

                       MCF_DSPI_RSER_TFFF_DIRS  + // DMA for Tx

                       MCF_DSPI_RSER_TFFF_RE    + // Enable Interrupt/DMA for Tx

//                       MCF_DSPI_RSER_TFUF_RE    + // No Int for Underflow

                       MCF_DSPI_RSER_EOQF_RE    + // No End Of Queue interrupt

                       MCF_DSPI_RSER_TCF_RE     + // Yes, Interrupt on Transmision Complete!

                       0;

                      

    // eDMA Config                                    Chapter 19

    // Channel 12 = DSPI0_SR[RFDF] (Receive)

    // Channel 13 = DSPI0_SR[TFFF] (Transmit)

   

    MCF_eDMA_EDMA_CR = 0; // Fixed priority.  Continue to operate in DEBUG mode.

   

    // Clear flags in eDMA engine:

    MCF_eDMA_EDMA_CDNE = MCF_eDMA_EDMA_CDNE_CADN;  // Clear DONE status bits register

    MCF_eDMA_EDMA_CERQ = MCF_eDMA_EDMA_CERQ_CAER;  // Clear Enable Requests

    MCF_eDMA_EDMA_CEEI = MCF_eDMA_EDMA_CEEI_CAEE;  // Clear Error Interrupt Enables

   

    // Configure DMA for Rx:

    MCF_eDMA_TCD12_SADDR       = (&MCF_DSPI0_POPR); // 32-bit register

    MCF_eDMA_TCD12_ATTR        = 0x0200; // 32-bit source, 8-bit dest; No modulo

    MCF_eDMA_TCD12_SOFF        = 0; // Offset for source (will stay zero)

    MCF_eDMA_TCD12_NBYTES      = 1; // 1 byte per request

    MCF_eDMA_TCD12_SLAST       = 0; // Last Source Adjustment

    MCF_eDMA_TCD12_DADDR       = 0; // Will be filled in when initialized with address of buffer.

    MCF_eDMA_TCD12_CITER       = 0; // Will be the byte count (I think), written when enabled.

    MCF_eDMA_TCD12_DOFF        = 1; // Increment Destination by 1 each write

    MCF_eDMA_TCD12_DLAST_SGA   = 0; // Last Dest adjustment

    MCF_eDMA_TCD12_BITER       = 0; // Will be set equal to CITER when enabled (I think)

    MCF_eDMA_TCD12_CSR         = 0; // No Interrupt.  p.19-26

   

    // Configure DMA for Tx:

    MCF_eDMA_TCD13_SADDR       = 0; // Will be set with address from Tx Buffer.

    MCF_eDMA_TCD13_ATTR        = 0x0002; // 8-bit source, 32-bit dest; no modulo.

    MCF_eDMA_TCD13_SOFF        = 1; // Source address will increment by 1 each read

    MCF_eDMA_TCD13_NBYTES      = 1; // 1 byte per request

    MCF_eDMA_TCD13_SLAST       = 0; // No last Source adjustment

    MCF_eDMA_TCD13_DADDR       = (&MCF_DSPI0_PUSHR); // 32-bit register

    MCF_eDMA_TCD13_CITER       = 0; // Byte count (I think) will be set later.

    MCF_eDMA_TCD13_DOFF        = 0; // Desination register will NOT change

    MCF_eDMA_TCD13_DLAST_SGA   = 0; // Last Dest adjustment

    MCF_eDMA_TCD13_BITER       = 0; // Equal to CITER when enabled

    MCF_eDMA_TCD13_CSR         = 0; // Rx DMA will provide interrupt.

   

    // DSPI0 is Interrupt source 31 in INTC0  p.17-13. */

    MCF_INTC0_ICR31 = MCF_INTC_ICR_LEVEL(7); // Level 6 IRQ

    MCF_INTC0_IMRL &= ~ MCF_INTC_IMRL_INT_MASK31;         // Unmask this interrupt

   

    MCF_eDMA_EDMA_SERQ = 12; // Enable Channel 12 (DSPI Rx)

    MCF_eDMA_EDMA_SERQ = 13; // Enable Channel 13 (Tx)

}

 

Then the function SPI_Send does the rest:

 

 

 

void SPI_Send( pipbuf * pTxBuf, int Mode )

{ // Prepare SPI Interface for a transaction.  Mode is one of PIP_SPI_TX or _RX

    pipbuf    *pRxBuf;

    int ByteCount;

   

    ByteCount = pTxBuf->Length;

   

    if( ByteCount < 16 || ByteCount > PIP_MAXFRAME + 16 ) {

        #ifdef DEBUG

            iprintf( "Invalid byte count (%d)\n", ByteCount);

        #endif

        if( pTxBuf) {

            freePIPbuffer( pTxBuf);

        }

        return;

    }

   

    switch( PIPInfo.SPIState ) {

    case PIP_SPI_IDLE   :

    case PIP_SPI_TXDONE :

    case PIP_SPI_RXDONE :

        break;

    case PIP_SPI_TX     :

    case PIP_SPI_RX     :

        #ifdef DEBUG

            iprintf( "SPI_Send: Error: Attempt to send while SPIState is %d\n", PIPInfo.SPIState  );

        #endif

        return;

    }

 

    pRxBuf = getPIPbuffer();

    if( pRxBuf == NULL ) {

        #ifdef DEBUG

            iprintf( "SPI_Send failed to get a buffer for Rx\n");

        #endif

        freePIPbuffer( pTxBuf);

    }

   

   

    PIPInfo.TxBuf = pTxBuf;

    PIPInfo.TxBuf->pCursor = & PIPInfo.TxBuf->Header.MsgType;

    PIPInfo.TxBuf->Count = ByteCount;

   

    PIPInfo.RxBuf = pRxBuf;

    PIPInfo.RxBuf->pCursor = & PIPInfo.RxBuf->Header.MsgType;

    PIPInfo.RxBuf->Length = 0;

    PIPInfo.RxBuf->Count = ByteCount;

   

    PIPInfo.SPIState = Mode;

   

   

    // Configure DMA for Rx:

    MCF_eDMA_TCD12_SADDR       = (&MCF_DSPI0_POPR); // 32-bit register

    MCF_eDMA_TCD12_DADDR       = &(PIPInfo.RxBuf->Header.MsgType); // Point to first byte of frame

    MCF_eDMA_TCD12_CITER       = ByteCount;

    MCF_eDMA_TCD12_BITER       = ByteCount;

   

    // Configure DMA for Tx:

    MCF_eDMA_TCD13_SADDR       = &(PIPInfo.TxBuf->Header.MsgType); // First byte of Tx Frame

    MCF_eDMA_TCD13_DADDR       = (&MCF_DSPI0_PUSHR); // 32-bit register

    MCF_eDMA_TCD13_CITER       = ByteCount;

    MCF_eDMA_TCD13_BITER       = ByteCount;

   

    MCF_DSPI0_RSER  =  0 +

                       MCF_DSPI_RSER_RFDF_DIRS  + // DMA all the way

                       MCF_DSPI_RSER_RFDF_RE    + // Enable Interrupt/DMA for Rx

//                       MCF_DSPI_RSER_RFOF_RE    + // Don't want overflow Interrupt.

                       MCF_DSPI_RSER_TFFF_DIRS  + // DMA for Tx

                       MCF_DSPI_RSER_TFFF_RE    + // Enable Interrupt/DMA for Tx

//                       MCF_DSPI_RSER_TFUF_RE    + // No Int for Underflow

                       MCF_DSPI_RSER_EOQF_RE    + // No End Of Queue interrupt

                       MCF_DSPI_RSER_TCF_RE     + // Yes, Interrupt on Transmision Complete!

                       0;

   

                      

    MCF_DSPI0_MCR &=  ~(MCF_DSPI_MCR_HALT); // Clear the HALT bit, allow SPI to start.

                      

     PIP_Ready( TRUE);  // Handshake to peer that we're ready

}

Outcomes