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 }