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.

TMDSDSK6713: EDMA: MCBSP receive event interrupt not clearing

Part Number: TMDSDSK6713

I made a small test program to check the functionality of the EDMA data transfer when the MCBSP triggers a REVT event. I achieved to receive an interrupt when EDMA completes data transfer to the receive buffer. However, this only happens once, after I have received the first frame. The next coming frames do not generate any interrupts unless the DSP is restarted. So my question is why I am receiving ONLY the first interrupt and how can I fix it.

After modifying the code slightly, I have checked that the MCBSP still receives data, as can be seen in MCBSP_rrdy() and MCBSP_read(), but the data cannot be seen in the receive buffer, where the EDMA is expected to copy the data into, before generating the interrupt. So I guess the problem is somehow related to the fact that EDMA is not receiving MCBSP REVT events anymore after the first frame is completed

I attach the sample code below:

#include <csl.h>
#include <csl_mcbsp.h>
#include <csl_edma.h>
#include <csl_dma.h>
#include <csl_irq.h>
#include <stdio.h>

#define BUFFER_SIZE_T 1

static MCBSP_Handle hMcbsp1;           /* handle for McBSP1  */
static EDMA_Handle hEdma15;            /* handle for EDMA 15 */

static volatile int receive_done = FALSE;

static char recv_msg[BUFFER_SIZE_T] = "T";
#pragma DATA_SECTION(recvbuf1,"recv_buf");
unsigned char recvbuf1[0x0400];

/* Include the vector table to call the IRQ ISRs hookup */
extern far void vectors();

/* Prototypes   */
static void ConfigMcBSP(void);
static void ConfigEDMA(void);
static void ProcessReceiveChar(unsigned char *);
static char VoteLogic(unsigned char);
interrupt void c_int08(void);

void main()
{

    int waittime = 0;
    unsigned char* rec_buffer = &recvbuf1[0];

    /* initialize the CSL library */
    CSL_init();

    /* enable NMI and GI */
    IRQ_nmiEnable();
    IRQ_globalEnable();

    /* point to the IRQ vector table */
    IRQ_setVecs(vectors);

    /* disable and clear the event interrupt */
    IRQ_reset(IRQ_EVT_EDMAINT);

    /* clear Parameter RAM of EDMA */
    EDMA_clearPram(0x00000000);

    hEdma15 = EDMA_open(EDMA_CHA_REVT1, EDMA_OPEN_RESET);
    hMcbsp1 = MCBSP_open(MCBSP_DEV1, MCBSP_OPEN_RESET);


    /* Configure the EDMA channels */
    ConfigEDMA();

    IRQ_enable(IRQ_EVT_EDMAINT);

    /* enable EDMA channel interrupt to CPU */
    EDMA_intEnable(EDMA_CHA_REVT1);

    /* Enable EDMA channels */
    EDMA_enableChannel(hEdma15);

    /* Setup for McBSP */
    ConfigMcBSP();

    /* Start Sample Rate Generator: set /GRST = 1 */
    MCBSP_enableSrgr(hMcbsp1);

    /* inserted wait time for McBSP to get ready */
    for (waittime=0; waittime<0xF; waittime++);

    /* Wake up the McBSP as transmitter and receiver */
    MCBSP_enableRcv(hMcbsp1);
    MCBSP_enableXmt(hMcbsp1);

    //printf("Enable Frame Sync Generator for McBSP...\n\n");

    /* Enable Frame Sync Generator for McBSP 1: set /FRST = 1 */
    MCBSP_enableFsync(hMcbsp1);

    printf("Waiting for completion...\n\n");


    /* To flag an interrupt to the CPU when EDMA transfer/receive is done */
    for (;;) {
        /* now wait until the value is received then read it */
        while (!receive_done);
        receive_done = FALSE;
        /* process received data */
        printf("Processing Receive string. . \n");
        ProcessReceiveChar(rec_buffer++);
        printf("String received: %s", recv_msg);
    }

    IRQ_disable(IRQ_EVT_EDMAINT);
    EDMA_RSET(CIER, 0x0);

    MCBSP_close(hMcbsp1);   /* close McBSP 1 */
    EDMA_close(hEdma15);    /* close EDMA 15 */

    for (;;);
}


