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 Interrupt Firing

We're using the 6670 and are having an intermittent issue w/ the UART interrupt firing.

In my code I was only clearing the cic interrupt (CSL_INTC0_UARTINT) when reading of the IIR Register says there is an interrupt pending (bit 0 = 1).  So we've been able to figure out that the UART cic interrupt is firing, when IIR says there are not any pending UART interrupts.  I've worked around that by clearing the cic interrupt if it is set, however we were wondering what could cause the CSL_INTC0_UARTINT cic interrupt to fire if IIR says there are no pending interrupts?

Any insight as to why this could be happening would be greatly appreciated.

Erick

  • Erick,

    There might be some new UART interrupts happen when you are inside of the ISR to service the interrupt.

    Please check if your ISR is similar as the following example:

    void USER_DEFINED_ISR (Uint32 eventId)
    {

    /* Disable the CIC0 host interrupt output */
    CSL_CPINTC_disableHostInterrupt(cphnd, host_event);

    /* Clear the CIC0 system interrupt */
    CSL_CPINTC_clearSysInterrupt(cphnd, sys_event);
    (Add dummy read of the System Interrupt Status Indexed Clear Register)

    /* Service the interrupt at source */
    ......
    (clear and read back the source interrupt flag is typically the first step in the service)

    /* Clear the CorePac interrupt */
    CSL_intcHwControl(hIntcEvent[Event IDX],CSL_INTC_CMD_EVTCLEAR,NULL);

    /* Enable the CIC0 host interrupt output */
    CSL_CPINTC_enableHostInterrupt(cphnd, host_event);

    }

    Adding CIC host output disable/enable in the ISR is intended to capture the new event happens during the ISR.

    And you can read back some CIC configuration registers (such as System Interrupt Status Indexed Clear Register) after clearing the CIC interrupt to make sure the clearing is indeed completes. 

    In the stage of "Service the interrupt at source", you may need to clear some bits or complete some actions in the source IP (e.g. UART) in order to clear the interrupt.

    The interrupt clearing information is mentioned in the "Table 3-6 Interrupt Identification and Interrupt Clearing Information" of UART user guide. Please take a look to see you the corresponding actions are completed.

    If you still see any issue, please attach one example project which could reproduce the issue. Then we could take a look at it further. Thanks.

  • Hi Steven,

    We previously did not have the structure of disabling/enabling correctly handled (not sure why since we had it right in all our other interrupts), however once we corrected this issue, we are still running into it. 

    The Interrupt still happens when the UART says there are no interrupts pending.

    Here's a snippet of what I am doing

    #ifdef UART_USE_EDMA
    static inline bool_t	_ti_uart_process_edma_isr(void) {
    
    	bool_t		result = false;
    	uint		intStatus;
    
    	CSL_CPINTC_getRawInterruptStatus(gCpHandle, 0, &intStatus);
    	if (intStatus & ((1 << CSL_INTC0_CPU_3_2_EDMACC_ERRINT) | (1 << CSL_INTC0_CPU_3_2_EDMACC_GINT))) {
    		ti_uart_edma_clear_event();
    		if (intStatus & (1 << CSL_INTC0_CPU_3_2_EDMACC_ERRINT)) {
    			CSL_CPINTC_clearSysInterrupt(gCpHandle, CSL_INTC0_CPU_3_2_EDMACC_ERRINT);
    		}
    		if (intStatus & (1 << CSL_INTC0_CPU_3_2_EDMACC_GINT)) {
    			CSL_CPINTC_clearSysInterrupt(gCpHandle, CSL_INTC0_CPU_3_2_EDMACC_GINT);
    		}
    
    		gTiUartGlobals.txCnt -= gTiUartGlobals.edmaInProgressCnt;
    		gTiUartGlobals.txRdPtr += gTiUartGlobals.edmaInProgressCnt;
    		if (gTiUartGlobals.txRdPtr >= &(gTiUartGlobals.txBuff[gTiUartGlobals.txBuffSize])) {
    			gTiUartGlobals.txRdPtr = gTiUartGlobals.txBuff;
    		}
    		gTiUartGlobals.edmaInProgressCnt = 0;
    
    		ti_uart_start_edma_xfer();
    		result = true;
    	}
    
    	return result;
    }
    #endif
    
    #pragma CODE_SECTION(ti_uart_isr, ".csl_vect")
    static void	ti_uart_isr(void *data) {
    
    	bool_t		flag = true;
    	bool_t		handled = false;
    	uint		uartIIR, temp;
    	char		val;
    	uint		intStatus0, intStatus5;
    	uint		processCount = 0;
    
    	if (gTiUartGlobals.isInitialized == false)
    		return;
    
    	/* Disable CPINTC0 Host interrupt (CPINTC output) */
    	CSL_CPINTC_disableHostInterrupt(gCpHandle, UART_CORE_INTC_CHANNEL);
    
    	interrupt_start(null, null);
    
    	_ti_uart_process_edma_isr();
    
    	CSL_CPINTC_getRawInterruptStatus(gCpHandle, 5, &intStatus5);
    	if (intStatus5 & (1 << (CSL_INTC0_UARTINT - (32 * 5)))) {
    		handled = false;
    		uartIIR = UART_REGS->IIR;
    		if ((uartIIR & 1) == 0) {
    			uartIIR >>= 1;
    			uartIIR &= 7;
    			switch (uartIIR) {
    				case kUartIIR_INTID_TXEmpty:
    					/* THR empty */
    					ti_uart_start_edma_xfer();
    					break;
    				case kUartIIR_INTID_RXLineStatus:
    					/* Line status Error */
    					temp = UART_REGS->LSR;
    					if ((temp & (1 << 1)) != 0) {
    						break;
    					}
    				case kUartIIR_INTID_RXAvailable:
    				case kUartIIR_INTID_CharTimeout:
    					/* DR - Receiver data-ready */
    					val = (char)UART_REGS->RBR;
    					switch (val) {
    						case 0x13:	//xoff
    							ti_uart_edma_pause_transfer();
    							break;
    						case 0x11:	//xon
    							ti_uart_edma_continue_transfer();
    							break;
    						default:
    							if (gTiUartGlobals.uartDev.uartInit.rxHandler != null) {
    								(gTiUartGlobals.uartDev.uartInit.rxHandler)(kNoError, (char*) &val, 1);
    							} else if (gTiUartGlobals.rxCnt < gTiUartGlobals.rxBuffSize) {
    								gTiUartGlobals.rxCnt++;
    								*gTiUartGlobals.rxWrPtr++ = val;
    								if (gTiUartGlobals.rxWrPtr >= &(gTiUartGlobals.rxBuff[gTiUartGlobals.rxBuffSize])) {
    									gTiUartGlobals.rxWrPtr = gTiUartGlobals.rxBuff;
    								}
    							}
    							break;
    					}
    					break;
    				default:
    					break;
    			}
    			if (++processCount > 1) {
    				puts_uart("\n" kConsole_Escape_Yellow "***UART Multi Processed***\n" kConsole_Escape_Default);
    			}
    			handled = true;
    		}
    		/* Acknowledge cp intc interrupt */
    		CSL_CPINTC_clearSysInterrupt(gCpHandle, CSL_INTC0_UARTINT);
    		if (handled == false) {
    			// This should never Print right?
    			puts_uart("\n" kConsole_Escape_Red "***UART Glitch***\n" kConsole_Escape_Default);
    		}
    	}
    	interrupt_exit(null, null);
    
    	/* Acknowledge CorePac intcUartHnd */
    	CSL_intcHwControl(gTiUartGlobals.intCHandle, CSL_INTC_CMD_EVTCLEAR, NULL);
    	/* Enable the CIC0 host interrupt output */
    	CSL_CPINTC_enableHostInterrupt(gCpHandle, UART_CORE_INTC_CHANNEL);
    
    }
    

  • Erick,

    Please take a look at the Table 3-6 in UART user guide. The IIR.IPEND could be cleared automatically if certain events happen. 

    It could be the case that the code enters into the ISR after the initial UART interrupt being triggered. But certain event happens inside of the ISR which clears the interrupt in IPEND bit.

    So are you able to selectively enable a couple UART interrupts only and identify under which case the "false alarm" will happen and if anything could happen to clear the interrupt pending bit please?

  • Steven,

    I'm pretty sure that I am not doing anything that could cause the interrupt to be cleared in my routine.

    The only possibility is if a DMA is in progress and the TX interrupt fires, however I do not have the IER register set to enable the TX register empty while the DMA is going so that interrupt should not be cause of it entering right?

    UART_REGS->IER = 
    (0 << 3) | /* EDSSI - Modem Status */
    (1 << 2) | /* ELSI - Receiver line status */
    (0 << 1) | /* ETBEI - Transmitter holding register empty */
    (1 << 0); /* ERBI - Receiver data available/character timeout indication */

    Erick