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.

UART interrupts McASP

System used: LCDKC6748.

SYS/BIOS used. UART Interrupt service routine (ISR) is linked to CPU interrupt #5 (hence, more prior). The McASP ISR called by CPU interrupt #7 (less prior). Their Masking option set is MaskingOption_ALL.

I want to receive a stream of bytes on UART at 115200 baud rate when McASP ISR is halted (McASP is getting stereo audio data with sampling frequency of 48000).

Upon running the code, when UART is finished receiving bytes, McASP Transmitter underrun and receiver overrun bits are set (In XSTAT and RSTAT registers). The only way to combat TX underrun is to restart the McASP module ( according to technical reference manual of C674x).

Is there anything I can do to avoid McASP going into TX under run and RX-over run? so the program goes back to McASP in.out after UART ISR is finished?

  • Dear Sherry,
    Which example are you using ?
    You can also refer PSP drivers which is using BIOS.
    C:\ti\pspdrivers_01_30_00_06\packages\ti\pspiom\examples\evmOMAPL138\uart
  • Hi,

    I have suggestions for you are below and kindly valdate the same:

    1. Start the Rx. & Tx. clocks after enabling error interrupts for McASP like

    /* Enable error interrupts for McASP */

    McASPTxIntEnable(SOC_MCASP_0_CTRL_REGS, MCASP_TX_DATAREADY  

                                            | MCASP_TX_CLKFAIL

                                            | MCASP_TX_SYNCERROR

                                            | MCASP_TX_UNDERRUN);

    McASPRxIntEnable(SOC_MCASP_0_CTRL_REGS, MCASP_RX_DATAREADY  

                                            | MCASP_RX_CLKFAIL

                                            | MCASP_RX_SYNCERROR

                                            | MCASP_RX_OVERRUN);

    /* Start the clocks */

       McASPRxClkStart(SOC_MCASP_0_CTRL_REGS, MCASP_RX_CLK_EXTERNAL);

       McASPTxClkStart(SOC_MCASP_0_CTRL_REGS, MCASP_TX_CLK_EXTERNAL);

    2. Please ensure codec ISR mapping to CPU mask interrupt C674X_MASK_INTx should be done before configuring the AIC31 codec for I2S mode:

        IntRegister(C674X_MASK_INTx, Codec_ISR);

        IntEventMap(C674X_MASK_INTx, SYS_INT_MCASP0_INT);

        IntEnable(C674X_MASK_INTx);

    3.  In the McASPI2SConfigure(void) function code, activate the state machines after making sure that the XDATA bit is cleared to zero like below:

    /* make sure that the XDATA bit is cleared to zero */

    Kindly ensure to get INTx in the Interrupt vector table (i.e control is transferred to ISR - Codec_ISR() ).

    while(McASPTxStatusGet(SOC_MCASP_0_CTRL_REGS) & MCASP_TX_STAT_DATAREADY);

    /* Activate the state machines */

    McASPRxEnable(SOC_MCASP_0_CTRL_REGS);

    McASPTxEnable(SOC_MCASP_0_CTRL_REGS);

    4. I think, to enable Tx. and Rx. McASP interrupts, kindly ensure to configure McASP error interrupts through  McASPTxIntEnable() & McASPRxIntEnable () which would trigger error interrupts if any.

    mcasp->rintctl    = 0x00000001;  // overrun interrupt only

    mcasp->xintctl    = 0x00000020;  // data interrupts

    Kindly validate the above configuration and try it.

    For more details to configure the transmitter and receiver interrupt control registers (XINTCTL & RINTCTL), kindly refer sections 23.3.20 & 23.3.32 in the C6748TRM below:

    http://www.ti.com/lit/ug/spruh79a/spruh79a.pdf

    Thanks & regards,

    Sivaraj K

    -------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question

    -------------------------------------------------------------------------------------------------------

  • Hi Sherry,

    Sherry said:
    Upon running the code, when UART is finished receiving bytes, McASP Transmitter underrun and receiver overrun bits are set (In XSTAT and RSTAT registers). The only way to combat TX underrun is to restart the McASP module ( according to technical reference manual of C674x).

    Is there anything I can do to avoid McASP going into TX under run and RX-over run? so the program goes back to McASP in.out after UART ISR is finished?

    For McASP, which I2C module is used? I2C0 or I2C1? If  you are using I2C1 and UART2, check there is no pinmux conflict when you use UART2_RXD with I2C1_SCL. The codec of McASP is configured through I2C bus..

    When I looked into the starterware code, "MCASP play back example" , I2C0 is used.

    Would you please try out the McASP playback example of starterware, modify and try to reproduce this problem???

    Starterware download link:

  • I have used I2C0 for the on-board codec. I did not use EDMA, Instead I use simple ping-pong buffering for a stereo channel, as demonstrated in C6000 Embedded design workshop videos. The starterware example is wayy too obfuscated for my humble understanding. Please see my code attached. The only PINMUX conflict was between UART2 and AMUTE pin of MCASP. I am not using RTS CTS of UART2.

    audio_C6000_buffer_LR_download.rar

    Please see the ISR of UART

    void UART_ISR(void) {
    	//Log_info0("UART_ISR");
    	uart2->IER = 0;		// disable I2S interrupt temporarily
    	i = UART2Read();
    	UART2RInt(0);
    	switch (i) {
    	case 0x02:
    		downloadFilter();	//branch out to another function
    		break;
    	case 'E':
    		UART2Write(0x45);	//Echo back E
    		break;
    	default:
    		UART2Write(0xAE);	//if anything else sent, send back AE
    		break;
    	}
    	UART2RInt(1);	//enable RX int
    }

    The code works fine when i send 'E' (i.e. byte 0x45) or anything. but as soon as a byte 0x02 is sent and subsequent code is executed, McASP goes into under-run error .

    inline void downloadFilter() {
    	/* Mute the codec by writing on codec register number 7. 
    	 * Receive bytes to make 16 bit words.
    	 */
    	AIC3106_writeRegister(7, (0 << 7) |// fs(ref) = 48kHz (needed only for AGC time constants, not used)
    					(0 << 6) |	// ADC dual rate mode is disabled
    					(0 << 5) |	// DAC dual rate mode is disabled
    					(0 << 3) |	// left DAC datapath plays left channel input data
    					(0 << 1) |	// right DAC datapath plays right channel input data
    					(0 << 0));	// reserved
    	uint8_t rxByte[4];
    	rxByte[1] = UART2Read();
    	rxByte[0] = UART2Read();
    	loopSize = ((uint16_t) rxByte[1] << 8) | rxByte[0];	//number of filter coefficients
    	rxByte[1] = UART2Read();
    	rxByte[0] = UART2Read();
    	wordSize = ((uint16_t) rxByte[1] << 8) | rxByte[0];	//32 bit/24 bit/16 bit
    	Log_info2("xstat:[%x] ,rstat:[%x]", mcaspRegs->XSTAT,mcaspRegs->RSTAT);
    
    }

  • Hi Sivaraj,
    In step 1, you are enabling all clock error interrupts but in step 4, XINTCTL and RINTCTL only have data interrupts enabled. How would they work together?
    I have followed your guidelines and also sections of 23.3.x in Technical reference manual. The McASP works fine if there is no other interrupt on the horizon.
    In my code, (please please see the .rar project I attached) The mcasp comes back from UART interrupt if the ISR sequence is very short, but if it is long, the MCASP module misses the sampled data and goes into underrun/over run state, how can I download a long stream of bytes (4096 bytes at 115200 baudrate) ? Meanwhile, the MCASP should ignore the incoming audio sample data and put outgoing data to be zero (or mute the codec). Once UART's ISR is finished, then McASP and codec can go back to execution.

    This is a BIOS system. UART interrupt is mapped to CPU interrupt with higher priority than MCASP interrupt service routine... but McASP somehow needs to PAUSE or be restarted while UART is working. I hope i rephrased my problem more specifically :-)
  • Hi,

    You could enable either tx. underrun interrupt as well rx. overrun interrupts in XINTCTL & RINTCTL respectively which is not a big deal.

    Usually, underrun would occur if the memory latency time exceeds the actual time to transmit Tx. data over the McASP port which indicates system doesn't meet real time requirement for underrun/overrun cause. I guess, due to the UART ISR long sequence, even the mcasp comes back from UART interrupt, it would have faced the latency time limitation while transmit mcasp tx. data which causes underrun. Kindly comply to the real time requirements to get rid of underrun/overrun.

    A buffer underrun would occur only when the serializer was instructed by the transmit state machine to transfer data from XRBUF[n] to XRSR[n], but XRBUF[n] has not yet been written with new data since the last time the transfer occurred. When this occurs, the transmit state machine sets the XUNDRN flag.

    Kindly ensure the above limitation on underrun/overrun conditions, sothat, you would be probably not required for the mcasp to pause or restart while UART is working.

    Thanks & regards,

    Sivaraj K

    -------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question

    -------------------------------------------------------------------------------------------------------

  • Sivaraj,
    It is still not working. I have used your guidelines as follows:

    1. TX/RX state machines of MCASP are paused and serialisers are cleared before the long ISR of UART starts.

    2. State machines and Serialisers are resumed after UART is serviced.

    Please see the UART_ISR below

    void UART_ISR(void) {
    	//Log_info0("UART_ISR");
    	uart2->IER = 0;		// disable interrupt temporarily
    	i = UART2Read();
    	UART2RInt(0);	//Disable RX interrupts
    	switch (i) {
    //http://www.utf8-chartable.de/
    	case 0x02:
    		downloadFilter();      //Branch out -> problem here
    		break;
    	case 'E':
    		UART2Write(0x45);	//echo back 'E'
    		break;
    	default:
    		UART2Write(0xAE);       //echo back byte 0xAE
    		break;
    	}
    	UART2RInt(1);	//enable RX interrupt
    }

    The 'downloadFilter' function works like this:

    inline void downloadFilter() {
    	McASP_hold();     //Put MCASP state machine in reset state and clear the serialiser
    	uint8_t rxByte[4];
    	rxByte[1] = UART2Read();
    	rxByte[0] = UART2Read();
    	loopSize = ((uint16_t) rxByte[1] << 8) | rxByte[0];	//combine the bytes to make 16 bit word
    	McASP_resume();
    }

    The McASP_hold and McASP resume toggle the Global Control register of MCASP module. The bits are toggled are for RX/TX state machines and serialisers.
    Please see the code here:

    void McASP_hold(void) {
    	mcaspRegs->XSTAT = 0x0000FFFF;
    	mcaspRegs->RSTAT = 0x0000FFFF;
    	//		while ((mcaspRegs->RSTAT & 0x0000FFFF) != 0);
    	CSL_FINS(mcaspRegs->GBLCTL, MCASP_GBLCTL_XSRCLR, 0);
    	while (CSL_FEXT(mcaspRegs->GBLCTL, MCASP_GBLCTL_XSRCLR)
    			!= CSL_MCASP_GBLCTL_XSRCLR_ACTIVE)
    		;
    	CSL_FINS(mcaspRegs->GBLCTL, MCASP_GBLCTL_RSRCLR, 0);
    	while (CSL_FEXT(mcaspRegs->GBLCTL, MCASP_GBLCTL_RSRCLR)
    			!= CSL_MCASP_GBLCTL_RSRCLR_ACTIVE)
    		;
    	//only for polling
    		mcaspRegs->XBUF13 =0;
    	//Verify that all TX buffers are serviced, wait for XDATA to clear
    	CSL_FINS(mcaspRegs->GBLCTL, MCASP_GBLCTL_XSMRST, 0);
    	while (CSL_FEXT(mcaspRegs->GBLCTL, MCASP_GBLCTL_XSMRST)
    			!= CSL_MCASP_GBLCTL_XSMRST_ACTIVE)
    		;
    	CSL_FINS(mcaspRegs->GBLCTL, MCASP_GBLCTL_RSMRST, 0);
    	while (CSL_FEXT(mcaspRegs->GBLCTL, MCASP_GBLCTL_RSMRST)
    			!= CSL_MCASP_GBLCTL_RSMRST_ACTIVE)
    		;
    }
    void McASP_resume(void) {
    	CSL_FINS(mcaspRegs->GBLCTL, MCASP_GBLCTL_XSRCLR, 1);
    	while (CSL_FEXT(mcaspRegs->GBLCTL, MCASP_GBLCTL_XSRCLR)
    			!= CSL_MCASP_GBLCTL_XSRCLR_ACTIVE)
    		;
    	CSL_FINS(mcaspRegs->GBLCTL, MCASP_GBLCTL_RSRCLR, 1);
    	while (CSL_FEXT(mcaspRegs->GBLCTL, MCASP_GBLCTL_RSRCLR)
    			!= CSL_MCASP_GBLCTL_RSRCLR_ACTIVE)
    		;
    	//only for polling
    		mcaspRegs->XBUF13 =0;
    	//Verify that all TX buffers are serviced, wait for XDATA to clear
    	CSL_FINS(mcaspRegs->GBLCTL, MCASP_GBLCTL_XSMRST, 1);
    	while (CSL_FEXT(mcaspRegs->GBLCTL, MCASP_GBLCTL_XSMRST)
    			!= CSL_MCASP_GBLCTL_XSMRST_ACTIVE)
    		;
    	CSL_FINS(mcaspRegs->GBLCTL, MCASP_GBLCTL_RSMRST, 1);
    	while (CSL_FEXT(mcaspRegs->GBLCTL, MCASP_GBLCTL_RSMRST)
    			!= CSL_MCASP_GBLCTL_RSMRST_ACTIVE)
    		;
    
    }

    It has no Underrun run if ISR branch is short (e.g. transmitting any character that simply echoes back, but when '02 55 66' is sent to TI-DSP56321 board, it goes into downloadFilter() execution, and it puts the bytes correctly into the 'loopSize' variable. But the McASP goes into TX/RX error.  

  • Sivaraj and Shankari

    Thank you for your help. I realised my mistake now. In McASP_hold() code above, I am holding McASP module in reset but my while() condition for checking GBLCTL register bits were incorrect. After writing '0' to GBLCTL register bits, my while() condition is still for waiting for '1'... I copied the code across from McASP_start() mindlessly.

    Sivaraj, thank you for directing me to specific registers of McASP.

    The correct code for McASP_hold is below. My McASP_resume() and UART's ISR works fine

    void McASP_hold(void) {
    	mcaspRegs->XSTAT = 0x0000FFFF;
    	mcaspRegs->RSTAT = 0x0000FFFF;
    	// clear serialisers
    	CSL_FINS(mcaspRegs->GBLCTL, MCASP_GBLCTL_XSRCLR, 0);
    	while (CSL_FEXT(mcaspRegs->GBLCTL, MCASP_GBLCTL_XSRCLR)
    			!= CSL_MCASP_GBLCTL_XSRCLR_CLEAR)
    		;
    	CSL_FINS(mcaspRegs->GBLCTL, MCASP_GBLCTL_RSRCLR, 0);
    	while (CSL_FEXT(mcaspRegs->GBLCTL, MCASP_GBLCTL_RSRCLR)
    			!= CSL_MCASP_GBLCTL_RSRCLR_CLEAR)
    		;
    	//probably dont need to write to XBUF13.
    	mcaspRegs->XBUF13 = 0;
    	//Hold state machines in reset
    	CSL_FINS(mcaspRegs->GBLCTL, MCASP_GBLCTL_XSMRST, 0);
    	while (CSL_FEXT(mcaspRegs->GBLCTL, MCASP_GBLCTL_XSMRST)
    			!= CSL_MCASP_GBLCTL_XSMRST_RESET)
    		;
    	CSL_FINS(mcaspRegs->GBLCTL, MCASP_GBLCTL_RSMRST, 0);
    	while (CSL_FEXT(mcaspRegs->GBLCTL, MCASP_GBLCTL_RSMRST)
    			!= CSL_MCASP_GBLCTL_RSMRST_RESET)
    		;
    }

  • Hi,

    Glad to hear that works!

    Thanks for your update.

    Hereby, closing your post.

    Regards,

    Sivaraj K