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.

[参考译文] TMS570LC4357:由于 canIsTxMessagePending ()卡滞、CAN 初始化不可靠

Guru**** 2455560 points
Other Parts Discussed in Thread: HALCOGEN

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1183626/tms570lc4357-unreliable-can-initialization-due-to-stuck-canistxmessagepending

器件型号:TMS570LC4357
主题中讨论的其他器件:HALCOGEN

我遇到了很多不可靠的 CAN 启动。  有时可以正常启动、消息在我的两个 Launchpad 之间无问题地流动。  有时、可能无法正常启动、两个 Launchpad 之间没有任何流动。

每个 Launchpad 节点上的代码,1和2,调用 canInit() 以初始化通信。  我发现,如果我在两个节点的特定“时间窗口”内启动 canInit(),则流量将正常流动。  但是,如果 canInit()位于该窗口之外,则两个节点将无限期停留在 canIsTxMessagePending ()中,其中已填充了发送消息框(挂起),但未发生传输。  我已经尝试忽略挂起的情况并使用另一条消息调用 canTransmit()或清除传输挂起位,但也不会"解开"消息框。  我还尝试将 Halcogen 设置为使用"启用自动总线打开"、但没有结果。

我很确定这与 INAAN CAN 协议缺陷有关、在这种缺陷中、如果没有接收器来接收消息(接收器清除总线上消息中的"我正在侦听"位)、发送器"中止"其传输、也许 TI CAN 实现。  如果我在 CAN 总线上放置 Kvaser Leaf Lite 分析器探针、则数据流会很顺利、因为分析器会主动清除总线上消息中的位。  这是一种有缺陷的协议、其中分析器必须具有_侵入式_才能使数据流动并受到监控。

这个主要的错误有没有办法解决,或者我死在水里了吗?