void ConfigEDMA(void)
{

    EDMA_configArgs(hEdma15,
        EDMA_OPT_RMK(
                    EDMA_OPT_PRI_HIGH,          /* 1  */
                    EDMA_OPT_ESIZE_8BIT,           /* 01 */
                        EDMA_OPT_2DS_NO,        /* 0  */
                        EDMA_OPT_SUM_NONE,      /* 00 */
                        EDMA_OPT_2DD_NO,        /* 0  */
                        EDMA_OPT_DUM_INC,       /* 01 */
                        EDMA_OPT_TCINT_YES,     /* 1  */
                        EDMA_OPT_TCC_OF(15),            /* 15 */
                        EDMA_OPT_LINK_NO,       /* 0  */
                        EDMA_OPT_FS_NO          /* 0  */
                    ),

        /* SRC Setup */
        EDMA_SRC_RMK(MCBSP_getRcvAddr(hMcbsp1)),

        /* CNT Setup */
        EDMA_CNT_RMK(0, (BUFFER_SIZE_T * 10)),

        /* DST Setup */
        EDMA_DST_RMK((Uint32) recvbuf1),        /*recvbuf address*/

        /* IDX Setup */
        EDMA_IDX_RMK(0,0),

        /* RLD Setup */
        EDMA_RLD_RMK(0,0)
    );

} /* End of ConfigEDMA() */


void ConfigMcBSP(void)
{

    MCBSP_Config mcbspCfg1 = {

          MCBSP_SPCR_RMK(
                          MCBSP_SPCR_FREE_YES,            /* 1  */
                          MCBSP_SPCR_SOFT_DEFAULT,        /* 0  */
                          MCBSP_SPCR_FRST_DEFAULT,        /* 0  */
                          MCBSP_SPCR_GRST_DEFAULT,        /* 0  */
                          MCBSP_SPCR_XINTM_XRDY,          /* 00 */
                          MCBSP_SPCR_XSYNCERR_DEFAULT,            /* 0  */
                          MCBSP_SPCR_XRST_DEFAULT,        /* 0  */
                          MCBSP_SPCR_DLB_OFF,         /* 0  */
                          MCBSP_SPCR_RJUST_RZF,           /* 00 */
                          MCBSP_SPCR_CLKSTP_DISABLE,      /* 0  */
                          MCBSP_SPCR_DXENA_OFF,           /* 0  */
                          MCBSP_SPCR_RINTM_RRDY,          /* 00 */
                          MCBSP_SPCR_RSYNCERR_DEFAULT,            /* 0  */
                          MCBSP_SPCR_RRST_DEFAULT         /* 0  */
                      ),

          MCBSP_RCR_RMK(
                      MCBSP_RCR_RPHASE_SINGLE,          /* 1     */
                      MCBSP_RCR_RFRLEN2_DEFAULT,        /* 00010 */
                          MCBSP_RCR_RWDLEN2_DEFAULT,         /* 000   */
                          MCBSP_RCR_RCOMPAND_MSB,         /* 00    */
                          MCBSP_RCR_RFIG_YES,         /* 1     */
                          MCBSP_RCR_RDATDLY_1BIT,         /* 01    */
                          MCBSP_RCR_RFRLEN1_OF(9),        /* 01000 */
                          MCBSP_RCR_RWDLEN1_8BIT,        /* 010   */
                          MCBSP_RCR_RWDREVRS_DISABLE      /* 0     */
                      ),

          MCBSP_XCR_RMK(
                          MCBSP_XCR_XPHASE_SINGLE,          /* 1     */
                          MCBSP_XCR_XFRLEN2_DEFAULT,        /* 00010 */
                      MCBSP_XCR_XWDLEN2_DEFAULT,         /* 000   */
                      MCBSP_XCR_XCOMPAND_MSB,         /* 00    */
                      MCBSP_XCR_XFIG_YES,         /* 1     */
                      MCBSP_XCR_XDATDLY_0BIT,         /* 00    */
                      MCBSP_XCR_XFRLEN1_OF(9),        /* 01000 */       // Start + end + 8 bits (words)
                      MCBSP_XCR_XWDLEN1_8BIT,        /* 010   */
                  MCBSP_XCR_XWDREVRS_DISABLE      /* 0     */
                      ),

        /* SRGR Setup */
        MCBSP_SRGR_RMK(
            MCBSP_SRGR_GSYNC_FREE,              /* 0      */
            MCBSP_SRGR_CLKSP_RISING,            /* 0      */
            MCBSP_SRGR_CLKSM_INTERNAL,          /* 1      */
            MCBSP_SRGR_FSGM_DXR2XSR,            /* 0      */
            MCBSP_SRGR_FPER_DEFAULT,            /* 0      */
            MCBSP_SRGR_FWID_DEFAULT,            /* 0      */
            MCBSP_SRGR_CLKGDV_OF(121)           /* CLKGDV */
        ),

        /* MCR Setup */
        MCBSP_MCR_DEFAULT,                      /* default values */

        MCBSP_RCER_DEFAULT,                     /* default values */
        MCBSP_XCER_DEFAULT,                     /* default values */

        /* PCR Setup */
        MCBSP_PCR_RMK(
            MCBSP_PCR_XIOEN_SP,             /* 0 */
            MCBSP_PCR_RIOEN_SP,             /* 0 */
            MCBSP_PCR_FSXM_INTERNAL,            /* 1 */
            MCBSP_PCR_FSRM_EXTERNAL,            /* 0 */
            MCBSP_PCR_CLKXM_OUTPUT,             /* 1 */
            MCBSP_PCR_CLKRM_OUTPUT,             /* 1 */
            MCBSP_PCR_CLKSSTAT_0,               /* 0 */
            MCBSP_PCR_DXSTAT_0,             /* 0 */
            MCBSP_PCR_FSXP_ACTIVELOW,           /* 1 */
            MCBSP_PCR_FSRP_ACTIVELOW,           /* 1 */
            MCBSP_PCR_CLKXP_RISING,             /* 0 */
        MCBSP_PCR_CLKRP_FALLING             /* 0 */
        )
    };

    MCBSP_config(hMcbsp1, &mcbspCfg1);

}   /* end of Config_McBSP(void) */

