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.

TMS320C6748: EDMA3

Part Number: TMS320C6748

Finally got around to trying QDMA.  Didn't work :(

My scheme is as follows;

Use QDMA channel 0 to read from a 16-bit GPIO port 16 times and save the readings in an array of 16-bit words.

After POR, I set it up as follows:

// PaRAM Block

#define PaRAM_START 0x01c04000
#define PaRAM_SET_0 0x4000
#define PaRAM_SET_1 (PaRAM_SET_0 + 32)
#define PaRAM_SET_2 (PaRAM_SET_1 + 32)
#define RF_IN (SOC_GPIO_0_REGS + 0x70)
#define NO_LINK 0XFFFF

#define QCHMAP0 0x01c00200
#define QER 0x01c01080
#define QEER 0x01c01084
#define QEECR 0x01c01088
#define QEESR 0x01c0108c

#define IER 0x01c01050
#define IECR 0x01c01058
#define IESR 0x01c01060
#define IPR 0x01c01068
#define ICR 0x01c01070
#define RFDMA_READY (HWREG(IPR) & 0x00000001)

struct __attribute__((__packed__)) T_PaRAM {
// keep declaration order below!
uint32 opt;
uint32 src;
uint16 acnt;
uint16 bcnt;
uint32 dst;
uint16 srcbidx;
uint16 dstbidx;
uint16 link;
uint16 bcntrld;
uint16 srccidx;
uint16 dstcidx;
uint16 ccnt;
uint16 rsvd;
};

int16 RF_READINGS[16];

#pragma LOCATION(data_PaRAM, PaRAM_START)
struct __attribute__((__packed__)) T_PaRAM data_PaRAM;
//=============================================================================

bool QDMA_Done() {
return (RFDMA_READY);
}

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

