Dear tech supporters,
How should I configure SPI-DMA reading. I have made SPI-DMA writing work fine. However for reading, I configured 2 DMAs, one for writing and the other one for reading as the code below. I got correct scope curves of both writing(MOSI) and reading(MISO) to and from NVRAM chip. But the reading DMA did not work. Therefore, I cannot get the reading data DMAed to addrRdDest. I have following conceptual questions:
-
RD_8_BIT_SOURCE_ADDR should be 0xff0e0203 Rx[0], or 0xff0e0207 Rx[1]? We send out using Tx[1] fine.
-
SS_DMA_ReqAssign(CHANNEL_WR_NO, LINE_WR_NO);
SS_DMA_ReqAssign(CHANNEL_RD_NO, LINE_RD_NO);
we use lines and channels above. Can we map lines and channels as below? What is the correct way to map for the followings?
spiREG1->DMACTRL[CHANNEL_WR_NO].TXDMA_MAP = LINE_WR_NO;
spiREG1->DMACTRL[CHANNEL_WR_NO].RXDMA_MAP = LINE_RD_NO;
spiREG1->DMACTRL[CHANNEL_RD_NO].TXDMA_MAP = LINE_WR_NO;
spiREG1->DMACTRL[CHANNEL_RD_NO].RXDMA_MAP = LINE_RD_NO;
-
In order to make the reading DMA working, can we chain the reading DMA as below?
dmaCtrlPktRd.CHCTRL = CHANNEL_WR_NO; //CHANNEL+1, 0 for not chaining.
Thank you and best regards,
Long Wan
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define WR_8_BIT_DESTINATION_ADDR 0xff0e0007 // 0xff0e0007 Tx[1]
#define RD_8_BIT_SOURCE_ADDR 0xff0e0203 // 0xff0e0203 Rx[0], 0xff0e0207 Rx[1]
#define LARGE_COUNT
#define CHANNEL_WR_NO 7
#define CHANNEL_RD_NO 6
#define LINE_WR_NO 0
#define LINE_RD_NO 1
void StartSpiDmaRead( U8*addrWrSrc, U8*addrRdDest, U32 numBytes)
{
SS_DMA_CONTROL_PACKET_ST dmaCtrlPktWr, dmaCtrlPktRd;
SS_SPI_DMA_Init1(9U);
dmaREG->GCTRL = 0x00000001U; /* reset dma */
while(dmaREG->GCTRL);
spiREG1->ENA = 0; // SPIENA hold low for configuration
#ifdef LARGE_COUNT
spiREG1->DMACNTLEN = 1U; // select large count for SPI DMA
spiREG1->RAMACCESS = 0; // not to use Multi-buffer mode by set bit MSPIENA
#else
spiREG1->DMACNTLEN = 0; // select large count for SPI DMA
spiREG1->RAMACCESS |= 1U; // to use Multi-buffer mode by set bit MSPIENA
#endif
//============= SPI-DMA FOR WRITE=================================
dmaCtrlPktWr.SADD = (U32)addrWrSrc; //source address of DMA, Post-incremented
dmaCtrlPktWr.DADD = WR_8_BIT_DESTINATION_ADDR; //Fixed address needed here
dmaCtrlPktWr.FRCNT = (numBytes); //Frame count
dmaCtrlPktWr.ELCNT = 1; //element count
dmaCtrlPktWr.PORTASGN = 4U; //Port B
dmaCtrlPktWr.ADDMODERD = ADDR_INC1; //post-incremented
dmaCtrlPktWr.ADDMODEWR = ADDR_FIXED; //ADDR_FIXED; //constant
dmaCtrlPktWr.RDSIZE = SS_DMA_ACCESS_8_BIT; //8 or 16-bit
dmaCtrlPktWr.WRSIZE = SS_DMA_ACCESS_8_BIT; //8 or 16-bit
dmaCtrlPktWr.TTYPE = FRAME_TRANSFER; //FRAME_TRANSFER is required for SPI-DMA
dmaCtrlPktWr.AUTOINIT = AUTOINIT_ON; //AUTOINIT_OFF AUTOINIT_ON auto-init
dmaCtrlPktWr.CHCTRL = 0; //0 for not chaining. n+1 for channel n,
dmaCtrlPktWr.ELDOFFSET = 0; //element destination offset
dmaCtrlPktWr.ELSOFFSET = 0; //element source offset
dmaCtrlPktWr.FRDOFFSET = 0; //frame destination offset
dmaCtrlPktWr.FRSOFFSET = 0; //frame source offset
SS_DMA_ReqAssign(CHANNEL_WR_NO, LINE_WR_NO); // (SS_U32 channel, SS_U32 reqline)
SS_DMA_SetCtrlPacket(CHANNEL_WR_NO, &dmaCtrlPktWr);
SS_DMA_SetChEnable(CHANNEL_WR_NO, SS_DMA_REQ_TYPE_HW); // SS_DMA_REQ_TYPE_HW is spiREG1->DMACTRL[CHANNEL_WR_NO].ONESHOT = 1; // set, not clear ONESHOT
spiREG1->DMACTRL[CHANNEL_WR_NO].NOBRK = 1U; // set NOBRK
spiREG1->DMACTRL[CHANNEL_WR_NO].BUFID = 1; // a 7-bit BUFID. Start from No. 0 buffer RAM: 0 ~ 127, total 128 buffer RAMs. My set-up is using buffer1 that is verified by scope
spiREG1->DMACTRL[CHANNEL_WR_NO].TXDMA_MAP = LINE_WR_NO; // DMA TX channel line number?
spiREG1->DMACTRL[CHANNEL_WR_NO].RXDMA_MAP = LINE_RD_NO; // DMA RX channel line number?
#ifdef LARGE_COUNT
spiREG1->DMACOUNT[CHANNEL_WR_NO] = ( numBytes << 16 );
#else
spiREG1->DMACTRL[CHANNEL_WR_NO].ICOUNT = numBytes;
#endif
spiREG1->DMACTRL[CHANNEL_WR_NO].TXDMA_ENA = 1U;
spiREG1->DMACTRL[CHANNEL_WR_NO].RXDMA_ENA = 1U;
spiREG1->TGCTRL[CHANNEL_WR_NO] &= 0xffff00ff; // let PSTART = 0;
spiREG1->TGCTRL[CHANNEL_WR_NO] |= 0x80000000; // set TGENA bit
//============= SPI-DMA FOR READ =================================
dmaCtrlPktRd.SADD = RD_8_BIT_SOURCE_ADDR;
dmaCtrlPktRd.DADD = (U32)addrRdDest;
dmaCtrlPktRd.FRCNT = (numBytes); //Frame count
dmaCtrlPktRd.ELCNT = 1; //element count
dmaCtrlPktRd.PORTASGN = 4U; //Port B
dmaCtrlPktRd.ADDMODERD = ADDR_FIXED; //ADDR_FIXED; //constant
dmaCtrlPktRd.ADDMODEWR = ADDR_INC1; //post-incremented
dmaCtrlPktRd.RDSIZE = SS_DMA_ACCESS_8_BIT; //8-bit
dmaCtrlPktRd.WRSIZE = SS_DMA_ACCESS_8_BIT; //8-bit
dmaCtrlPktRd.TTYPE = FRAME_TRANSFER; //FRAME_TRANSFER is required for SPI-DMA
dmaCtrlPktRd.AUTOINIT = AUTOINIT_ON; //AUTOINIT_OFF AUTOINIT_ON auto-init
dmaCtrlPktRd.CHCTRL = CHANNEL_WR_NO; //CHANNEL_NO +1; // 0 for not chaining.
dmaCtrlPktRd.ELDOFFSET = 0; //element destination offset
dmaCtrlPktRd.ELSOFFSET = 0; //element source offset
dmaCtrlPktRd.FRDOFFSET = 0; //frame destination offset
dmaCtrlPktRd.FRSOFFSET = 0; //frame source offset
SS_DMA_ReqAssign(CHANNEL_RD_NO, LINE_RD_NO); // (SS_U32 channel, SS_U32 reqline). SS_DMA_SetCtrlPacket(CHANNEL_RD_NO, &dmaCtrlPktRd);
SS_DMA_SetChEnable(CHANNEL_RD_NO, SS_DMA_REQ_TYPE_HW); // SS_DMA_REQ_TYPE_HW is required for SPI-DMA
spiREG1->DMACTRL[CHANNEL_RD_NO].ONESHOT = 1; // set, not clear ONESHOT
spiREG1->DMACTRL[CHANNEL_RD_NO].NOBRK = 1U; // set NOBRK
spiREG1->DMACTRL[CHANNEL_RD_NO].BUFID = 1; // a 7-bit BUFID. Start from No. 0 buffer RAM: 0 ~ 127, total 128 buffer RAMs. My set-up is using buffer1 that is verified by scope
spiREG1->DMACTRL[CHANNEL_RD_NO].TXDMA_MAP = LINE_WR_NO; // DMA TX channel line number?
spiREG1->DMACTRL[CHANNEL_RD_NO].RXDMA_MAP = LINE_RD_NO; // DMA RX channel line number? RXDMA_MAP should be different from TXDMA_MAP, see page 698 of data sheet
#ifdef LARGE_COUNT
spiREG1->DMACOUNT[CHANNEL_RD_NO] = ( numBytes << 16 );
#else
spiREG1->DMACTRL[CHANNEL_RD_NO].ICOUNT = numBytes;
#endif
spiREG1->DMACTRL[CHANNEL_RD_NO].TXDMA_ENA = 1U;
spiREG1->DMACTRL[CHANNEL_RD_NO].RXDMA_ENA = 1U;
spiREG1->TGCTRL[CHANNEL_RD_NO] &= 0xffff00ff; // let PSTART = 0;
spiREG1->TGCTRL[CHANNEL_RD_NO] |= 0x80000000; // set TGENA bit
////////////////////////////////////////////////////////////////////////
dmaREG->GCTRL |= 0x00010000U; /* enable dma */
spiREG1->DMAREQEN = 1;// condition 1 to start for normal SPI DMA
spiREG1->ENA = 1U; // SPIENA condition 2 to start for normal SPI DMA
}