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 HWI being generated based on disabled events in XINTCTL/RINTCTL

Hello,

I am working with a TMSC320C6748, and trying to limit the interrupts generated by the McASP to XDATA, XCKFAIL, XSYNCERR and XUNDRN.  Plus the same, equivalent for RINTCTL.  However, it appears that I'm ending up in my McASP hardware interrupt service routine when none of those 4 are active.  For instance, I read the RSTAT and XSTAT right at the front of the McASP interrupt, and sometimes it's just STAFRM is active, or STAFRM and LAST together (i.e. 0x40 or 0x50 in the XSTAT/RSTAT registers).  Niether of these are enabled in XINTCTL or RINTCTL, so I'm wondering why an interrupt is being generated.

Ever heard of this, or having any suggestions of how to root cause?  Please advise.

Robert

  • Additional information, using these definitions:

        "true interrupt" = expected interrupt (conditions enabled in XINTCTL or RINTCTL)

        "false interrupt" = unexected interrupt (conditions not enabled in XINTCTL or RINTCTL)

    I'm using BIOS v5.41.  Interrupts are using the HWI_Dispathcher, including the McASP HWI I'm having this issue with.  I normally would service them with EDMA, but for debugging this, I'm simply polling in the HWI routine.  I am targeting a stereo sample rate of 25 Khz, which breaks down to 12.5 Khz for each channel, and have set the McASP clock dividers accordingly. 

    For now, the TX channels are just being fed with the last RX data.  What I am seeing is that I'll get an interrupt where both the RX and TX DATA flags are set, so both are serviced (data read from RX, sent to TX, via serializers 11 and 12).  This is the "true interrupt".  On the way out of that interrupt, I also read and log the XSTAT and RSTAT values, and see that the RDATA and XDATA flags were cleared, leaving 0x50 in TSTAT and 0x40 in RSTAT.  But the very next interrupt, the "false interrupt"  will contain the same 0x50 in TSTAT and 0x40 in RSTAT, even though that should not generate an interrupt, because of my XINTCTL and RINTCTL settings.  I try to clear those flags anyways during the "false interrupt".  The next interrupt will again be the "true interrupt", for RDATA and XDATA, followed by another "false interrupt". 

    So the sequence is:

        true interrupt -> clear RDATA and XDATA flags in XSTAT/RSTAT

        false interrupt -> try clear whatever flags are set in XSTAT/RSTAT, even though they are not enabled in RINTCTL/XINTCTL

        true interrupt

        false interrupt

        ... etc

    This occurs at the targeted 25 Khz rate (combined true plus false interrupts occuring at 25 Khz, with false following in about 5 us).

    It's almost like the interrupt processor logic isn't recognizing that the RDATA and XDATA flags were cleared after it leaves the "true interrupt" and imediately comes back in.

    I have no other events that I know of routed to that interrupt (INT4), other than the McASP event.

    Robert

  • Robert,

    I think I've experienced this same issue in the past.  In my case the root cause of the issue was due to the fact that the ISR for McASP is actually a shared ISR on c6748, i.e. there is a single combined interrupt (interrupt #61) which serves as both the transmit and receive interrupt.  As a result, when you're in the ISR you must conditionally read from the receive register and conditionally write to the transmit register.  Here' s a snippet of code from the BIOS workshop:


     // This ISR is executed for either a RCV (RRDY) or XMT (XRDY) interrupt from the McASP.
     // Therefore, we must check to see if it was RRDY or XRDY that triggered this ISR and
     // read or write accordingly.


     // check for receive ready
      if(CHKBIT(MCASP->SRCTL12, RRDY)) {    //if ISR triggered by RRDY...
       
      //read 32 bits from McASP (ROR 16, so lower 16 bits valid) and store in InBuf 
      dataIn32 = MCASP->XBUF12;
      pInBuf_local[blkCnt] = (int16_t)(dataIn32);
      
     }
     
     
     // check for transmit ready
        if(CHKBIT(MCASP->SRCTL11, XRDY)) {    //if ISR triggered by XRDY...
         
      //read 16 bits from XMT buffer and send to McASP XMT
      dataOut32 = pOutBuf_local[blkCnt];
      MCASP->XBUF11 = dataOut32;
     
        blkCnt++; 
                 
     }

     

     

     

     

  • Brad,

    Thanks for the reply.  I can understand it being a shared RX and TX interrupt.  In that case, though, it should be reflected by either RDATA in RSTAT or XDATA in XSTAT.  But in my case, there is that in-between “false” interrupt where neither RDATA or XDATA is indicated, nor any other McASP interrupt that is enabled in RINCTL/XINTCTL. 

    What I typically see is:

        (isr n + 0) RDATA and XDATA set in RSTAT/XSTAT

        (isr n + 1) false interrupt

        (isr n + 2 ) RDATA and XDATA set in RSTAT/XSTAT

        (isr n + 3) false interrupt

    where the false interrupt includes:

        RLAST = 0x50

        XSTAT = 0x40

    or

        RLAST = 0x8

        XLAST = 0x18

    which is RTDMSLOT, XTDMSLOT, RLAST, XLAST, RSTAFRM or XSTAFRM, none of which are enabled in RINTCTL/XINTCTL.  So shouldn’t be the source of the interrupt.

    In the example above, (isr n + 0) and (isr n + 2) are at the 25 Khz sample rate, and (isr n + 1) follows (isr n + 0) by 5 us, and (isr n + 3) follows (isr n + 2) by 5 us.

    Robert

    P.S.  I am doing the conditional checks in the ISR, but of XDATA in XSTAT, and RDATA in RSTAT, instead of XRDY and RRDY in the SRCTL registers for the serializers, like your example.  Is that a flawed method?

  • Robert,

    I think you are simply seeing the AXINT and ARINT interrupts.  The two interrupts will occur at slightly different times since you get a transmit interrupt just before sending data and you get the receive interrupt just after receiving data.  Here's a potential sequence of events that could be responsible:

    1. Transmit interrupt occurs
    2. ISR runs (hardware clears IFR)
    3. Before any register have actually been accessed the receive interrupt occurs (sets IFR again).
    4. Your software sees that both interrupts are ready and services both.
    5. Return from ISR.
    6. Since the receive interrupt is pending (IFR set) you will immediately take the interrupt again even though nothing needs to be done.

    Here are a couple thoughts that come to mind in trying to see this is truly the case:

    • Try disabling either the transmit or receive event (temporarily).  You should no longer get the "double" interrupts assuming that's the reason.
    • Another thing to do would be to LOG_printf the value of IFR to see if there is an interrupt already pending.  In my mind a potential workaround might be to manually/conditionally clear the IFR bit so you don't immediately take another interrupt. (Perhaps in the case where you've serviced both interrupts, if IFR is set then go ahead and clear it?)

    Brad

     

     

  • Brad,

    Good call.  That’s exactly what was happening, i.e. the dual TX, RX interrupt was leaving a hanging IFR, since I serviced both in the same ISR.  The solution was to either clear the IFR, as you indicated, or just service one or the other per ISR … not both.  I went for the latter, preferring not to mess with the IFR.

    The data is still not making it out the TX pin, as far as I can see, even though XRDY is consistently indicating new data can be written (which I do).  Plus the RX data has become a bit whacked now too.  But those are separate issues I’ll address in a different ticket, if stuck after more investigation.

    Thanks,

    Robert

  • Robert56682 said:
    Good call.  That’s exactly what was happening, i.e. the dual TX, RX interrupt was leaving a hanging IFR, since I serviced both in the same ISR.  The solution was to either clear the IFR, as you indicated, or just service one or the other per ISR … not both.  I went for the latter, preferring not to mess with the IFR.

    I think your initial method was ok, i.e. you conditionally service receive and transmit independently in the ISR.  I don't think it's necessary to do anything "special" to handle only one or the other, i.e. it's ok to service both assuming that the corresponding flags are set.  In that scenario servicing the transmitter/receiver will clear the corresponding flag.  When you get the subsequent ISR then I would expect neither flag to be set and so basically you would simply return.

    If you can utilize the FIFOs then I think you'll see greater separation in the interrupt times (not to mention fewer interrupts period).