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: MCBSP as UART: Problems with printf

Part Number: TMDSDSK6713

I am trying to use the example code from SPRA633. My working set consists of:

  • DSK6713 evaluation board
  • Code Composer Studio V10. With the .default DSK6713 gel file, supposed to run the DSP at 225 MHz)
  • Blackhawk USB560v2 emulator
  • Code example from SPRA633
  • MCBSP transmitting/receiving UART at 115200 baud rate. (with 225 MHz CPU frequency, the sample rate generator divider should be CLKGDV=225*10^6 / (16*115200) - 1 = 122

I have modified the code example slightly to use the MCBSP loopback mode. In order to have the transmitted data into the received data buffer. My problem is that, depending on the printf statements I use, the c_int08 interrupt is called or not. The c_int08 interrupt is supposed to be called by the EDMA peripheral when a transmission is completed (with code 14) and when a reception is completed (with code 15). The code 14 is properly working, but the code 15 only works after I comment some of the printf statements (the printf("Enable Frame Sync Generator for McBSP...\n\n"); statement precisely). Since the code 15 doesn't work sometimes, the code gets stuck in the while loop, waiting for the receive_done flag.

In addition, when the receive buffer is filled with some data, the console in the debugger prints some strange chars, like it was a corrupted printf.

As an additional question, how can multiple UART frames be transmitted via EDMA? I mean, what does the EDMA make to transmit data to the MCBSP after the XMIT BUFFER has been written?

Anyone can explain the cause of these two situations?

I attach the source code of the project here, note the modified statements:

main.c

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

/* Create buffers and aligning them on an L2 cache line boundary. */
#pragma DATA_SECTION(xmitbuf,"xmit_buf");
unsigned short xmitbuf[0x0400];

#pragma DATA_SECTION(recvbuf,"recv_buf");
unsigned short recvbuf[0x0400];

/* Definitions  */
#define BUFFER_SIZE 27              /* total number of UART data words  */
#define TRUE 1
#define FALSE 0

/* Declare CSL objects */
MCBSP_Handle hMcbsp1;           /* handle for McBSP1  */
EDMA_Handle hEdma14;            /* handle for EDMA 14 */
EDMA_Handle hEdma15;            /* handle for EDMA 15 */

/* Global Variables */
volatile int receive_done = FALSE;
volatile int transmit_done = FALSE;
char xmit_msg[BUFFER_SIZE] = "McBSP does UART on C6000!\n";
char recv_msg[BUFFER_SIZE] = "Transmission didn't work!\n";

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

/* Prototypes   */
void ConfigMcBSP(void);
void ConfigEDMA(void);
void ProcessTransmitData(void);
void ProcessReceiveData(void);
short VoteLogic(unsigned short);
int CheckTestCase(void);
interrupt void c_int11(void);
interrupt void c_int09(void);
interrupt void c_int08(void);


/*******************************************************************/
/* void main(void)                                                 */
/*******************************************************************/
void main(void)
{

    int waittime = 0;
    int works = FALSE;

    /* 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);

    /* process transmit data */
    printf("Processing Transmit string...\n");
    ProcessTransmitData();
    printf("String transmitted: %s \n", xmit_msg);

    /* Open the EDMA channels - EDMA 14 for transmit, EDMA 15 for receive   */
    hEdma14 = EDMA_open(EDMA_CHA_XEVT1, EDMA_OPEN_RESET);
    hEdma15 = EDMA_open(EDMA_CHA_REVT1, EDMA_OPEN_RESET);

    /* Open the McBSP channel 1 */
    hMcbsp1 = MCBSP_open(MCBSP_DEV1, MCBSP_OPEN_RESET);

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

    /* enable EDMA-CPU interrupt tied to McBSP */
    IRQ_enable(IRQ_EVT_EDMAINT);

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

    /* Enable EDMA channels */
    EDMA_enableChannel(hEdma14);
    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 */
    while (!receive_done || !transmit_done);

    /* Check to make sure the test case works */
    works = CheckTestCase();
    if (works != 0) printf("Transmission Error....\n\n");
    else printf("Received data matched transmitted data!\n\n");

    /* process received data */
    printf("Processing Receive string...\n");
    ProcessReceiveData();
    printf("String received: %s \n", recv_msg);

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

    MCBSP_close(hMcbsp1);   /* close McBSP 1 */

    EDMA_close(hEdma14);    /* close EDMA 14 */
    EDMA_close(hEdma15);    /* close EDMA 15 */
}   /* End of main() */


/*******************************************************************/
/* void ConfigEDMA(void): set up EDMA channel 14/15 for UART Xmit  */
/*******************************************************************/
void ConfigEDMA(void)
{
    EDMA_configArgs(hEdma14,
        EDMA_OPT_RMK(
                    EDMA_OPT_PRI_HIGH,      /* 1  */
                    EDMA_OPT_ESIZE_16BIT,           /* 01 */
                        EDMA_OPT_2DS_NO,        /* 0  */
                        EDMA_OPT_SUM_INC,       /* 01 */
                        EDMA_OPT_2DD_NO,        /* 0  */
                        EDMA_OPT_DUM_NONE,      /* 00 */
                        EDMA_OPT_TCINT_YES,     /* 1  */
                        EDMA_OPT_TCC_OF(14),            /* 14 */
                        EDMA_OPT_LINK_NO,       /* 0  */
                        EDMA_OPT_FS_NO          /* 0  */
                    ),

        /* SRC Setup */
        EDMA_SRC_RMK((Uint32) xmitbuf),        /*xmitbuf address*/

        /* CNT Setup */
        EDMA_CNT_RMK(
            EDMA_CNT_FRMCNT_DEFAULT,
            EDMA_CNT_ELECNT_OF(BUFFER_SIZE*11)
        ),

        /* DST Setup */
        EDMA_DST_RMK(MCBSP_getXmtAddr(hMcbsp1)),

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

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

    EDMA_configArgs(hEdma15,
        EDMA_OPT_RMK(
                    EDMA_OPT_PRI_HIGH,          /* 1  */
                    EDMA_OPT_ESIZE_16BIT,           /* 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 * 11)),

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

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

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

} /* End of ConfigEDMA() */


/*******************************************************************/
/* void ConfigMcBSP(void): Setup for McBSP Configuration           */
/*******************************************************************/
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_ON,         /* 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_DUAL,          /* 1     */
                      MCBSP_RCR_RFRLEN2_OF(1),        /* 00010 */
                          MCBSP_RCR_RWDLEN2_8BIT,         /* 000   */
                          MCBSP_RCR_RCOMPAND_MSB,         /* 00    */
                          MCBSP_RCR_RFIG_YES,         /* 1     */
                          MCBSP_RCR_RDATDLY_1BIT,         /* 01    */
                          MCBSP_RCR_RFRLEN1_OF(8),        /* 01000 */
                          MCBSP_RCR_RWDLEN1_16BIT,        /* 010   */
                          MCBSP_RCR_RWDREVRS_DISABLE      /* 0     */
                      ),

          MCBSP_XCR_RMK(
                          MCBSP_XCR_XPHASE_DUAL,          /* 1     */
                          MCBSP_XCR_XFRLEN2_OF(1),        /* 00010 */
                      MCBSP_XCR_XWDLEN2_8BIT,         /* 000   */
                      MCBSP_XCR_XCOMPAND_MSB,         /* 00    */
                      MCBSP_XCR_XFIG_YES,         /* 1     */
                      MCBSP_XCR_XDATDLY_0BIT,         /* 00    */
                      MCBSP_XCR_XFRLEN1_OF(8),        /* 01000 */
                      MCBSP_XCR_XWDLEN1_16BIT,        /* 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(122)           /* 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 ProcessTransmitData(void)                                  */
/*                                                                 */
/* This function expands each of the 8-bit ASCII characters in the */
/* transmit string "xmit_msg" into UART transmission 16-bit word   */
/* and place them in the transmit buffer "xmitbuf".  In addition,  */
/* 16-bit Start and 8-bit Stop framing words, respectively, are    */
/* inserted before and after each of the ASCII characters in the   */
/* buffer.                                                         */
/*******************************************************************/
void ProcessTransmitData(void)
{
    int     i;
    short   cnt = 1;
    unsigned char   xmit_char;
    unsigned short  *xmitbufptr;

    /* point to Transmit Buffer */
    xmitbufptr = (unsigned short *)xmitbuf;

    for (i=0; i<(sizeof(xmitbuf)/sizeof(unsigned int)); i++)
    {
        xmitbufptr[i] = 0x0000; /* zero fill buffer */
    }

    xmitbufptr = (unsigned short *)xmitbuf;

    /* Process data BYTES in xmit_msg[] and put in xmit buffer  */
    for (i = 0; i < BUFFER_SIZE; i++)
    {
        /*Get transmit character (one byte) from xmit_msg[] and put in xmit buffer*/
        xmit_char   =   xmit_msg[i];

        /* Process each BYTE of transmit character  */
        for (cnt = -1; cnt < 10; cnt++)
        {
            if (cnt == -1)
                *xmitbufptr++   =   0x0000;

            else if (cnt == 8 || cnt ==9)
                *xmitbufptr++   =   0xFFFF;

            else if (xmit_char & (1 << cnt))
                *xmitbufptr++   =   0xFFFF;

            else
                *xmitbufptr++   =   0x0000;

        }   /* end for cnt  */

    }   /* end for i    */

}   /* end ProcessTransmitData  */


/*******************************************************************/
/* void ProcessReceiveData(void)                                   */
/*                                                                 */
/* This function decodes the data in the receive buffer, "recvbuf" */
/* and strips the framing start (0x0000) and Stop (0xFFFF) words.  */
/* It calls the subroutine VoteLogic() to determine each bit of    */
/* the ASCII character.  It then puts the result in recv_msg.      */
/*******************************************************************/
void ProcessReceiveData(void)
{
    int i;
    unsigned char recv_char = 0;
    short cnt = -1;
    short recv_val;
    unsigned short  raw_data;
    unsigned short  *recvbufptr;    /*receive buffer pointer*/

    /* Point to the receive buffer  */
    recvbufptr  = (unsigned short *)recvbuf;

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

        /* Process each UART frame  */
        for (cnt = -1; cnt < 10; cnt++)
        {
            if(cnt == -1 || cnt == 8 || cnt == 9)
            {
                /* Ignore Start and Stop bits   */
                *recvbufptr++;
            }
            else
            {
                /* Get 16-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    */

}   /* end ProcessReceiveData() function    */


/*******************************************************************/
/* void CheckTestCase(void)                                        */
/*******************************************************************/
int CheckTestCase(void)
{
    unsigned short *source;
    unsigned short *result;
    unsigned int i = 0;
    short cnt = -1;
    int error = 0;

    source = (unsigned short *) xmitbuf;
    result = (unsigned short *) recvbuf;

    for (i = 0; i < BUFFER_SIZE ; i++)
    {
        for (cnt = -1; cnt < 10; cnt++)
        {
            /* Ignore the start and stop bits */
            if(cnt == -1 || cnt == 8 || cnt ==9)
            {
                source++;
                result++;
            }
            else
            {
                if (*source != *result)
                {
                    error = i + 1;
                    break;
                }
                source++;
                result++;
            }
        }
    }

    return(error);

}   /* end CheckTestCase() function */


/*******************************************************************/
/* short VoteLogic(unsigned short)                                 */
/*                                                                 */
/* This function decoded the received character by testing the     */
/* center 4 bits of the baud.  A majority rule is used for the     */
/* decoding.                                                       */
/*******************************************************************/
short VoteLogic(unsigned short value)
{
    short returnvalue;

    switch  ((value >>  6)  & 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 */


/*******************************************************************/
/* EDMA Data Transfer Completion ISRs                              */
/*******************************************************************/


interrupt void c_int08(void)
{
    #if (EDMA_SUPPORT)
        if (EDMA_intTest(14))
        {
            EDMA_intClear(14);
            transmit_done = TRUE;
            printf("Transmit Completed\n");
        }

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

vecs.asm

 .global _vectors
  .global _vector0
  .global _vector1
  .global _vector2
  .global _vector3
  .global _vector4
  .global _vector5
  .global _vector6
  .global _vector7
  .global _c_int08 ; Hookup the c_int08 ISR in main() for EDMA
  .global _c_int09 ; Hookup the c_int09 ISR in main() for DMA
  .global _vector10
  .global _c_int11 ; Hookup the c_int09 ISR in main() for DMA
  .global _vector12
  .global _vector13
  .global _vector14
  .global _vector15

; ************************************************************************ 
; Global symbols referenced in this file but defined somewhere else.
; Remember that your interrupt service routines need to be referenced here.
; ************************************************************************ 

  .ref _c_int00

; ************************************************************************ 
; This is a mcros that instantiates one entry in the inetrrupt service table.
; ************************************************************************ 

VEC_ENTRY .macro addr
  STW 	B0,*--B15
  MVKL 	addr,B0
  MVKH 	addr,B0
  B 	B0
  LDW 	*B15++,B0
  NOP 	2
  NOP
  NOP
  .endm
  
; ************************************************************************ 
; This is a dummy interrupt service routine used to initialize the IST.
; ************************************************************************ 

_vec_dummy:
  B 	B3
  NOP 	5
  
; ************************************************************************ 
; This is the actual interrupt service table (IST). It is properly aligned and
; is located in the subsection .text:vecs. This means if you don’t explicitly
; specify this section in your linker command file, it will default and link 
; into the .text section. Remember to set the ISTP register to point to this 
; table. 
; ************************************************************************ 

  .sect ".text:vecs"
  .align 1024
  
_vectors:
_vector0: VEC_ENTRY _vec_dummy
_vector1: VEC_ENTRY _vec_dummy
_vector2: VEC_ENTRY _vec_dummy
_vector3: VEC_ENTRY _vec_dummy
_vector4: VEC_ENTRY _vec_dummy
_vector5: VEC_ENTRY _vec_dummy
_vector6: VEC_ENTRY _vec_dummy
_vector7: VEC_ENTRY _vec_dummy
_vector8: VEC_ENTRY _c_int08 ; Hookup the c_int08 ISR in main() for EDMA
_vector9: VEC_ENTRY _vec_dummy
_vector10: VEC_ENTRY _vec_dummy
_vector11: VEC_ENTRY _vec_dummy
_vector12: VEC_ENTRY _vec_dummy
_vector13: VEC_ENTRY _vec_dummy
_vector14: VEC_ENTRY _vec_dummy
_vector15: VEC_ENTRY _vec_dummy

; ************************************************************************ 
; *******************************End of vecs.asm**************************
; ************************************************************************ 

linker.cmd

MEMORY
{
    VECS:   o = 00000000h       l = 00400h /* reset & interrupt vectors     */
    PMEM:   o = 00000400h       l = 0FC00h /* intended for initialization   */
    BMEM:   o = 80000000h       l = 10000h /* .bss, .sysmem, .stack, .cinit */
}

SECTIONS
{
    vectors     >       VECS
    .text       >       PMEM
    .switch     >       PMEM
    "xmit_buf"  >       BMEM
    "recv_buf"  >       BMEM
    .tables     >       BMEM
    .data       >       BMEM
    .stack      >       BMEM
    .bss        >       BMEM
    .sysmem     >       BMEM
    .cinit      >       BMEM
    .const      >       BMEM
    .cio        >       BMEM
    .far        >       BMEM
}

uart_edma_test.zip

  • Aner,

    As you can see, the document is a fairly old application note (last published in 2000). We no longer have access to the experts that authored the application note so we will only be able to offer limited support for this issue. We can also see if any DSP community member can provide inputs on this setup. 

    When running real time critical code, we don`t recommend use of printf so I would try to avoid using that you can either step through the code or setup a buffer to log values as you run through portions of the code. This device doesn`t have a FIFO on the MCBSP so you need to set the EDMA to trigger when MCBSP XMIT Buffer is empty and write a driver to hold the input of frames and send it to XMIT BUFFER one at a time.

    Regards,

    Rahul