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.

C6655自定义中断函数interrupt关键字使用

你好,一般使用中断都是写好普通中断函数,然后在中断初始化函数中将中断函数注册响应的中断号即可,例如下面这样:

/*******************************************************************************
 * @函数名称   UART0_INT_Init
 * @函数说明   串口0中断初始化函数
 * @输入参数   无
 * @输出参数   无
 * @返回参数   无
 *******************************************************************************/
void UART0_INT_Init()
{
    unsigned int intFlags = 0;

    // 使能中断
    intFlags |= (UART_INT_LINE_STAT  |  \
            UART_INT_TX_EMPTY |    \
            UART_INT_RXDATA_CTI);
    UARTIntEnable(SOC_UART_0_REGS, intFlags);

    intFlags |= (   UART_FCR_FIFOEN  |  \
            UART_FCR_DMAMODE1);
    UARTDMAEnable(SOC_UART_0_REGS, intFlags);

    // 禁用发送中断
    UARTIntDisable(SOC_UART_0_REGS, UART_INT_TX_EMPTY);


    CICDisableGlobalHostInt(SOC_CIC_0_REGS);

    CICEventMap(SOC_CIC_0_REGS, INTC0_UARTINT_A, uiCIC_out_num);

    CICEnableGlobalHostInt(SOC_CIC_0_REGS);

    IntRegister(C66X_MASK_INT6, UART0_Isr);

    IntEventMap(C66X_MASK_INT6, SYS_INT_CIC0_OUT0_20);

    IntEnable(C66X_MASK_INT6);
}

平时都使用上面这种方式,没有什么问题。

但是最近看到一个例程,使用interrupt关键字定义,但是并未在其他地方进行中断注册,这种方式的实现原理是什么,在哪里有具体的讲解?代码如下:

interrupt void GE_Message_ISR()
{
	EMAC_Desc *pDesc;
	int recv_bytes = 0;

	puts("Hello");
	//EMAC_Recv((Uint8 *)0x10880000);

	/* check for new packet */
	if(emac_mcb.lastrxhdp == (Uint32)EMAC_REGS->RX0HDP)
		//return 0;
	    return;

	pDesc = (EMAC_Desc *)EMAC_REGS->RX0CP;
	if (pDesc->PktFlgLen & EMAC_DSC_FLAG_SOP) {
		/* Acknowledge recevied packet */
		EMAC_REGS->RX0CP = (Uint32)pDesc;

		/* store bytes recevied */
		recv_bytes = pDesc->PktFlgLen & 0xFFFF;

		/* optionally copy data to output buffer */
		memcpy((Uint8 *)0x10880000, pDesc->pBuffer, recv_bytes);
		parserRxPacket(pDesc);

		/* re-initalize descriptor to recevie more data */
		pDesc->BufOffLen = RX_BUFF_SIZE;
		pDesc->PktFlgLen = EMAC_DSC_FLAG_OWNER;

		/* assign descriptor to HDP */
		if (0 == (Uint32)EMAC_REGS->RX0HDP)
		{
		    EMAC_REGS->RX0HDP = (Uint32)pDesc;
		}
		else
		{
			((EMAC_Desc *) (emac_mcb.lastrxhdp))->pNext = pDesc;
		}

		emac_mcb.lastrxhdp = (Uint32)pDesc;

		/* For debug purpose */
//		printf("Receive packet length = %d,\n", recv_bytes);
	}

	EMAC_REGS->MACEOIVECTOR = 0x01;

	return;
}

