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.

RM48 SPI2 using DMA

Hello,


I got a problem to use the SPI2 with DMA of the RM48L942.


I try to set up a DMA transfer to an serial FRAM, connected on SPI2. My approad is to set up a small DMA transfer (4 bytes) to send the read command to the FRAM and, when it completes, set up a big transfer to read the data from the FRAM (from within the block transfer complete interrupt of the DMA).

I am able to issue first small transfer (I can see that it works properly on an oscilloscope), but after changing the control package for the send operation, the second DMA transfer does not start and nothing happens on the SPI bus.

I assume the following:

 - At the end of the first transfer, the dma request for sending further data is pending. I see the corresponding bit in the pending channel register of the DMA.

- When I alter the control package for sending, the hardware request got "lost" (at least the corresponding bit in the pending channel register got lost). This isn't surprising, since this is documented behaviour (technical reference manual)

I tried to reset the dma enable bit in the spi interrupt register to trigger the hardware request again (this is what triggerst the first hardware request for writing, according to the reference manual). But this does not work out.

This brings me to the followin questions:

 - Is there a possibility to trigger the hardware request for writing again after changing the control packet at all? If so, how to force it?

- Is my approach valid at all? Or is there a smarter way to set up several spi dma requests of different size consecutively?

So any ideas welcome :)


Thanks and regards,

Ulrich Mohr

Attached you find the code snippet how I set up the transfers:

First transfer:

    rxCtrlPkt.SADD = (uint32) (&(spiREG2->BUF));
    rxCtrlPkt.DADD = (uint32) (&dummy);
    rxCtrlPkt.CHCTRL = 0;
    rxCtrlPkt.FRCNT = 4;
    rxCtrlPkt.ELCNT = 1;
    rxCtrlPkt.ELDOFFSET = 0;
    rxCtrlPkt.ELSOFFSET = 0;
    rxCtrlPkt.FRDOFFSET = 0;
    rxCtrlPkt.FRSOFFSET = 0;
    rxCtrlPkt.PORTASGN = 4;
    rxCtrlPkt.RDSIZE = ACCESS_16_BIT;
    rxCtrlPkt.WRSIZE = ACCESS_16_BIT;
    rxCtrlPkt.TTYPE = FRAME_TRANSFER;
    rxCtrlPkt.ADDMODERD = ADDR_FIXED;
    rxCtrlPkt.ADDMODEWR = ADDR_FIXED;
    rxCtrlPkt.AUTOINIT = AUTOINIT_OFF;
    dmaSetCtrlPacket(RX_DMA_CHANNEL, rxCtrlPkt);

    txCtrlPkt.SADD = (uint32) &(TX_data[0]);
    txCtrlPkt.DADD = (uint32) (&(spiREG2->DAT0));
    txCtrlPkt.CHCTRL = 0;
    txCtrlPkt.FRCNT = 4;
    txCtrlPkt.ELCNT = 1;    /* 16 bit access! */
    txCtrlPkt.ELDOFFSET = 0;
    txCtrlPkt.ELSOFFSET = 0;
    txCtrlPkt.FRDOFFSET = 0;
    txCtrlPkt.FRSOFFSET = 0;
    txCtrlPkt.PORTASGN = 4;
    txCtrlPkt.RDSIZE = ACCESS_16_BIT;
    txCtrlPkt.WRSIZE = ACCESS_16_BIT;
    txCtrlPkt.TTYPE = FRAME_TRANSFER;
    txCtrlPkt.ADDMODERD = ADDR_INC1;
    txCtrlPkt.ADDMODEWR = ADDR_FIXED;
    txCtrlPkt.AUTOINIT = AUTOINIT_OFF;
    dmaSetCtrlPacket(TX_DMA_CHANNEL, txCtrlPkt);

    dmaSetChEnable(TX_DMA_CHANNEL, DMA_HW);
    dmaSetChEnable(RX_DMA_CHANNEL, DMA_HW);

    spiREG2->INT0 |= 0x010000U;    // this seems to trigger the hardware request

