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.

[参考译文] TMS320F2.8069万:CAN Rx帧"丢失"

Guru**** 2577385 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/642123/tms320f28069-can-rx-frame-lost

部件号:TMS320F2.8069万

您好,

我在我的系统上运行过几次测试,似乎随机丢失了一个帧。

我的系统在总线上是从属设备。 eCAN模块配置为SCC模式。 邮箱6-9在接收中设置,10-15在传输中设置。

我在测试过程中观察到的是,帧由主机正确发送(总线上的间谍确认帧存在)。

然后在固件方面,当为相应的Rx邮箱(6-9)调用接收中断时,我将向UART发送ASCII字符。 我可以观察到,我没有在终端上写入此字节,因此我猜CAN收发器或CAN配置中有问题。

问题确实是随机的。 在这方面,任何调查想法或任何猜测都是非常受欢迎的。

此致,

Celine

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您说的是,您实际上在总线上看到了该帧,但eCAN中没有收到该帧。 因为这是一种随机现象,所以我现在不会怀疑硬件。 我能想到的唯一原因是接收邮箱未正确配置为接受此帧。 如果使用接受掩码过滤,请检查LAM寄存器的值。 或者检查邮件是否已复制到邮箱RAM中,但中断未触发(可能是由于当时的中断配置不正确)。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好Hareesh,

    感谢您的反馈。

    我不怀疑邮箱配置,因为丢失的帧ID在大多数时间都能正确接收,所以过滤工作正常。

    正如你所说的那样,我怀疑中断不会触发,但我不清楚如何检查这一点。

    此外,由于存在多个级别,我对中断标志的清除方式没有信心。 可能是问题所在。

    中断接收时完成:ECanaRegs.CANMIM.ALL = ECanaRegs.CANMIM.ALL &(~mbx_bit);  /*禁用Rx邮箱*/

                           PieCtrlRegs.PIEACK.ALL || PIEACK_group9;

    在线程上下文中处理邮箱内容时完成:ECanaRegs.CANRMP.ALL ||位;/*清除中断标志*/
                                                     ECanaRegs.CANMIM.ALL ||位; /*重新启用Rx邮箱*/

    中断初始化通过以下方式完成:

    PieVectorTable.ECAN0INTA =&cana_sys_isr;
    PieCtrlRegs.PIEIER9.bit.INTx5 = 1;
    PieVectorTable.ECAN1INTA =&cana_mbx_isr;
    PieCtrlRegs.PIEIER9.bit.INTx6=1;

    回叫定义如下

    中断无效cana_mbx_isr (void)

    Union CANGIF1_REG gif1;
    volatile结构MBOX *p_mbox =&ECanaMboxes.MBOX0;
    uINT32_t mbx_bit;
    gif1.all = ECanaRegs.CANGIF1.all;
    MBX_bit =((UINT32_t) 1)<gif1.bit.MIV1;
    p_mbox =&(p_mbox[gif1.bit.MV1]);
    EALLOW;
    ECanaRegs.CANMIM.ALL = ECanaRegs.CANMIM.ALL &(~mbx_bit);
    EDIS;
    如果( l_rx_CB[m]!=0)
    l_rx_cb[m](gif1.bit.mV1);

    PieCtrlRegs.PIEACK.ALL || PIEACK_group9;
    }

    和l_rx_CB[x]

    void CAN_RX_callback (uint16_t邮箱)

    //消息将在CANopen管理器上下文中处理
    can_msg_evt_t* PE = q_new( can_msg_evt_t, SIG_CAMSG );
    pE->data =邮箱;
    QActive_postFIFO (g_ao_CANopen,(QEvent*)PE);

    }

    最后,在线程上下文中接收邮件时,我阅读邮箱的内容

    void can_read_msg( uint16_t mbx, canmsg_t* msg )

    volatile结构mBOX *p_mbox =0;
    uINT16_t prev_int_status;
    UINT32_t位=((UINT32_t) 1)<mbx;
    char msg2[50];
    p_mbox =&(ECanaMboxes.MBOX0)+ mbx;

    EALLOW;
    ECanaRegs.CANRMP.ALL ||位;/*清除中断标志*/
    ECanaRegs.CANMIM.ALL ||位;/*重新启用Rx邮箱*/
    EDIS;

    IF (ECanaRegs.CANRML.ALL & BIT)

    日志("CAN_READ_MSG %d丢失\r\n",位);
    }

    msg->id = p_mbox->msgid.bit.stdmsgid;/*复制消息ID */
    msg->len = p_mbox->MSGCTRL.bit.dlc;/*复制消息长度*/
    MSG->RTR = p_mbox->MSGCTRL.bit.RTR;/*复制消息RTR位*/
    msg->data[0]= p_mbox->mDL.byte.BYTE0;
    MSG->DATA[1]= p_mbox->MDL.byte.BYTE1;
    MSG->DATA[2]= p_mbox->MDL.byte.BYTE2;
    MSG->DATA[3]= p_mbox->MDL.byte.BYTE3;
    msg->data[4]= p_mbox->mDH.byte.BYTE4;
    msg->data[5]= p_mbox->mDH.byte.BYTE5;
    MSG->DATA[6]= p_mbox->mDH.byte.BYTE6;
    msg->data[7]= p_mbox->mDH.byte.BYTE7;
    }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    如何确保消息未被覆盖? 是否启用了RML中断?
    由于您不使用邮箱0到5,您是否尝试过将这些邮箱配置为接收,以确保收到的邮件不会被改写?

    您是否使用OPC机制?

    是否已验证邮件是否正确复制到邮箱RAM中?

    您可能还需要使用邮箱超时机制,在特定时间内未收到邮件时向您发出警报。 请注意,仅当根本没有收到消息时才适用,不适用于收到消息但由于某种原因中断未触发的情况(我怀疑此处是这种情况)。

    在SPRUH18G中,1.7 一节清楚地说明了CPU进行中断所必须满足的各种条件。 它还包含一些需要遵守的注意事项。 请特别注意图1-94和1.7 .3.1 至1.7 .3.3 部分。

    有关一些调试提示和程序示例,请参见SPRA876B。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好Hareesh,
    感谢您的回答和链接。 我确实看了一下,但很遗憾,我仍然有问题。

    我已启用RML中断。 读取邮箱时,我确实已阅读检查CANRML寄存器,以检查是否没有丢失消息

    /*检查是否未设置邮箱丢失标志*/
    IF (ECanaRegs.CANRML.ALL & BIT)

    邮箱0至5用于SYNC和NMT。 我设置了三个邮箱来接收这些特定邮件。 我添加了一些调试程序,但仅使用邮箱9,其他两个从未使用,因此这不是缺少邮箱。 为了检查该部件,我已经为前两个部件启用了OPC机制,并为最后一个禁用了OPC机制,因此在出现问题时,它应该会触发中断。 我也没有收到。

    EALLOW;
    CAN_MASK_6_15 (0xFF03FFFF);

    CAN_mbx (6,RX,OP_OFF,STD_MSGID (AME_ON,CANopen_id));//最后一个mbox保护应关闭以触发中断
    for (i=7;i<=last_RX_MBX;i++)
    CAN_mbx (I,RX,OP_ON,STD_MSGID (AME_ON,CANopen_id));

    最后,我得出的结论是,在RAM中接收并复制了该消息,但中断不会触发。
    由于在读取邮箱之前禁用了中断,我对阅读的一些示例感到困惑。 如果我正确理解了数据表,那么当RMP中的相应标志未被清除时,我收到中断的邮箱将被禁用,同时我也已在引发Rx中断时删除ECanaRegs.CANMIM.All的配置。

    下面是我的代码。 我相信仍然有一些问题,但无法找出。

    当为接收邮箱触发中断时,将调用cana_mbx_isr()。 然后,调用CAN_RX_callback(ECanaRegs.CANGIF1.bit.MIV1),并在中断上下文中向CANopen任务发送消息SIG_CANMSG。 将使用can_read_msg()在CANopen任务上下文中读取邮箱。 这种邮箱读取延迟是否是根本原因?如果是,我不理解为什么邮箱不应该被覆盖,因为OPC机制和其他Rx邮箱应该被使用。 我很有信心不是这样。

    *******************
    ******************************* 初始化 **********
    *******************

    void can_module_init( uint16_t canopen_id,uint16_t bitrate )

    int i =0;
    CAN_INIT (比特率);

    EALLOW;
    CAN_MASK_0_2( MASK_NMT_ERR_CTRL );

    CAN_mbx( 0, Rx, OP_OFF, STD_MSGID( AME_ON,0x700);
    CAN_mbx( 1, Rx, OP_ON, STD_MSGID( AME_ON,0x700);
    CAN_mbx( 2, Rx, OP_ON, STD_MSGID( AME_ON,0x700);

    //邮箱3-5用于接收CANopen NMT,同步和时间戳
    CAN_mbx (3,RX,OP_OFF,STD_MSGID (AME_OFF,0x00));// NMT
    CAN_mbx (4,RX,OP_ON,STD_MSGID (AME_OFF,0x00));// NMT
    CAN_mbx (5,RX,OP_ON,STD_MSGID (AME_OFF,0x00));// NMT

    /*邮箱6-9用于接收CANopen节点消息*/
    EALLOW;
    CAN_MASK_6_15 (0xFF03FFFF);// 1111 1111 0000 0011 1111 1111 1111 1111 1111 1111 1111

    CAN_mbx (6,RX,OP_OFF,STD_MSGID (AME_ON,CANopen_id));//最后一个mbox保护应关闭以触发中断
    for (i=7;i<=last_RX_MBX;i++)
    CAN_mbx (I,RX,OP_ON,STD_MSGID (AME_ON,CANopen_id));

    //10-15个邮箱是TX
    for (I=FIRST_TX_MBX;I<=LST_TX_MBX;I++)
    CAN_mbx (I,TX,OP_OFF,0);

    CAN_Interrupts (CAN_SYS_callback,CAN_RX_callback);

    EDIS;
    }


    void can_interrupts (can_sys_callback_t sys_cb, can_rx_callback_t rx_cb)

    易失性结构ECAN_regs *p_CAN_regs;
    EALLOW;

    p_can_regs = ECanaRegs (&E);
    l_sys_cb[0]= sys_cb;
    l_rx_cb[0]= rx_cb;

    PieVectorTable.ECAN0INTA =&cana_sys_isr;
    PieCtrlRegs.PIEIER9.bit.INTx5 = 1;
    PieVectorTable.ECAN1INTA =&cana_mbx_isr;
    PieCtrlRegs.PIEIER9.bit.INTx6=1;

    /*这些寄存器允许CPU识别中断源。 */
    p_CAN_regs->CANGIF0.ALL = 0xFFFFFFFF;
    p_CAN_regs->CANGIF1.ALL = 0xFFFFFFFF;
    p_can_regs->canmil.all = 0xFFFFFFFF;//所有邮箱在第1行生成中断
    //将global (模块,而不是邮箱)中断行设置为0并启用这两行
    p_CAN_regs->CANGIM.ALL =(UINT32_t)(INT_SCC_ALL |0x3);
    IER || M_INT9;

    EDIS;
    }

    *******************
    ******************************* 回调 ******
    *******************

    #define SYS_ISR_internals(regs, m)\
    联合CANGIF1_REG gif1;\
    gif1.all = ECanaRegs.CANGIF1.all;\
    IF (regs.CANGIF0.ALL & INT_ABORT_ACK){\
    IF (l_sys_CB[m]!=0) l_sys_CB[m](INT_ABORT_ACK,gif1.bit.MIV1);\
    regs.canaa.all = 0xFFFFFFFF;\
    }\
    其他\
    IF (regs.CANGIF0.ALL & INT_WRITE拒绝){\
    if (l_sys_CB[m]!=0) l_sys_CB[m](INT_write_denied,gif1.bit.mV1);\
    regs.CANGIF0.ALL &= INT_WRTE_DENIED;\
    }\
    其他\
    IF (regs.CANGIF0.ALL & INT_WAKEUP){\
    if (l_sys_CB[m]!=0) l_sys_CB[m](INT_WAKEGWAY,gif1.bit.MIV1);\
    regs.CANGIF0.ALL &= INT_WAKEE;/*清除中断标志位*/\
    }\
    其他\
    IF (regs.CANGIF0.ALL & INT_RECV_MSG_Lost){\
    IF (l_sys_CB[m]!=0) l_sys_CB[m](INT_RECV_MSG_Lost,gif1.bit.MIV1);\
    REGS.CANGIF0.ALL &= INT_RECV_MSG_LOSS;/*清除中断标志位*/\
    regs.canrmp.all = 0xFFFFFFFF;\
    }\
    其他\
    IF (regs.CANGIF0.ALL & INT_BUS_OFF){\
    IF (l_sys_CB[m]!=0) l_sys_CB[m](INT_BUS_OFF,gif1.bit.MIV1);\
    regs.CANGIF0.ALL &= INT_BUS_OFF;\
    }\
    其他\
    IF (regs.CANGIF0.ALL & INT_ERR_PASSIVE){\
    IF (l_sys_CB[m]!=0) l_sys_CB[m](INT_ERR_PASSIVE,gif1.bit.MIV1);\
    regs.CANGIF0.ALL &= INT_ERR_PASSENE;\
    }\
    其他\
    IF (regs.CANGIF0.ALL & INT_WARE_LEVEL){\
    IF (l_sys_CB[m]!=0) l_sys_CB[m](INT_WARE_LEV,gif1.bit.MIV1);\
    regs.CANGIF0.ALL &= INT_WARE_LEV;\
    }

    #pragma code_section (cana_sys_isr,"ramfuncs";
    中断无效cana_sys_isr (void)

    SYS_ISR_internals(ECanaRegs,0);

    IER || M_INT9; //启用INT9
    EINT;
    PieCtrlRegs.PIEACK/bit.ACK9 =1;//启用PIE将脉冲驱动到CPU中
    }

    #pragma code_section (cana_mbx_isr,"ramfuncs";
    中断无效cana_mbx_isr (void)

    IER || M_INT9;
    PieCtrlRegs.PIEACK/bit.ACK9 =1;//启用PIE将脉冲驱动到CPU中
    EINT;

    L_RX_CB[0](ECanaRegs.CANGIF1.bit.MIV1);
    }

    void CAN_RX_callback (uint16_t邮箱)

    /*确认在cana_mbx_isr */中完成中断

    //消息将在CANopen管理器上下文中处理
    can_msg_evt_t* PE = q_new( can_msg_evt_t, SIG_CAMSG );
    pE->data =邮箱;
    QActive_postFIFO (g_ao_CANopen,(QEvent*)PE);
    }

    void can_read_msg( uint16_t mbx, canmsg_t* msg )

    volatile结构mBOX *p_mbox =0;
    uINT16_t prev_int_status;
    UINT32_t位=((UINT32_t) 1)<mbx;
    uINT16_t i=0;
    p_mbox =&(ECanaMboxes.MBOX0)+ mbx;

    /*检查是否未设置邮箱丢失标志*/
    IF (ECanaRegs.CANRML.ALL & BIT)

    同时(1);
    }

    EALLOW;
    ECanaRegs.CANRMP.ALL ||位;/*清除中断标志*/
    EDIS;

    msg->id = p_mbox->msgid.bit.stdmsgid;/*复制消息ID */
    msg->len = p_mbox->MSGCTRL.bit.dlc;/*复制消息长度*/
    MSG->RTR = p_mbox->MSGCTRL.bit.RTR;/*复制消息RTR位*/
    msg->data[0]= p_mbox->mDL.byte.BYTE0;
    MSG->DATA[1]= p_mbox->MDL.byte.BYTE1;
    MSG->DATA[2]= p_mbox->MDL.byte.BYTE2;
    MSG->DATA[3]= p_mbox->MDL.byte.BYTE3;
    msg->data[4]= p_mbox->mDH.byte.BYTE4;
    msg->data[5]= p_mbox->mDH.byte.BYTE5;
    MSG->DATA[6]= p_mbox->mDH.byte.BYTE6;
    msg->data[7]= p_mbox->mDH.byte.BYTE7;

    IF (ECanaRegs.CANRMP.ALL和BIT)

    同时(1);
    }
    }