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.

McASP not generating AREVT0 or AXEVT0 in EDMA3?

Guru 15580 points
Other Parts Discussed in Thread: OMAP-L138, OMAPL138, ADS1278

I am trying to get my OMAP-L138 experimenter to do DMA transfer from McASP to DSP. However, even though the McASP shows XRDY and RRDY bits set (=0x1) in the SCRTL, no AREVT0 or AXEVT0 show up in the EDMA3 Event Register. Yes, I have set EER (=0x3) for both events (AREVT0=0, AXEVT0=1). What could prevent the McASP from generating the EDMA3 events?

Thx

MikeH

 

  • Hi Mike

    What software base/OS are you using to accomplish this? EDMA3LLD, DSP/BIOS McASP drivers, Linux drivers?

    A few things to make sure

    1) I am assuming that EDMA3 clocks are enabled via PSC, seems like it, looking at your email confirming EER is set to 0x3?

    2) The PARAM is configured properly for receive/transmit from/to McASP? What do you see in the PARAM content?

    3) Ensure that you are using EDMA3 channel controller 0 , channel 0 and 1. OMAPL138 has a second 32 bit channel controller that does not support McASP transfers

    4) Make sure that SER register bits corresponding to REVT/XEVT0 are not set

    5) If you are writing your own driver, I hope you are following the sequence specified in the McASP user guide section 2.4.1.2 ?

    6) Make sure that McASP is not in a bad state, underrun conditions etc, where in a reset on McASP is required (section 2.4.7.2).

     

    Hope this helps.

    Regards

    Mukul

     

  • Mukul,

    I am attempting to adap the TTO example found here (https://gforge.ti.com/gf/project/lld_examples/frs/) from McBSP to McASP. It uses DSP/BIOS and EDMA LLD to implement a ping-pong buffered configuration for transferring audio.

    To your questions:

    1. EDMA3 closcks are enabled via PSC in GEL file:

    PSC0_LPSC_enable(0, LPSC_EDMA_CC0);

    PSC0_LPSC_enable(0, LPSC_EDMA_TC0);

    PSC0_LPSC_enable(0, LPSC_EDMA_TC1);

    2.PARAM content:

    PARAMENTRY = 0x01C04000
     [0] = {...}
      OPT = 0x81100000
      SRC = 0x01D02000
      A_B_CNT = 0x00010002
      DST = 0x1181E9B0
      SRC_DST_BIDX = 0x01000000
      LINK_BCNTRLD = 0x00024420
      SRC_DST_CIDX = 0xFF020000
      CCNT = 0x00000080
     [1] = {...}
      OPT = 0x81101000
      SRC = 0x1181E5B0
      A_B_CNT = 0x00010002
      DST = 0x01D02000
      SRC_DST_BIDX = 0x00000100
      LINK_BCNTRLD = 0x00024460
      SRC_DST_CIDX = 0x0000FF02
      CCNT = 0x00000080

    3. EDMA channel controller set to zero.

     

     

     

     

    // Declare Config structure used to initialize the Driver Instance (needed by DRV_open)

    initCfg.isMaster = TRUE;

     

    // we are a master, not a slave on this device

    initCfg.regionId = 0;

     

    // user must specify region (LLD/DRV does not support "global" region)

    initCfg.drvSemHandle = &OsSem;

     

    // OsSem added statically in the .tcf file with an initial count of 1

    initCfg.drvInstInitConfig = instanceConfig;

     

    // device-specific configuration - resources owned by region 1

    initCfg.gblerrCb =

    NULL;

    // callback function to catch channel controller errors such as TCC error, queue threshold exceeded, etc.

    initCfg.gblerrData =

    NULL;

    // any data required by the error callback function

    4. All SER bits = 0

    SHADOW = 0x01C02000
     [0] = {...}
      ER = 0
      ERH = 0
      ECR = 0
      ECRH = 0
      ESR = 0
      ESRH = 0
      CER = 0
      CERH = 0
      EER = 3
      EERH = 0
      EECR = 0
      EECRH = 0
      EESR = 0
      EESRH = 0
      SER = 0
      SERH = 0
      SECR = 0
      SECRH = 0
      RSVD0 = 0x01C02048
      IER = 3
      IERH = 0
      IECR = 0
      IECRH = 0
      IESR = 0
      IESRH = 0
      IPR = 0
      IPRH = 0
      ICR = 0
      ICRH = 0
      IEVAL = 0
      RSVD1 = 0x01C0207C
      QER = 0
      QEER = 0
      QEECR = 0
      QEESR = 0
      QSER = 0
      QSECR = 0
      RSVD2 = 0x01C02098

    5. Using the EDMA LLD driver and the lld_6455 example 8 code from (https://gforge.ti.com/gf/project/lld_examples/frs/) modified for OMAP-L138 (C6748) McASP.

    6. McASP is reset before all EDMA channels are created and EESR is set = 0x3. McASP clocks are started as the final step before returning to DSP/BIOS. After returning to BIOS, then pausing program execution, I see ROVRN=0x1 and XUNDRN =0x1.

    Bottom line question. Shouldn't I see an event in the ER register after starting the McASP?

    Thx,

    MikeH

  • ....also. The linked parameter sets appear to be 32 & 33 (shown below).

    [32] = {...}
     OPT = 0x81100000
     SRC = 0x01D02000
     A_B_CNT = 0x00020002
     DST = 0x1181E8B0
     SRC_DST_BIDX = 0x01000000
     LINK_BCNTRLD = 0x00024420
     SRC_DST_CIDX = 0xFF020000
     CCNT = 128
    [33] = {...}
     OPT = 0x81100000
     SRC = 0x01D02000
     A_B_CNT = 0x00020002
     DST = 0x1181EAB0
     SRC_DST_BIDX = 0x01000000
     LINK_BCNTRLD = 0x00024400
     SRC_DST_CIDX = 0xFF020000
     CCNT = 0x00000080

    However, I don't believe the program is getting to this point. It apears to be stuck before it generates AREVT0 or AXEVT0.

  • MikeH said:
    Bottom line question. Shouldn't I see an event in the ER register after starting the McASP?

    What offset are you looking at to check ER status, if you are using Shadow Region 0 , offset 0x10c02000, then can you make sure you have enabled these channels via enabling DRAE0 register. Alternatively as a quick check you should also be able to see whether or not event is getting latched/visible at offset 0x1000 (Global channel registers)

  • Mike

    I also recommend that you look at the BIOS PSP package, it specifically has McASP+EDMA example

    http://software-dl.ti.com/dsps/dsps_public_sw/psp/BIOSPSP/index.html

    This way you could make sure that you have the right McASP initialization, and not missing anything porting a c6455 McBSP example over.

    Regards

    Mukul

  • Mukul,

    I have looked at both the global ER as well as the shadow ER (0x10c02000). Neither shows a latched event. I would assume that these latched events would get rapidly reset to zero of the EMDA is actually working. Wouldn't this prevent me from being able to see the event, unless I was very lucky and happened to halt the program at jus the right moment? Is there another way to detect whether AREVT0 or AXEVT0 are actually occuring?

  • Mukul,

    "I also recommend that you look at the BIOS PSP package, it specifically has McASP+EDMA example"

    I have looked at this example in the past. Unfortunately, it is build on the PSP package which uses a very different scheme for initializing the McASP. However, I have walked through the code and do not see any major initilization omissions on my part.

    I am guessing that there is some sort of overrun or underrun that is killing the McASP before the EDMA event can occur. This could either be a config error on my part, or a proceduring (ie out of order) initilization or enabling of the MCASP/EDMA regs.

    MikeH

     

  • MikeH said:
    Is there another way to detect whether AREVT0 or AXEVT0 are actually occuring?

    Yes ER will clear if it serviced by the EDMA, and you would've possibly seen a change in the associated PaRAM values. One quick way to check whether or not the McASP generated an event, would be to not enable EER register, this way if the event got latched in the ER register, it will remain latched but not pass through the CC as it wasn't enabled via writes to EESR (to set EER).

     

  • Hi,

    I'm trying to configure the McASP with a external ADC (ADS1278), and i want to use the EDMA3. I'm trying  to use the PSPIOM mini drivers and the same TTO EDMA LLD example.

    The McASP AHCLK is external but the ACLK and frame sync are internal generated, based on the AHCLK. I had build the McASP library without the -DMcasp_EDMA_ENABLE.

    1- Create the User Device driver in DSP/BIOS:

    bios.UDEV.create("MCASP");
    bios.UDEV.instance("MCASP").initFxn = prog.extern("MCASP_DevInit");
    bios.UDEV.instance("MCASP").fxnTableType = "IOM_Fxns";
    bios.UDEV.instance("MCASP").params = prog.extern("MCASP_Params");
    bios.UDEV.instance("MCASP").fxnTable = prog.extern("Mcasp_IOMFXNS");

    #define McaspReg_PFUNC        (0x1E00FFE0u)
    #define McaspReg_PDIR        (0xA0000000u)
    #define McaspReg_GBLCTL        (0x0000001Fu)
    #define McaspReg_DITCTL        (0x00000000u)
    #define McaspReg_DLBCTL        (0x00000000u)
    #define McaspReg_AMUTE        (0x00000000u)
    #define McaspReg_SRCTLn        (0x00000002u)

    #define McaspReg_RMASK        (0x00FFFFFFu)
    #define McaspReg_RFMT        (0x000180B0u)
    #define McaspReg_AFSRCTL    (0x00000492u)
    #define McaspReg_RTDM        (0x00000010u)
    #define McaspReg_RINTCTL    (0x00000020u)
    #define McaspReg_RSTAT        (0x00000000u)
    #define McaspReg_REVTCTL    (0x00000000u)
    #define McaspReg_ACLKRCTL    (0x00000023u)
    #define McaspReg_AHCLKRCTL    (0x00000000u)

    void MCASP_DevInit(){
         MCASP_Params = Mcasp_PARAMS; 

        Mcasp_init();

           MCASP_Params.enablecache=TRUE;
        MCASP_Params.hwiNumber = 8;
        //MCASP_Params.isDataBufferPayloadStructure=FALSE;

        // Mcasp Hardware setup global structure
        //*    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *

        MCASP_Params.mcaspHwSetup.glb.pfunc=            McaspReg_PFUNC;
        MCASP_Params.mcaspHwSetup.glb.pdir=                McaspReg_PDIR;
        MCASP_Params.mcaspHwSetup.glb.ctl=                McaspReg_GBLCTL;
        MCASP_Params.mcaspHwSetup.glb.ditCtl=            McaspReg_DITCTL;
        MCASP_Params.mcaspHwSetup.glb.dlbMode=            McaspReg_DLBCTL;
        MCASP_Params.mcaspHwSetup.glb.amute=            McaspReg_AMUTE;
        //MCASP_Params.mcaspHwSetup.glb.serSetup[0]=        McaspReg_SRCTLn;
        //MCASP_Params.mcaspHwSetup.glb.serSetup[1]=        McaspReg_SRCTLn;
        //MCASP_Params.mcaspHwSetup.glb.serSetup[2]=        McaspReg_SRCTLn;
        //MCASP_Params.mcaspHwSetup.glb.serSetup[3]=        McaspReg_SRCTLn;
        MCASP_Params.mcaspHwSetup.glb.serSetup[4]=        McaspReg_SRCTLn;

        // Mcasp Hardware setup RX data structure
        //*    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *

        MCASP_Params.mcaspHwSetup.rx.mask=                McaspReg_RMASK;
        MCASP_Params.mcaspHwSetup.rx.fmt=                McaspReg_RFMT;
        MCASP_Params.mcaspHwSetup.rx.frSyncCtl=            McaspReg_AFSRCTL;
        MCASP_Params.mcaspHwSetup.rx.tdm=                McaspReg_RTDM;
        MCASP_Params.mcaspHwSetup.rx.intCtl=            McaspReg_RINTCTL;
        MCASP_Params.mcaspHwSetup.rx.stat=                McaspReg_RSTAT;
        MCASP_Params.mcaspHwSetup.rx.evtCtl=            McaspReg_REVTCTL;

        MCASP_Params.mcaspHwSetup.rx.clk.clkSetupClk=    McaspReg_ACLKRCTL;
        MCASP_Params.mcaspHwSetup.rx.clk.clkSetupHiClk=    McaspReg_AHCLKRCTL;
    //    MCASP_Params.mcaspHwSetup.rx.clk.clkChk=        McaspReg_RCLKCHK;
       
        // Mcasp Hardware setup TX data structure
        //*    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *   
        MCASP_Params.mcaspHwSetup.tx.clk.clkSetupClk |= 0x00000040;
    }

    2- Inicialize the EDMA3

    Instance ID =0

    Region =0

    TCC = 0

    Channel =0

    Parameters Set 0

    OPT                        0x81100400
    SRC                       0x01D02000
    A_B_CNT              0x00770001
    DST                        0x11800000
    SRC_DST_BIDX  0x00010000
    LINK_BCNTRLD  0x0004FFFF
    SRC_DST_CIDX  0x00000000
    CCNT                     0x00000080

    void CCeEDMA3::CreateChan(edma_object_t *EdmaObj, unsigned int Src, unsigned int Dst)
    {
        EDMA3_DRV_Result edma3Result = EDMA3_DRV_SOK;  // return value for some driver calls so they can return an error
        EDMA3_DRV_PaRAMRegs currentParam; // used for debug purposes in EDMA3_DRV_getPaRAM()

        EDMA3_RM_EventQueue eventQ = 0; // both used below in _requestChannel()
        //EDMA3_RM_TccCallback tccCb = 0;
        EDMA3_RM_TccCallback tccCb = (EDMA3_RM_TccCallback)*INT8McASP;
       
        edma3Result = EDMA3_DRV_requestChannel (EdmaObj->hEdma, &EdmaObj->iChannel, &EdmaObj->iTcc, eventQ, tccCb, NULL);

        EDMA3_DRV_setSrcParams (EdmaObj->hEdma, EdmaObj->iChannel, Src, EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W128BIT);
        EDMA3_DRV_setDestParams (EdmaObj->hEdma, EdmaObj->iChannel, Dst, EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W128BIT);

        EDMA3_DRV_setSrcIndex(EdmaObj->hEdma, EdmaObj->iChannel, 0, 0);
        EDMA3_DRV_setDestIndex(EdmaObj->hEdma, EdmaObj->iChannel, 1, 0);

        EDMA3_DRV_setTransferParams(EdmaObj->hEdma, EdmaObj->iChannel, 1,128,128,4,EDMA3_DRV_SYNC_A);

        EDMA3_DRV_setOptField (EdmaObj->hEdma,EdmaObj->iChannel, EDMA3_DRV_OPT_FIELD_TCINTEN, EDMA3_DRV_TCINTEN_EN);  
        EDMA3_DRV_setOptField (EdmaObj->hEdma,EdmaObj->iChannel, EDMA3_DRV_OPT_FIELD_TCC, 0u); 
       
        //  For debug purposes, get currentParam set so that we can add it to a watch window for debug
        EDMA3_DRV_getPaRAM(EdmaObj->hEdma, EdmaObj->iChannel, &currentParam);
    }

    void CCeEDMA3::Start(edma_object_t EdmaObj)
    {
        EDMA3_DRV_Result edma3Result = EDMA3_DRV_SOK;
        edma3Result = EDMA3_DRV_enableTransfer(EdmaObj.hEdma, EdmaObj.iChannel, EDMA3_DRV_TRIG_MODE_EVENT);
    }

    Can somebody help me???

    Can I use the McASP building the library without -DMcasp_EDMA_ENABLE and use the TTO EDMA LLB Library with McASP at same time?

    Do i need to create a DIO and SIO API's?

    How I can see the McASP AREVT? How I know that EDMA3 see the event?

    What is the right EDMA configuration for McASP receive events?

    How I configure the EDMA TCC interrupt in Bios witout use the ECM Events?

    Regards,

    Luis Mendes

  • Luis,

    I would appreciate if you would not hijack my thread. This is a very important problem and we have not yet solved it. Would you please post your question on a new thread?

    thx

    MikeH

  • Mike

    Can you try a value of ACNT=4 instead of 2 for your EDMA setup for transfers to/from XBUF/RBUF

    or alternatively if you are using ACNT=2 , can you try to write to individual serializers like XBUF0 or RBUF0

    Regards

    Mukul

  • Mukul,

    With an ACNT=2, I *do* get data transferred into my receive buffer! Why did this work? What's going on? And how do I fix this?

    Progress!!

    MikeH

     

  • You mean ACNT=4 ?

  • Sorry...yes, ACNT=4 (got too excited...:)

    I can also watch the params change each time I reset the processor (CCNT becomes a random number between zero and CCNT=128) indicating that the event is occuring properly.

  • Mike

    I didn't review your param settings very carefully when you first posted it , as  I was still fishing for other probable errors (sorry about that). The bottom line is that  for the DMA ports XBUF/RBUF , it is always recommended to use 32 bit transfers aka ACNT=4. Doing 8 or 16 bit transfers does not work well with these ports. If you need 16 bit data I believe there are McASP registers that you can configure to have masking etc.

    Hope this helps.
    Regards

    Mukul

     

  • Mukul,

    No problem. At least I now have data being transferred. I believe you are correct that McASP can mask and rotate.

    Thanks for the assistance!

    MikeH

  • So Mike,

     

    Eric here. Mukul - thanks for handling Mike's questions. He had been emailing me and I hadn't gotten around to helping him yet - so I'm glad he posted to the forum. By the way Mike, when I have questions, Mukul is one of the people I go to for answers as well - he's a keeper. ;)

    So what ended up being the issue? I emailed Mukul a little while ago and told him I suspected the McASP setup. The setup code in the workshop (which I modified from LogicPD's BSL) configures CPU interrupts, not EDMA events. If you look at the McASP datasheet, you'll find the exact bits that need to change. There are also some other McASP config steps that are different for EDMA that I saw as I was writing the McASP setup code.

    I suspected that the McASP was the problem - you were getting CPU ints instead of EDMA events. Was that the problem?

    The info Mukul sent you was also news to me - about the data sizes - but I probably would have suspected that since the McASP ALWAYS deals with 32 bits - and when you READ a 16-bit audio sample (like in the TTO workshop or any 16-bit data size app), the 16-bits lands in the UPPER half of the 32-bit X/RBUF. When you read it, you have to strip off the lower 16 bits OR, turn on ROR like I did in the McASP setup code (makes the code more readable and less messy - but users who take that code from the BIOS workshop need to know that's happening because it is basically hidden - although it is commented).

     

    Mukul mentioned ACNT had to be 4 - that is good info. I'm not positive how you get the 16-bit audio size out of the EDMA write of 32 bits. Same with the writes to the McASP. Maybe Mukul can answer this also.

     

    Thanks,

    eric

  • Mike, et al,

    There are two EDMA3 tricks I have tried to implement on a customer's multi-serializer McASP system where she wants to use 16-bit data. These are to either use ACNT=4 and BIDX=2 or use an interim buffer that is spread out into 32-bit words.

    In the first case, SYNCDIM=ABSYNC, ACNT=4 so that 32-bit accesses will occur to the McASP, and SRCBIDX(tx)/DSTBIDX(rx)=2. This has the positive effect of maintaining the 32-bit accesses required by the McASP side while also maintaining a packed buffer of short's. The negative effect is that for the rx process an extra 16 bits gets written to the memory buffer at the end of the buffer. This is easy to allow for, but it does have to be planned and expected.

    In the second case, when a set of buffers are ready to transmit, an extra step is required to copy all of the packed shorts into a 2x-sized buffer of interleaved 32-bit samples for the multiple serializers, then the AXEVTn events will trigger a DMA transfer from the 2x buffer in 32-bit words to match the 32-bit size needed by the McASP. For the receive process, the incoming samples would be stored into a 2x-sized buffer and after the last sample comes in for that buffer an additional DMA channel would be chained to and would copy the shorts into the separate buffers as needed.

    I am not sure if my explanation is very clear. If you want to try it and would like me to be clearer, please let me know. Give me some details like how many serializers, how the buffers are allocated, and so on and I will try to be more helpful.

    Regards,
    RandyP

  • Randy,

    Great minds think alike! Yesterday I implemented case #1 and it works perfectly. Thanks for the heads-up on the overwrite into the next memory location(s). I saw this happening in CCS4 memory watch window, but wasn't sure if it was just a bug or real. Looks like it is real and something I need to allow for (it was clobbering one of my variables).

    Also, thanks for the great on-line video tutorial on EDMA3. I have watched it numerous times, and frequently re-watch sections when I get myself confused (regular occurance).

    So, FYI, I now have a reliable AIC3106->McASP ->EDMA3->Ram->algorithm->Ram->EDMA3->McASP->AIC3106 working with excellent quality audio!

    Thanks to Eric Wilbur (TTO Workshop author), Mukul (ACNT=4 enlightenment), and RandyP (excellent video tutorial)!!

    MikeH