感谢所有帮助。

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

    《技术参考手册》指出、有一个 TxRqst 位可用于重新启动(失败)传输。  这显然仅在自动重传关闭时使用。  我不知道自动重传的功能是什么、也不知道这是否可以节省一天的时间。

    感谢你的任何帮助。  谢谢。

    ===来自技术参考手册...

    如果通过将 CAN 控制寄存器的 DAR 位置位来禁用自动重发送模式
    接口寄存器组的消息控制寄存器中的 TxRqst 和 NewDat 位的行为如所示
    如下:
    •当一个传输开始时、相应接口寄存器组的 TxRqst 位被复位、同时位被复位
    NewDat 保持置位。
    •当发送成功完成时、NewDat 位被复位。
    当发送失败(丢失仲裁或错误)时、NewDat 位保持置位。 要重新启动传输、
    应用必须再次设置 TxRqst。

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

    在堵塞的 TX 消息盒周围似乎存在潜在的修复/黑客攻击。  希望清除 TxRqst 位将会解除消息框的堵塞并使 canTransmit()正常工作(再次)。  我看不到任何 TI CAN 控制器功能可以忽略总线上消息的"接收器监听"位。

    27.17.15发送请求寄存器(DCAN TXRQ12至 DCAN TXRQ78)
    这些寄存器保存已执行的报文对象的 TxRqst 位。 通过读取这些位、即
    CPU 可以检查是否有挂起的传输请求。 特定报文对象中的 TxRqst 位可以是
    由 CPU 通过 IF1/IF2消息接口寄存器置位/复位、或之后由消息处理器置位/复位
    接收远程帧或成功传输后。

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

    修复简单、只需检查 TX 挂起何时处于活动状态、例如、在看到 TX 消息通知后已过一段时间...

    。 //此时不应有任何 TX 待处理,因此请清除任何 TX
    uint32 txrqx =节点->TXRQX;
    if (txrqx & 0x3){//仅选中使用的16个消息框
    CNC_TxMessagePendingClogs++;
    canClearTxMessagePending (节点、messageBoxHi);
    canClearTxMessagePending (节点、messageBoxLo);

    ===添加了 Halcogen 函数...

    uint32 canClearTxMessagePending (canBASE-t *节点、uint32 MessageBox)

    uint32成功= 0U;
    uint32 regIndex =(MessageBox - 1U)>> 5U;
    uint32 bitIndex = 1U <<(MessageBox - 1U)和0x1FU);

    /**-检查待处理消息:
    *-无待处理消息、返回0
    *-待处理消息、清除待处理消息
    *
    if ((node->TXRQx[regIndex]& bitIndex)=0U)

    成功= 0U;

    其他

    /**-等待 IF1准备就绪可供使用*/
    /*SAFETYMCUSW 28 D MR:NA "找到可能无限的循环-执行序列的硬件状态检查"*/
    while ((node->IF1STAT & 0x80U)=0x80U)

    }/*等待*/

    /**-通过清除消息框中的 TxRqst 来终止传输*/
    NOD->IF1CMD =(uint8) 0x00U;//注意0x84U =BUSY+TxRqst */

    /**-从消息框触发远程帧传输*/
    /*SAFETYMCUSW 93 S MR:6.1、6.2、10.1、10.2、10.3、10.4 "LDRA 工具问题"*/
    NOode->IF1NO =(uint8) MessageBox;

    成功= 1U;

    /**@请注意,必须先调用函数 canInit,然后才能使用此函数。\n
    *用户负责初始化消息框。
    *
    返回成功;

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

    清除 TxRqst 所需的代码实际上如下所示、CMD 写入0x90U。  node->TXRQX 和 node->TXRQx[]寄存器显示该位已清除,随后的 canTransmit()实际上会执行一些操作。

    遗憾的是、这不能解决问题、因为消息盒确实被解除阻塞、TX 数据开始流动、但数据速率低于应有的10%。  TxRqst (挂起)问题也会持续出现。  需要执行一些其他操作来恢复/修复 Tx 引擎、或者根本无法修复。

    请提供建议帮助。  谢谢。

    === canClearTxMessagePending ()中的代码以清除 TxRqst...

    /**-通过清除消息框中的 TxRqst 来终止传输*/
    Node->IF1CMD =(uint8) 0x90U;/* ProtectedWrite+Control+No_TxRqst */

    /**-从消息框中触发清除发送挂起*/
    /*SAFETYMCUSW 93 S MR:6.1、6.2、10.1、10.2、10.3、10.4 "LDRA 工具问题"*/
    NOode->IF1NO =(uint8) MessageBox;

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

    通过(my) canTxMessagePending ()中的 IF1CMD 清除 TxRqst 似乎已正确完成,但随后对 canTransmit()的调用会执行所有"正确"的操作,只是总线上的传输没有发生。

    我不知道要用什么来获得在 canTransmit()中发出的0x87命令才能将消息对象实际发送到总线上。

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

    尊敬的 Peter:

    我很抱歉耽误你的答复。 您是否在 launchpad 上添加了 CAN 收发器、并在 CAN 总线的两端添加了端接电阻器(120欧姆)?

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

    是的。

    正如我提到过的、如果我在特定的时间窗口(大约8秒)内启动两个 Launchpad 节点、则传输-接收工作正常。  如果节点在时间窗口之外启动(例如15秒后)、则发送器卡塞。  此外、如果我在总线上插入 Kvaser Light Leaf V2探针、则一切都正常;Light Leaf V2会在总线上传输的所有 CAN 帧上将 ACK Slot 位设置为显性。

    在查看技术参考手册第27.17.1节时、提到了 TI 控制器停用控制器(发送器?) 一旦看到11个隐性位(我假设这意味着 ACK 时隙位)。  本节的其余部分对我来说是希腊语、因为我无法判断我应该查找的错误是什么、或者如果控制器(发送器)确实处于非活动状态、如何从该错误中恢复。

    我甚至不清楚 TI 控制器是如何重新传输的。  不确定这是 CAN 规范还是 TI 控制器功能、以及要查看的规范。

    非常感谢您的帮助。

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

    我已经重新验证了如果 Launchpad 处于发送器阻塞状态(没有接收器通电、或 Kvaser Light Leaf v2探测器位于总线上)、然后将 Kvaser 探测器放置在总线上、则发送器开始传输。  因此、似乎是 TI 控制器接收器(如果可用/可用)不堆叠(重新)传输的帧。

    对此的任何见解都将大有帮助。

    谢谢。

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

    有趣的是、如果我在端口上关闭_自动重传、将 Kvaser 探头放在总线上仍会使 Launchpad 控制器进行传输。  因此、如果"CAN 总线状态"发生变化、TI 控制器将以某种方式启动传输(与自动重发送无关)。

    当然、我不知道 Kvaser 探针在公共汽车上实际执行的操作的确切细节。

    谢谢。

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

    我认为  Kvaser 探针具有内置 CAN 收发器和 CAN 总线终端器。   CAN 网络 必须通过  两个端点的总线终端(120欧姆)从一个节点连接到另一个节点。

    在启动期间、如果只有1个 CAN 节点处于联机状态、并且此节点传输消息、则不会获得 ACK。 它可能会成为"错误被动"、但不会成为"总线关闭"。

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

    您好、QJ、

    正如我提到过的、CAN 通信具有这种"定时窗口"行为、因此总线终端(在本例中)不是问题、因为只要建立了通信握手、数据就会在两个 TMS570-LC43之间永久地成功传输。  我们确实遇到了一些可能与收发器连接相关的终止问题、我稍后将介绍这一点、这与此特定握手问题无关。

    由于 Kvaser 充当了"消息接收器"(将显性 ACK 槽置为有效)、我决定查看连接另一个仅配置为数据接收器的 CAN 端口是否会有效地取代 Kvaser。  我们在两个 TMS570板上以1M bps 的速率运行 CAN1、因此我在该总线上连接了(之前未使用)以1M bps 的速率运行的 CAN4端口。  CAN4根本不用于发送或接收报文。  正如人们所期望的那样、CAN4能够 执行数据接收器功能以及 Kvaser、因此这成为了一种回退(但很丑)解决方案。

    但是、在进行 CAN4实验时、我注意到"定时窗口"与我们使用的1M bps 速度有某种关系。  我们一直在使用调用 canInit()后发生的一些动态修补来修复1M bps BTR Halcogen 错误。  您为我们的硬件人员提供了一些计算器来确定 BTR 值。  我们的代码如下所示:

    =

    canInit();

    … 有些时间过去了...

    #define FIX_CAN_1000

    #ifdef FIX_CAN_1000

    canbase_t * CNC 端口= canREG1;
    canSetSpeed (CNC 端口、1000);
    canbase_t * ncnc_ sink_port = canREG4;
    canSetSpeed (CNC_SINK_PORT、1000);
    Timer_udelay (750000);
    #endif

    =

    因此、在 CANInit()和 canSetSpeed()[使用与 Halcogen 生成的代码相同的自定义函数]之间调用、并且固定速度生效所需的3/4秒之间、CAN 总线被拧紧。  众所周知、串行通信协议是糟糕的、因为发送器和接收器端无法"协商"或"检测"正在运行的比特率。 CAN 更糟糕、因为即使接收器无法确定其运行的位速率与发送器相同、接收器也可以绕过总线上的"编号"位。  当我最初未将数据接收器 CAN4配置为右侧/固定1M bps 时、我意识到了这一点。

    因此、我需要做的实验是对 HL_CAN.c 的 Halcogen 代码生成进行后期编辑、并删除上面的 FIX_CAN_100部分。

    这个实验很好,虽然它涉及一个我能够使用(Unix/Linux)流编辑器(SED)来执行的难看的代码编辑。

    ==原始错误的 Halcogen 生成的代码

    canREG1->BTR =(uint32)((uint32) 0U << 16U)|
    (uint32)((uint32)(1U-1U)<<12U)|
    (uint32)((uint32)((8U + 1U)- 1U)<<8U)|
    (uint32)((uint32)(1U-1U)<<6U)|
    (uint32) 6U;

    =固定代码

    canREG1->BTR =(uint32)((uint32) 0U << 16U)|
    (uint32)((uint32)(5U-1U)<<12U)|
    (uint32)((uint32)((8U + 1U)- 1U)<<8U)|
    (uint32)((uint32)(4U - 1U)<<6U)|
    (uint32) 6U;
    /* fix_hlcg 脚本将 canREG1->BTR 更正为0x48c4 */

    =SED 脚本

    f=HL_CAN.c

    如果[["`grep 'fix_hlcg'$F`"="]]
    然后 sed -i -e '/CanREG1->BTR =/{
    N
    S/1U/5U/
    N
    N
    S/1U/4U/
    N
    答\
    /* fix_hlcg 脚本将 canREG1->BTR 更正为0x48c4 */
    }“$F”

    =

    底线是尝试修改 CAN 速度_after_使用某些 canSetSpeed()调用 CAN/将导致各种令人厌恶的 CAN 协议错误,包括在发送请求等待锁定中锁定控制器。  我不知道 CAN 总线交互的微小细节、因为我没有一个微 CAN 总线分析器、 但是、发送 器可能会注意到由于接收器位数错误而导致的一些灾难性故障、并会放弃、不确定重新传输(或缺少此类传输)的方式以及是否存在数据接收器。

    无论如何、我的问题是使用 fix_hlcg 脚本解决的。

    至于终止问题、在我们的其中一个 TMS570硬件设置(而不是 Launchpad)中、向 CAN1总线添加 CAN4数据接收器按预期工作正常。  但是、在我们的 TMS570 Launchpad 设置中、CAN1总线(工作中)的 CAN4加法根本不起作用。  在某种程度上、我们在这些设置上对收发器和/或终端器的不同使用之间存在一些差异、这必然会导致 Launchpad 出现严重问题。

    非常感谢。

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

    谢谢 Peter!

    对于一个给定的比特率、可能有几 个可能的设置(seg1、seg2、prop、SJW)。 建议选择允许最高振荡器容差范围的配置。 HALCOGen 可能无法选择最佳组合。  最大容差 df 由两个条件定义。

    TRM 建议 SJW 不能长于 PHASE_seg1和 PHASE_seg2。 但工作位时序参数的 SJW 大于 PHASE_SEG1:

       SJW=4、PHASE_seg2=5、PHASE_seg1=1、prog=8

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

    您好、QJ、

    非常感谢您提供此信息。  我正在与我们的硬件人员一起查看需要(或可以)做什么。

    您能否描述 SJW > Phase_Seg1的可能结果是什么?  它是否会导致更多的消息错误、如果是、是否有任何特性(例如、随着总线测试运行时间的增加、更多的错误)?

    我的数据乒乓测试确实显示了一些小百分比的掉下来的消息(这似乎是一段很长的时间内随机出现的)。  我尚未确定原因、 但 CPU 除了馈送发送器或卸载接收器之外没有做太多的工作(在112微秒以上的消息时间内需要大约5微秒的中断处理)、并且每个发送器的发送时间仅小于总线总线带宽的20%、并且没有同时传输(无冲突)。

    感谢您的任何见解。

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

    SJW (同步跳转宽度)限制允许位长度摆动的距离。  如果使用非常精确的晶体、SJW 可能会非常小。  如果使用对温度敏感的谐振器、SJW 可能会非常大。

    CAN 技术规格显示、125kb/s 波特率下的最大振荡器容差为0.158%。 如果2个节点之间的时钟差为0.158%,则 SJW > 20*0.158%* bit_time = 4*bit_time。

    SJW 不能大于 Phase_Seg2。  如果 SJW 大于 Phase_Seg2、它可能会在重新同步期间跳过帧边界并进入下一个位。

    在 CONFIG 寄存器中没有 Phase_Seg1或 Prop_Seg 的位字段。 Prop_Seg + Phase_Seg1用于 CAN 位时序设置。 在您的设置中、它是8+1。 CAN 控制器不关心它是8+1还是1+8。  

    Prop_Seg 参数来自总线长度和通过收发器的延迟。 报文必须从一个节点传输到另一个节点、"ACK"位将在为 Prop_Seg 分配的时间内返回。 例如,在1MHz 为1us/位时,如果将 Prop_Seg 设置为8/18*1us = 0.44us,则总线的长度可以为(0.44us * 300/2)= 66米。 如果电缆长度仅为6米、则1Tq 对于 Pro_Seg 来说足够大、其余(8+1)则用作 Phase_Seg1。

    因此、如果电缆长度如此长、则设置中的 SJW=4应该起作用。

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

    您好、QJ、

    我不是很确定你说什么。  当电缆长度约为66米时、您似乎会说使用了 SJW=4、但我们使用的电缆长度约为1米、而 SJW=4、运行良好、Kvaser 能够正确监控1Mbps CAN 总线并与之交互。  我不确定 Kvaser 探针实际提供的是什么、但它具有仅提供1或2选项的"SJW"设置(我们使用的是1、但不知道该设置有何不同)。

    我们的硬件人员表示、他计算出的 BTR 值只是您为他提供的实用程序。  我们对这些公式不会有太多的赞赏。

    请详细说明您对 SJW=4的关注。  我们当前的 BTR 代码如下所示。

    非常感谢。

    ===当前相关代码

    /**-设置位时序

    *-设置波特率预分频器扩展

    *-设置 TSeg2

    *-设置 TSeg1

    *-设置样本跳转宽度

    *-设置波特率预分频器

    *

    canREG1->BTR =(uint32)((uint32) 0U << 16U)|

    (uint32)((uint32)(5U-1U)<<12U)|

    (uint32)((uint32)((8U + 1U)- 1U)<<8U)|

    (uint32)((uint32)(4U - 1U)<<6U)|

    (uint32) 4U;

    /* fix_hlcg 脚本将 canREG1->BTR 更正为0x48c4 */

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

    尊敬的 Peter:

    相位缓冲段(Phase_Seg1和 Phase_Seg2)和同步跳转宽度(SJW)用于补偿振荡器容差。 相位缓冲段可以通过同步延长或缩短。

    SJW 不应大于相位缓冲段( Phase_Seg1和 Phase_Seg2)中较小的值。 在您的设置中、SJW=4、Phase_Seg2=5、 Prop_Seg + Phase_Seg1=9。  

    (SJW = 4)<(Phase_Seg2=5)  -->符合要求

    如果电缆很长,Prop_Seg 大于6,Phase_Seg1<3--> SJW > Phase_Seg1 -->不符合要求

    如果电缆较短、并且 Prop_Seg < 6、则 Phase_Seg1>=4 -> SJW <= Phase_Seg1 -->符合要求

    其中 tPROP_SEG = 2*(TBU + tTransmitter + tReceiver)、电缆上的信号速度约为5ns/m、假设  tTransmitter + tReceiver = 100ns

    如果电缆长度= 1米、则  tPROP_SEG = 2*(5+100)= 110ns、这大约是2tQ、其中 TQ = 1000ns /19 = 53ns (1000ns 是1MB 波特率的位时间)

                             tPROP_SEG = 2 < 6 -->符合要求

    如果电缆长度=10米、则  tPROP_SEG =2*(50+100)=300 ns、这大约是6tQ  

                             tPROP_SEG = 6 -> Phase_Seg1 = 9-6=3 = 4 (SJW) -->不符合要求

    希望这对您有所帮助