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