void InitQDMA() {


int i;
for (i=0;i<16;i++) {
RF_READINGS[i] = 0;
}

//enable QDMA Ch 0
HWREG(QEESR) = 0x00000001;
//clear interrupt status
HWREG(ICR) = 0x00000001;
//set interrupt enable
HWREG(IESR) = 0x00000001;
// initialize PaRAM Set 0
data_PaRAM.src = RF_IN;
data_PaRAM.acnt = 2;
data_PaRAM.bcnt = 16;
data_PaRAM.srcbidx = 0;
data_PaRAM.dstbidx = 2;
data_PaRAM.bcntrld = 0;
data_PaRAM.srccidx = 0;
data_PaRAM.dstcidx = 0;
data_PaRAM.ccnt = 1;
data_PaRAM.dst = (uint32) &RF_READINGS;
data_PaRAM.link = NO_LINK;
// trigger word; must be the last assignment statement in the function
data_PaRAM.opt = 0x00100008; //TCINTEN=1, STATIC=1
}
Then, in an while(1) loop, I call QDMA_Done() to check the bit 0 of IPR.  If it's set, I process the data.  Then, InitQDMA() is called to repeat the procedure.  It does not seem to work - no data transfer observed.  What seems to be missing or incorrect?
  • Hi,

    I thought you read from a fixed address (GPIO port) and move the data into a buffer with incremental destination address. For the simplest case, just read GPIO 16-bit once, so you ACNT=2, BCNT=1, will this work for you? That is, will you see the IPR bit set? What is your QDMA trigger word? If nothing happened, do you see any error for EDMA transfer? E.g in ERRSTAT register?

    In the 16 times read, I thought you need to use SAM=0, DAM=1 in the OPT field.

    Regards, Eric

  • Great to have someone finally reply!!  Thanks!!

    For learning purpose, I simplified the code so it is a memcpy of 8 byte array.  When I run it, it results in error .  ERRSTAT and ERRDET.  What could be happening?

    ERRSTAT 0x00000001 Error Status [Memory Mapped]
    _RESV_1 **************************** Reserved
    MMRAERR 0 - NONE MMR Address Error Event
    TRERR 0 - NONE TR Error Event
    _RESV_4 * Reserved
    BUSERR 1 - ERROR Bus Error Event
    ERREN 0x00000000 Error Enable [Memory Mapped]
    ERRCLR 0x00000000 Error Clear Register [Memory Mapped]
    ERRDET 0x00010001 Error Details [Memory Mapped]
    _RESV_1 ************** Reserved
    TCCHEN 0 Transfer Completion Chaining Enable
    TCINTEN 1 Transfer Completion Interrupt Enable
    _RESV_4 ** Reserved
    TCC 000000 Transfer Completion Code
    _RESV_6 **** Reserved
    STAT 0001 - READ_ADDRESS Transation Status
    ERRCMD 0x00000000 Error Command [Memory Mapped]

  • Here is the new code snippet:

    bool QDMA_Done() {
    uint32 x = RFDMA_READY;
    bool tb = (x != 0) ? TRUE : FALSE;
    return (tb);
    }

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

    void InitQDMA() {

    //clear interrupt status
    HWREG(ICR) = 0x00000001;

    int i;
    for (i=0;i<8;i++) {
    dstdata[i] = 0;
    }

    // initialize PaRAM Set 0
    HWREG(QCHMAP0) = 0x0000000c;
    HWREG(QEESR) = 0x00000001;
    data_PaRAM.src = (uint32) srcdata;
    data_PaRAM.acnt = 1;
    data_PaRAM.bcnt = 8;
    data_PaRAM.srcbidx = 1;
    data_PaRAM.dstbidx = 1;
    data_PaRAM.bcntrld = 1;
    data_PaRAM.srccidx = 0;
    data_PaRAM.dstcidx = 0;
    data_PaRAM.ccnt = 1;
    data_PaRAM.opt = 0x0010000c; //TCINTEN=1, STATIC=1, SYNCDIM=1
    data_PaRAM.link = NO_LINK;
    // trigger word; must be the last assignment statement in the function
    //set interrupt enable
    //enable QDMA Ch 0
    HWREG(IESR) = 0x00000001;
    data_PaRAM.dst = (uint32) dstdata;

    /* int i;
    for (i=0;i<16;i++) {
    RF_READINGS[i] = 0;
    }

    //clear interrupt status
    HWREG(ICR) = 0x00000001;
    //enable QDMA Ch 0
    HWREG(QEESR) = 0x00000001;
    // initialize PaRAM Set 0
    data_PaRAM.src = RF_IN;
    data_PaRAM.acnt = 2;
    data_PaRAM.bcnt = 16;
    data_PaRAM.srcbidx = 0;
    data_PaRAM.dstbidx = 2;
    data_PaRAM.bcntrld = 0;
    data_PaRAM.srccidx = 0;
    data_PaRAM.dstcidx = 0;
    data_PaRAM.ccnt = 1;
    data_PaRAM.dst = (uint32) &RF_READINGS;
    data_PaRAM.link = NO_LINK;
    // trigger word; must be the last assignment statement in the function
    //set interrupt enable
    HWREG(IESR) = 0x00000001;
    data_PaRAM.opt = 0x00100008; //TCINTEN=1, STATIC=1
    */
    }

  • Some progress made.  Address adjustments for source and destination in the PaRAM made it work.  I found out from other e2e posts that L2 RAM is addressed differently from edma3.

    Proceeding to the gpio to 16 sample storage in L2 RAM ... If I try one sample only - that is, transfer one 16 bit gpio read to one 16 bit memory location, it works.  But, one to 16 scheme does not work.  Basically, I am waiting for the interrupt bit in IPR to get set forever.  The parameters are

    data_PaRAM.acnt = 2;
    data_PaRAM.bcnt = 16;
    data_PaRAM.srcbidx = 0;
    data_PaRAM.dstbidx = 2;
    data_PaRAM.bcntrld = 0;
    data_PaRAM.srccidx = 0;
    data_PaRAM.dstcidx = 0;
    data_PaRAM.ccnt = 1;

  • Hi,

    Great that you made progress --- transfer one 16 bit gpio read to one 16 bit memory location, it works. For "But, one to 16 scheme does not work.", that is you read the FIFO 16 times and each time save the reading out to a different location. You may try if data_PaRAM.dstbidx = 4 helps. Also in the OPT field, there are bit settings: Intermediate transfer completion interrupt enable and Transfer complete interrupt enable, and Transfer synchronization dimension. Try to see if using A-sync only and both intermediate and transfer complete interrupt enable, how far you can go. Whether you saw the GPIO data in the buffers or not? And how many buffers received data?

    Also I'm not sure the reason you need 16 consecutive QDMA read. The DMA read is so fast and the GPIO may not populated with the new data. So you may have 16 identical GPIO data put into 16 different destination buffers. Why not each time you just do one 16-bit GPIO read into a memory, then the application needs to know when the next GPIO data will come in and schedule another QDMA read.

    Regards, Eric   

  • It's working finally after setting it up for AB synchronization.

    Question:

    If the polling code is slow and unable to respond in time to active IPR bit and let's say QDMA uses linking, it is possible to miss an interrupt. My question is the missed interrupt unrecoverable?  IPR bit overwritten and previous one is not retained? 

  • Hi,

    I tried the scenario where IPR is not cleared (via writing ICR), but another DMA transfer came in from the same DMA channel. I found the second transfer still happened and IPR bit is overwritten amd previous interrupt is missed and can't be recovered.

    Regards, Eric 

  • Thanks.  That is good info.

    I'm definitely learning more about edma3.  Still not clear about why A synchronization would not work, but AB sync does.

    Thanks again for the follow up.

    Peter