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.

[参考译文] TMS320F280025:针对消息目标的 CAN 中断生成

Guru**** 2524550 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1158472/tms320f280025-can-interrupt-generation-for-message-objects

器件型号:TMS320F280025

大家好、

如果有多个消息对象被标记为中断、我不确定 CAN 中断是如何工作的。 遗憾的是、所有 CAN 样本都非常简单、每个方向只有一个消息对象。

我们在程序流程中禁用了中断、因此可能会发生中断、而 CAN0INT 的中断例程会在发送多个消息对象后得到服务。 在服务例程中、最新对象(中断原因 INT0ID)和服务例程的标志被清除:

    CAN_clearInterruptStatus(CANIF_CAN_BASE, intCause);

    CAN_clearGlobalInterruptStatus(CANIF_CAN_BASE, CAN_GLOBAL_INT_CANINT0);
    
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);

然后是否预计 ISR 将再次调用、因为其他报文对象会将 CAN0INT 保持为高电平? 或者、我们是否需要循环、直到 INT0ID 返回0?
我希望根据图3-2再次调用 ISR。 中断传播路径和图21-8. CAN 中断拓扑2 (F28002x 技术参考中均有)。

非常感谢、

Andreas

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Andreas:

    你是对的。  CAN 示例仅使用一个接收和一个发送报文对象、并且显示的 ISR 每次仅为其中一个对象提供服务。  但是、您可以展开该示例以使用所有32个消息对象、它们可以是组合或接收或发送对象。  有两条中断线路可供使用。  您可以选择 INT0ID 或 INT1ID 行。  示例使用 INT01D 行、 如果您查找 CAN_INT 寄存器的定义、INT1ID 将显示32个邮箱中每个邮箱的中断原因。  INT0ID 将显示32个邮箱中每个邮箱的中断原因以及错误和状态寄存器。

    所有示例都使用 INT0ID、因此无论何时接收到与邮箱定义匹配的消息以及何时触发状态和错误标志、它们都将触发 ISR。  如果希望消息对象触发 INT01D 行,则需要在对象创建中指定此项,例如:

    	#define MSGOBJ0		0
    	#define MSGOBJ1		1
    	#define MSGOBJ2		2
    	#define MSGOBJ3		3
    	:
    	:
    	:
    	#define MSGOBJ29	29
    	#define MSGOBJ30	30
    	#define MSGOBJ32	31
    	
        CAN_setupMessageObject(CANA_BASE, MSGOBJ0, 0x12345,
                               CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 0,
                               CAN_MSG_OBJ_RX_INT_ENABLE, MSG_DATA_LENGTH);
        CAN_setupMessageObject(CANA_BASE, MSGOBJ1, 0x23456,
                               CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 0,
                               CAN_MSG_OBJ_RX_INT_ENABLE, MSG_DATA_LENGTH);
        CAN_setupMessageObject(CANA_BASE, MSGOBJ2, 0x789AB,
                               CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 0,
                               CAN_MSG_OBJ_RX_INT_ENABLE, MSG_DATA_LENGTH);
    						   :
    						   :
    	CAN_setupMessageObject(CANA_BASE, MSGOBJ29, 0x789AB,
                               CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_TX, 0,
                               CAN_MSG_OBJ_TX_INT_ENABLE, MSG_DATA_LENGTH);
    

    在 CAN ISR 中、您可以按如下方式处理中断:

        //
        // Read the CAN-B interrupt status to find the cause of the interrupt
        //
        status = CAN_getInterruptCause(CANA_BASE);
    	
    	if(status == MSGOBJ0)
    	{
            //
            // Get the received message
            //
            CAN_readMessage(CANA_BASE, MSGOBJ0, rxMsgData1);
    
            //
            // Getting to this point means that the RX interrupt occurred on
            // message object 1, and the message RX is complete.  Clear the
            // message object interrupt.
            //
            CAN_clearInterruptStatus(CANA_BASE, MSGOBJ0);	
    	}
    	if(status == MSGOBJ1)
    	{
            //
            // Get the received message
            //
            CAN_readMessage(CANA_BASE, MSGOBJ1, rxMsgData2);
    
            //
            // Getting to this point means that the RX interrupt occurred on
            // message object 1, and the message RX is complete.  Clear the
            // message object interrupt.
            //
            CAN_clearInterruptStatus(CANA_BASE, MSGOBJ1);		
    	}
    	if(status == MSGOBJ2)
    	{
            //
            // Get the received message
            //
            CAN_readMessage(CANA_BASE, MSGOBJ2, rxMsgData3);
    
            //
            // Getting to this point means that the RX interrupt occurred on
            // message object 1, and the message RX is complete.  Clear the
            // message object interrupt.
            //
            CAN_clearInterruptStatus(CANA_BASE, MSGOBJ2);		
    	}
    	
    	//
        // Clear the global interrupt flag for the CAN interrupt line
        //
        CAN_clearGlobalInterruptStatus(CANA_BASE, CAN_GLOBAL_INT_CANINT0);
    
        //
        // Acknowledge this interrupt located in group 9
        //
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
    

    每次接收到符合任何报文对象定义的匹配 CAN 报文时、都会调用 ISR。

    Hope 上述示例阐明了消息对象和中断的处理方式。

    此致、

    Joseph

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的回复、Joseph。

    我们基本上已经开始工作了。

    正如您所说的、每次接收或发送消息对象时都会调用 ISR。 在本例中、我们只是发送消息。 关于 INT0ID 的行为("中断原因")、声明如下:

    If several interrupts are pending, the CAN Interrupt Register will point
    to the pending interrupt with the highest priority.
    Note: The CANINT0 interrupt line remains active until INT0ID
    reaches value 0 (the cause of the interrupt is reset) or until IE0 is
    cleared.

    在我们的情况下、这种情况可能会发生、因为我们必须针对应用程序的某些其他代码全局禁用中断、因此在禁用中断期间、将在 CAN 总线上发送多个消息对象。

    如上所示、我们不清除 IE0、因此 CANINT0应保持活动状态。

    我们观察到、如果我们只读取和清除 ISR 中的一个对象("中断原因")-正如您对 CAN_clearInterruptStatus 所做的那样-中断将不会再次被调用、尽管 CAN0INT 应该保持有效、因为仍然存在设置了"传输正常"的消息对象。

    是否需要此行为? CAN0INT 是否需要有一个上升沿来实际触发中断? 我在文档中没有找到任何关于这一点的信息。
    当然、另一个选项是在中断例程中循环、直到 INT0ID 为零。

    总的来说、我想知道到底发生了什么(不发生)、以便我了解在实施任何可能的解决方案时的影响。

    谢谢、
    Andreas

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Andreas:

    很抱歉、我错过了您发送消息的部件。  在这种情况下、当定义发送消息对象时、您不必启用中断、因此当发送消息时、代码不会进入 ISR。  这样就无需清除中断标志。  以下示例代码:

    	#define MSGOBJ0		0
    	#define MSGOBJ1		1
    	#define MSGOBJ2		2
    	#define MSGOBJ3		3
    	:
    	:
    	:
    	#define MSGOBJ29	29
    	#define MSGOBJ30	30
    	#define MSGOBJ32	31
    	
        CAN_setupMessageObject(CANA_BASE, MSGOBJ0, 0x12345,
                               CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 0,
                               CAN_MSG_OBJ_RX_INT_ENABLE, MSG_DATA_LENGTH);
        CAN_setupMessageObject(CANA_BASE, MSGOBJ1, 0x23456,
                               CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 0,
                               CAN_MSG_OBJ_RX_INT_ENABLE, MSG_DATA_LENGTH);
        CAN_setupMessageObject(CANA_BASE, MSGOBJ2, 0x789AB,
                               CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 0,
                               CAN_MSG_OBJ_RX_INT_ENABLE, MSG_DATA_LENGTH);
    						   :
    						   :
    	CAN_setupMessageObject(CANA_BASE, MSGOBJ29, 0x789AB,
                               CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_TX, 0,
                               CAN_MSG_OBJ_NO_FLAGS, MSG_DATA_LENGTH);

    发送消息对象 MSGOBJ29定义使用 CAN_MSG_OBJ_NO_FLAGS、这意味着发送此对象不会触发中断、也不会进入 ISR 以进行服务并清除标志和确认。  CANITN0中断线仍然有效、并且可以由将使用它的报文对象触发。

    请告诉我这是否对您有效。

    此致、

    Joseph

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Joseph、

    我们确实希望在成功发送所有报文对象时收到通知。 这就是我们首先启用中断的原因。

    我的问题仍然是预期的中断行为。 如果仍有具有挂起中断的消息对象,是否会再次调用 ISR (立即调用)?
    根据文件,我要说是的,但我们没有看到这种情况发生。 正如我说过的、CAN0INT 可能需要某种上升沿?

    这就是为什么我假设我们必须在 ISR 内循环、直到 INT0ID 为0。 不幸的是,这里的文件似乎不清楚,如果有此打算,我希望得到确认。

    再次感谢、

    Andreas

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Andreas:

    F280025不支持嵌套中断、因此、只要一个中断发生、就必须首先为其提供服务、清除原因并确认是否发生其他挂起的中断。

    此致、

    Joseph