void ProcessReceiveChar(unsigned char * recvbuffer)
{
    int i;
    unsigned char recv_char = 0;
    short cnt = -1;
    short recv_val;
    unsigned char  raw_data;
    unsigned char  *recvbufptr;    /*receive buffer pointer*/

    /* Point to the receive buffer  */
    recvbufptr  = recvbuffer;

    /* Process all data in the Receive buffer   */
    for (i = 0; i < BUFFER_SIZE_T; i++)
    {

        printf("PROCESSING CHAR %d: ", i);

        recv_char = 0;

        /* Process each UART frame  */
        for (cnt = -1; cnt < 9; cnt++)
        {

            printf("%X, ", *recvbufptr);

            if(cnt == -1 || cnt == 8)
            {
                /* Ignore Start and Stop bits   */
                *recvbufptr++;
            }
            else
            {
                /* Get 8-bit data from receive buffer  */
                raw_data    =   *recvbufptr;
                recvbufptr++;

                /* get the value of the majority of the bits    */
                recv_val    =   VoteLogic(raw_data);

                /* put received bit into proper place   */
                recv_char   += recv_val << cnt;
            }
        }   /* end for cnt  */

        /* A full BYTE is decoded. Put in result: recv_msg[i]   */
        recv_msg[i] =   recv_char;

    }   /* end for i    */

    printf("\n");

}   /* end ProcessReceiveData() function    */


char VoteLogic(unsigned char value)
{
    short returnvalue;

    switch  ((value >>  2)  & 0x0F)
    {
        case    0:
        case    1:
        case    2:
        case    3:
        case    4:
        case    5:
        case    6:
        case    8:
        case    9:
        case    10:
                        returnvalue = 0;
                        break;
        case    7:
        case    11:
        case    12:
        case    13:
        case    14:
        case    15:
                        returnvalue = 1 ;
                        break;
    }   /* end switch   */

    return (returnvalue);

}   /* end VoteLogic() funciton */


interrupt void c_int08(void)
{
    volatile Uint8 *ledReg;
    volatile Uint8 ledStatus;

    if (EDMA_intTest(15))
    {
        EDMA_intClear(15);
        receive_done = TRUE;
        printf("Receive Completed\n\n");

        ledReg = (volatile Uint8 *) 0x90080000;

        ledStatus = *(ledReg);
        ledStatus &= 0xF0; // turn off all LEDs
        ledStatus |= (0x0F); // turn on LEDs
        *ledReg = ledStatus;
    }
}



  • Hi,

    I saw you asked a similar question in this thread. I would similarly recommend you not to do "printf" in ISR, because printf is slow and it can cause ISR not to finish before next interrupt comes. As a result, subsequent interrupts will not be serviced. Instead, you could increment a counter or toggle a flag inside ISR for debugging. 

    Keep in mind that your code runs on the DSP and anything related to I/O (printf, fprintf, etc.) will have to go to the host PC through the JTAG, which is a slow process.

    Regards,

    Jianzhong

  • Hi ,

    Just tried commenting out every printf statement, but still the same problem. I can only receive the first interrupt. Any other solution?

    Thanks,

    Aner

  • Hi Aner,

    I would recommend you to debug the problem in two steps:

    1. do not use EDMA. Make sure MCBSP REVT event is generated reliably and repeatedly.

    2. after you verify #1, add EDMA. Start EDMA transfer when you receive MCBSP REVT event and generate interrupt after transfer is done.

    See which one still has problems.

    Regards,

    Jianzhong