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.

DMA from internal RAM to RAM

Other Parts Discussed in Thread: TMS570LS3137
I tried to a simple DMA from internal RAM to RAM as coded below. However, it did not happen. After this function get called, I checked the dma status register and found that there is no dma channel is active, its PEND bit is set. Did I missed something that prevented from activating the dma? I have tried both DMA_REQ_TYPE_HW, and DMA_REQ_TYPE_SW trig. Neither worked.  Please help me to remind me that I missed something important item to trig it.
 
from TMS570LS3137, the RAM location is correct
 
 
#define CHANNEL_NO 7
#define LINE_NO    7
 
void DMA_WriteBlockTest(SS_U16 *dataBlock, SS_U32 startAddress, SS_U32 numBytes)
{
DMA_CONTROL_PACKET_ST dmaCtrlPktn;
dmaREG->GCTRL  = 0x00000001U; /* reset dma       */
while(dmaREG->GCTRL);
dmaCtrlPktn.SADD = (SS_U32)(dataBlock); //source address of DMA, Post-incremented
dmaCtrlPktn.DADD = 0x08030000; //destination of DMA,
dmaCtrlPktn.FRCNT =  (numBytes >> 2);   //Frame count
dmaCtrlPktn.ELCNT = 1;   //element count
dmaCtrlPktn.ADDMODERD = ADDR_INC1; //post-incremented
dmaCtrlPktn.ADDMODEWR = ADDR_INC1; //post-incremented
dmaCtrlPktn.RDSIZE = SS_DMA_ACCESS_16_BIT; //16-bit
dmaCtrlPktn.WRSIZE = SS_DMA_ACCESS_16_BIT; //16-bit
dmaCtrlPktn.TTYPE = FRAME_TRANSFER;  //frame
dmaCtrlPktn.AUTOINIT = AUTOINIT_OFF; //auto-init
dmaCtrlPktn.CHCTRL = 0; // 0 for not chaining. n+1 for channel n, channel control, chain channel
dmaCtrlPktn.ELDOFFSET = 0;  //element destination offset
dmaCtrlPktn.ELSOFFSET = 0;  //element source offset
dmaCtrlPktn.FRDOFFSET = 0;  //frame destination offset
dmaCtrlPktn.FRSOFFSET = 0;  //frame source offset
SS_DMA_ReqAssign(CHANNEL_NO, LINE_NO);    // (SS_U32 channel, SS_U32 reqline)
SS_DMA_SetCtrlPacket(CHANNEL_NO, &dmaCtrlPktn);
SS_DMA_SetChEnable(CHANNEL_NO, DMA_REQ_TYPE_HW);
// SS_DMA_SetChEnable(CHANNEL_NO, DMA_REQ_TYPE_SW);
dmaREG->GCTRL |= 0x00010000U; /* enable dma      */
}
 
  • Wan,

    Looks like you are not explicitly setting Port assignment (PORTASGN) to dmaControlPacket stack variable.

    dmaSetCtrlPacket() uses that value and could be invalid.

    I believe you should set the port to 4.

    Joe

  • Dear Joe,

    It has been tested working for DMA_REQ_TYPE_SW after putting PORTASGN = 4 in block transfer. When in frame transfer, it copied only one 16-bit data into destination address.

    However when I am using DMA_REQ_TYPE_HW instead, it did not happen.

    In previous condition without PORTASGN = 4 in the line:
    1) when in DMA_REQ_TYPE_SW type, the PEND bit is set;
    2) when in DMA_REQ_TYPE_HW type, the PEND bit is NOT set;

    We need to use DMA_REQ_TYPE_HW to trigger. It looks like I have missed something else for hardware triggering. Please help me on this.

    Thank you and Best Regards,

    Long Wan
  • Long Wan,

    SW request type with AUTO_INIT OFF mode will do only ONE FRAME as you found out.

    Make sure that your HW request line is the correct request line and the source peripheral is configured properly to trigger DMA request.

    Note that the request line and DMA channels are not the same thing (looking at Ch7 and request line 7 that you have).

    Request Line 7 can be triggered by MIBADC1 / MIBSPI5 modules. Please refer to Section 6.16.2 Default DMA Request Map for the DMA request line connection in the data sheet page 95: www.ti.com/.../tms570ls3137.pdf

    Joe

  • Long,

      DMA transfers are described in SPNU499 sections 16.2.2 (SPNU499B page 534).
      Here it shows that when the transfer type is frame (0) it will transfer one frame per trigger,
                 if you change to block mode(1) it will transfer the entire block (or FRCNT * ELCNT * wrsize bits).

     Dave

  • Hi Joe,

    The purpose of my RAM to RAM test is try to implement SPI-DMA application in the project of UTC Aerospace Systems. According to Section 6.16.2 DMA request Map, I have set up request line 0 to DMA channel 7, and some SPI settings and made DMA from RAM to SPI Tx Register through hardware DMA_REQ working properly!!! Thank you for your help! 

    However, there are some problems in SPI side now. When the following function get called the SPI is sending continuously and going forever. The data is DMAed data through hardware DMA_REQ. If I commented out the following line for spiREG1->TGCTRL[1]  setting in the function, 

    | (TRG_ALWAYS << 20) // trigger event, if this line is commented out, there will be no SPI clock, no DMA request sent!

    then SPI will not send out any thing at all. My question is how can make SPI send the data out exactly. As seen by using LARGE_COUNT , I put

    spiREG1->DMACOUNT[CHANNEL_NO] = ( numBytes << 16 );

    and hardware DMA_REQ just made exactly the number of requests as the data size for 16-bit data transfer. That is quite good. I know that TRG_ALWAYS may cause the sending forever problem. But should remove this line, it will not trigger the SPI clock event, though the following two line that enables SPI machine.

    spiREG1->DMAREQEN = 1; // condition 1 to start for normal SPI DMA, not for multi-buffer ram
    spiREG1->ENA = 1U; // SPIENA condition 2 to start for normal SPI DMA, not for multi-buffer ram

    Please help me on SPI side for SPI-DMA application.

    Thank you and Best Regards,

    Long Wan

    //==============================================================================

    #define CHANNEL_NO 7
    #define LINE_NO 0
    #define LARGE_COUNT //LARGE_COUNT looks required for the following set-up. Otherwise, the scope got meaningless curve


    void SS_NVM_SPI_DMA_WriteBlockTest(SS_U16 *dataBlock, SS_U32 startAddress, SS_U32 numBytes)
    {
    SS_DMA_CONTROL_PACKET_ST dmaCtrlPktn;
    dmaREG->GCTRL = 0x00000001U; /* reset dma */
    while(dmaREG->GCTRL);
    dmaCtrlPktn.SADD = (SS_U32)(dataBlock); //source address of DMA, Post-incremented
    dmaCtrlPktn.DADD = 0xff0e0006; //0xff0e0006; destination of SPI-DMA, Fixed address needed here
    // this is buffer 1 address is verified by scope
    dmaCtrlPktn.FRCNT = (numBytes); //Frame count
    dmaCtrlPktn.ELCNT = 1; //element count
    dmaCtrlPktn.PORTASGN = 4U; //Port B
    dmaCtrlPktn.ADDMODERD = ADDR_INC1; //post-incremented
    // dmaCtrlPktn.ADDMODEWR = ADDR_INC1; //ADDR_FIXED is required for SPI-DMA, here just for testing to see whether or not a block of data is
    dmaCtrlPktn.ADDMODEWR = ADDR_FIXED; //ADDR_FIXED; //constant
    dmaCtrlPktn.RDSIZE = SS_DMA_ACCESS_16_BIT; //16-bit
    dmaCtrlPktn.WRSIZE = SS_DMA_ACCESS_16_BIT; //16-bit
    dmaCtrlPktn.TTYPE = FRAME_TRANSFER; //FRAME_TRANSFER is required for SPI-DMA
    dmaCtrlPktn.AUTOINIT = AUTOINIT_ON; //AUTOINIT_OFF AUTOINIT_ON auto-init
    dmaCtrlPktn.CHCTRL = 0; //CHANNEL_NO +1; // 0 for not chaining. n+1 for channel n, channel control, chain channel
    dmaCtrlPktn.ELDOFFSET = 0; //element destination offset
    dmaCtrlPktn.ELSOFFSET = 0; //element source offset
    dmaCtrlPktn.FRDOFFSET = 0; //frame destination offset
    dmaCtrlPktn.FRSOFFSET = 0; //frame source offset
    SS_DMA_ReqAssign(CHANNEL_NO, LINE_NO); // (SS_U32 channel, SS_U32 reqline)
    SS_DMA_SetCtrlPacket(CHANNEL_NO, &dmaCtrlPktn);
    SS_DMA_SetChEnable(CHANNEL_NO, SS_DMA_REQ_TYPE_HW); // SS_DMA_REQ_TYPE_HW is required for SPI-DMA
    dmaREG->GCTRL |= 0x00010000U; /* enable dma */
    spiREG1->ENA = 0; // SPIENA hold low for configuration
    spiREG1->GCR0 = 1; // to allow SPI register configurable per 14.8 on page 617
    /** enable SPI multi-buffered mode and enable buffer RAM */
    while (spiREG1->BUFINIT) ; // wait until this bit is cleared 
    spiREG1->PCFUN |= (1 /* SCS[0] */
    | (1 << 1)
    | (1 << 9) /* CLK */
    | (1 << 10) /* SIMO */
    | (1 << 11)); /* SOMI */

    // spiREG1->GCR1 = ... // CLKMOD, MASTER bit setting
    spiREG1->GCR1 = (1 << 1) /* CLOCKMOD */
    | 1; /* MASTER */
    // spiREG1->FMT[0] = ... // set wait, delay, phase, shift direction ...
    // spiREG1->DELAY = ... // set as Master delay values
    spiREG1->DELAY = (5 << 24) /* C2TDELAY */
    | (0 << 16) /* T2CDELAY */
    | (0 << 8) /* T2EDELAY */
    | 0; /* C2EDELAY */

    spiREG1->FMT0 = 0; // already cleared to 0, the following 3 lines are not necessary needed.
    // spiREG1->FMT0 &= ~(1 << 24); // wdelay
    // spiREG1->FMT0 &= ~(1 << 20); // shift direction
    // spiREG1->FMT0 &= ~(1 << 17); // clock polarity

    spiREG1->FMT0 |= (1 << 16); /* clock phase */
    spiREG1->FMT0 |= (baudratePrescaler << 8); /* baudrate prescale */
    spiREG1->FMT0 |= 16; /* data word length */

    while(spiREG1->BUFINIT & 0x1000000); // wait until BUFINITACTIVE = 0
    /** - initialize transfer groups */
    spiREG1->TGCTRL[1] = (1 << 31) // TGENA
    | (0 << 29) // pcurrent reset
    | (TRG_ALWAYS << 20) // trigger event, if this line is commented out, there will be no SPI clock, no DMA request sent!
    | (TRG_DISABLED << 16) // trigger source
    | (1 << 8); // start buffer
    /* The following TGs are unused */
    spiREG1->TGCTRL[2] = (2 << 8); /* start buffer */
    spiREG1->TGCTRL[3] = (2 << 8); /* start buffer */
    spiREG1->TGCTRL[4] = (2 << 8); /* start buffer */
    spiREG1->TGCTRL[5] = (2 << 8); /* start buffer */
    spiREG1->TGCTRL[6] = (2 << 8); /* start buffer */
    spiREG1->TGCTRL[7] = (2 << 8); /* start buffer */
    spiREG1->TGCTRL[8] = (2 << 8);
    spiREG1->LTGPEND = 1; // TG end pointer
    // TG 1
    spiRAM1->tx[1].control = (4 << 13); // buffer mode Continues mode
    spiRAM1->tx[1].control |= (1 << 12); // hold chip select
    spiRAM1->tx[1].control &= ~(1 << 11); // lock transmission
    spiRAM1->tx[1].control &= ~(1 << 8); // data format
    spiRAM1->tx[1].control |= CS_0; // chip select

    // spiREG1->DMACNTLEN = 1U; // select large count for SPI DMA, here try small first
    /** - set interrupt levels */
    spiREG1->LVL = 0;
    /** - clear any pending interrupts */
    spiREG1->FLG = 0xFFFFFFFFU;

    /** - enable/disable interrupts */
    spiREG1->INT0 = 0;
    /** @b initialize @b SPI @b Port */

    /** - SPI Port output values */
    /* Set CS high */
    spiREG1->PCDOUT |= 1; /* SCS[0] */

    spiREG1->PCDOUT &= ~((1 << 9) /* CLK */
    | (1 << 10) /* SIMO */
    | (1 << 11)); /* SOMI */

    /** - SPI Port direction - outputs */
    spiREG1->PCDIR |= 1 /* SCS[0] */
    | (1 << 9) /* CLK */
    | (1 << 10); /* SIMO */

    /** - SPI Port direction - inputs */
    spiREG1->PCDIR &= ~(1 << 11); /* SOMI */

    /** - SPI Port open drain enable */
    spiREG1->PCPDR &= ~( 1 /* SCS[0] */
    | (1 << 9) /* CLK */
    | (1 << 10) /* SIMO */
    | (1 << 11)); /* SOMI */

    /** - SPI Port pullup / pulldown selection */
    spiREG1->PCPSL |= 1 /* SCS[0] */
    | (1 << 9) /* CLK */
    | (1 << 10) /* SIMO */
    | (1 << 11); /* SOMI */

    /** - SPI Port pullup / pulldown enable*/
    spiREG1->PCDIS &= ~( 1 /* SCS[0] */
    | (1 << 9) /* CLK */
    | (1 << 10) /* SIMO */
    | (1 << 11)); /* SOMI */

    /* SPI set all pins to functional */
    spiREG1->PCFUN |= (1 /* SCS[0] */
    | (1 << 9) /* CLK */
    | (1 << 10) /* SIMO */
    | (1 << 11)); /* SOMI */
    // spiREG1->DMACNTLEN = 0x01; // Enable large count
    /** - start SPI */
    spiREG1->CSDEF = 1U; //

    #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->RAMACCESS |= 1U; // to use Multi-buffer mode by set bit MSPIENA
    #endif
    dmaREG->DREQASI[1] = LINE_NO; // channel 7 (bit 0-5 of DREQASI[1])is assigned for line 0 to trigger DMA
    spiREG1->DMACTRL[CHANNEL_NO].ONESHOT = 1; // set, not clear ONESHOT
    spiREG1->DMACTRL[CHANNEL_NO].NOBRK = 1U; // set NOBRK
    spiREG1->DMACTRL[CHANNEL_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_NO].TXDMA_MAP = LINE_NO; // DMA TX channel line number?
    spiREG1->DMACTRL[CHANNEL_NO].RXDMA_MAP = LINE_NO+1; // DMA RX channel line number? RXDMA_MAP should be different from TXDMA_MAP, see page 698 of data sheet
    spiREG1->DMACTRL[CHANNEL_NO].ICOUNT = numBytes; // send by ICOUNT+1 buffer, confusing? 5-bit count can send max buffer with 32. However there are 128 16-bit in single Tx buffer.
    spiREG1->DMACTRL[CHANNEL_NO].COUNT = numBytes+1; // send by ICOUNT+1 buffer,
    #ifdef LARGE_COUNT
    spiREG1->DMACOUNT[CHANNEL_NO] = ( numBytes << 16 );
    #endif
    spiREG1->DMACTRL[CHANNEL_NO].TXDMA_ENA = 1U;
    spiREG1->DMACTRL[CHANNEL_NO].RXDMA_ENA = 1U;
    /////////////////////////////////////////////////// ther following 2 items have been tested and there is no effect on scope result
    spiREG1->TGCTRL[CHANNEL_NO] &= 0xffff00ff; // let PSTART = 0;
    spiREG1->TGCTRL[CHANNEL_NO] |= 0x80000000; // set TGENA bit
    ////////////////////////////////////////////////////////////////////////
    spiREG1->DMAREQEN = 1; // condition 1 to start for normal SPI DMA, not for multi-buffer ram
    spiREG1->ENA = 1U; // SPIENA condition 2 to start for normal SPI DMA, not for multi-buffer ram

    }

  • Hi Dave,

    Thank you for the information. I have made both software and hardware DMA triggering working. Please see my reply to Joe. Now I have problem in SPI side. It is either sending SPI data forever, or sending nothing.

    Best Regards,

    Long Wan