Second transfer (from within interrupt)

    rxCtrlPkt.SADD = (uint32) (&(spiREG2->BUF));
    rxCtrlPkt.DADD = (uint32) (data);
    rxCtrlPkt.CHCTRL = 0;
    rxCtrlPkt.FRCNT = count;
    rxCtrlPkt.ELCNT = 1;
    rxCtrlPkt.ELDOFFSET = 0;
    rxCtrlPkt.ELSOFFSET = 0;
    rxCtrlPkt.FRDOFFSET = 0;
    rxCtrlPkt.FRSOFFSET = 0;
    rxCtrlPkt.PORTASGN = 4;
    rxCtrlPkt.RDSIZE = ACCESS_16_BIT;
    rxCtrlPkt.WRSIZE = ACCESS_16_BIT;
    rxCtrlPkt.TTYPE = FRAME_TRANSFER;
    rxCtrlPkt.ADDMODERD = ADDR_FIXED;
    rxCtrlPkt.ADDMODEWR = ADDR_INC1;
    rxCtrlPkt.AUTOINIT = AUTOINIT_OFF;
    dmaSetCtrlPacket(RX_DMA_CHANNEL, rxCtrlPkt);

    txCtrlPkt.SADD = (uint32) &(dummy);
    txCtrlPkt.DADD = (uint32) (&(spiREG2->DAT0));
    txCtrlPkt.CHCTRL = 0;
    txCtrlPkt.FRCNT = count;
    txCtrlPkt.ELCNT = 1;
    txCtrlPkt.ELDOFFSET = 0;
    txCtrlPkt.ELSOFFSET = 0;
    txCtrlPkt.FRDOFFSET = 0;
    txCtrlPkt.FRSOFFSET = 0;
    txCtrlPkt.PORTASGN = 4;
    txCtrlPkt.RDSIZE = ACCESS_16_BIT;
    txCtrlPkt.WRSIZE = ACCESS_16_BIT;
    txCtrlPkt.TTYPE = FRAME_TRANSFER;
    txCtrlPkt.ADDMODERD = ADDR_FIXED;
    txCtrlPkt.ADDMODEWR = ADDR_FIXED;
    txCtrlPkt.AUTOINIT = AUTOINIT_OFF;
    dmaSetCtrlPacket(TX_DMA_CHANNEL, txCtrlPkt);
    
    spiREG2->INT0 &= ~0x010000U;                // attempt to reset the hardware trigger

    dmaSetChEnable(TX_DMA_CHANNEL, DMA_HW);
    dmaSetChEnable(RX_DMA_CHANNEL, DMA_HW);

    spiREG2->INT0 |= 0x010000U;                    // nothing happens

  • Ulrich,


    I think the best approach will be to use the DMA chaining.
    In a similar way as you did you will have to configure 2 control packet. 1 for sending the read command and 1 to receive the data.

    I've attached a project shown 3 control packet in chain mode.
    RTI is used as trigger source for the first control packet.
    At the end of the first transfer, the next control packet is triggered. Same for the third one.

    Please have a look. It will not be difficult to port this code to your SPI2 implementation.

    1884.LS31x_DMA_Chaining.zip

  • Jean-Marc,

    thank you for your very fast reply.

    Although I did not make the chaining work (see below), I was able to enable the secondary transfer from within the interrupt. The problem has been on my side, since the size of the transfer exceeded the maximum transfer frame size of the DMA.
    So my problem is solved for the moment. I will go on without the chaining for now and try this later again, because I really like the idea to set up the whole transfer at one time.

    I tried the chaining of the dma requests, and it actually starts the transfer of the second control packet, but stops after three element transfers. So it seems to work somehow, but needs some further invenstigation from my side to make it work completely.

    Thank you very much for your help & best regards,
    Ulrich
  • Ulrich,

    Glad to see that it is working for you know.

    In this case, could you please close the thread?