void GE_Interrupts_Init(void)
{
	/* Disable Global host interrupts. */
	gpCIC0_regs->GLOBAL_ENABLE_HINT_REG= 0;


	/* Configure no nesting support in the CPINTC Module. */
	gpCIC0_regs->CONTROL_REG= ((gpCIC0_regs->CONTROL_REG&
		~CSL_CPINTC_CONTROL_REG_NEST_MODE_MASK)|
		(CPINTC_NO_NESTING<<CSL_CPINTC_CONTROL_REG_NEST_MODE_SHIFT));

	/* Clear Interrupt events in MDIO*/
//	gpMDIO_regs->LINK_INT_RAW_REG= 0xFFFFFFFF;

	/* Enable Global host interrupts. */
	gpCIC0_regs->GLOBAL_ENABLE_HINT_REG= 1;

	/* Enable EMAC RX interrupts in the control module */
	ECTL_REGS->C0_RX_EN = 0xFF;

	/*map EMAC RX interrupt to INT4 */
	gpCGEM_regs->INTMUX1 = 99<<CSL_CGEM_INTMUX1_INTSEL4_SHIFT;

	 /*Clear all DSP core events*/
	gpCGEM_regs->EVTCLR[0]= 	0xFFFFFFFF;
	gpCGEM_regs->EVTCLR[1]= 	0xFFFFFFFF;
	gpCGEM_regs->EVTCLR[2]= 	0xFFFFFFFF;
	gpCGEM_regs->EVTCLR[3]= 	0xFFFFFFFF;

	//clear DSP core interrupt flag
	ICR= IFR;

	//enable INT4 and INT5
	IER = 3|(1<<4)|(1<<5);

	/*Interrupt Service Table Pointer to begining of LL2 memory*/
	ISTP= 0x800000;

	//enable GIE
	TSR = TSR|1;
}

 

 

  • interrupt关键字在编译器手册里有讲。
    6.5.3 The interrupt Keyword
    www.ti.com/.../spru187u.pdf
  • 你好,我看了一下手册中interrupt关键字这段解释,但是稍微有点不明白。
    例如上面这段代码中GE_Message_ISR被定义为中断函数,什么条件下这个中断会被触发,是中断初始函数GE_Interrupts_Init(void)中的//enable INT4 and INT5
    IER = 3|(1<<4)|(1<<5);
    这句吗,所有的 INT4 and INT5均可以触发?
  • 中断事件发生,中断会被触发,相应的中断标志位会被置位,如果这时总中断和相应的中断使能位使能而且是最高 优先级的话,就会跳转到中断子函数。
  • 第一种中断使用方式很好理解,
    CICDisableGlobalHostInt(SOC_CIC_0_REGS);

    CICEventMap(SOC_CIC_0_REGS, INTC0_UARTINT_A, uiCIC_out_num);

    CICEnableGlobalHostInt(SOC_CIC_0_REGS);

    IntRegister(C66X_MASK_INT6, UART0_Isr);

    IntEventMap(C66X_MASK_INT6, SYS_INT_CIC0_OUT0_20);
    就是串口0中断标志位寄存器与中断号明确绑定注册,中断6和SYS_INT_CIC0_OUT0_20被置位时就会出发中断UART0_Isr。

    第二种中断定义方式,我在初始化函数中没法看到中断标志位、中断函数interrupt void GE_Message_ISR()与某个特定的中断号绑定注册,如何知道哪个中断标志位被置位时,会触发中断函数interrupt void GE_Message_ISR()?
  • 这个是把EMAC RX绑定到INT4
    /*map EMAC RX interrupt to INT4 */
    gpCGEM_regs->INTMUX1 = 99<<CSL_CGEM_INTMUX1_INTSEL4_SHIFT;

    GE_Message_ISR中断子程序的入口地址会在中断向量表中绑定,可以查看一下中断向量表vectors.asm

  • 非常感谢,是这样的,之前没注意到vectors.asm这个文件:

    ;--------------------------------------------------------------
    ;interrupt vector table	
    	.sect "vecs"
    	.align 1024
    	
    vectors:
    	VEC_RESET _c_int00     		;RESET 
    	VEC_ENTRY NMI_ISR	;NMI/Exception
    	VEC_DUMMY   		;RSVD
    	VEC_DUMMY   		;RSVD
    	VEC_ENTRY GE_Message_ISR   	;interrupt 4
    	VEC_ENTRY GE_MISC_MDIO_ISR   	;interrupt 5
    	VEC_DUMMY   		;interrupt 6
    	VEC_DUMMY   		;interrupt 7
    	VEC_DUMMY     		;interrupt 8 
    	VEC_DUMMY   		;interrupt 9
    	VEC_DUMMY   		;interrupt 10
    	VEC_DUMMY   		;interrupt 11
    	VEC_DUMMY   		;interrupt 12
    	VEC_DUMMY   		;interrupt 13
    	VEC_DUMMY   		;interrupt 14
    	VEC_DUMMY   		;interrupt 15
    	
    	.end

    这种中断注册方式使用起来没用第一种这么方便,什么情况下要用到这种方式,两者优缺点在哪里,在项目中两种方式同时使用要注意哪些问题呢?

  • 在中断向量表里注册中断一般是在裸机程序中用。在BIOS程序中bios自带中断向量表,通过HWI配置即可。