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.

[参考译文] TM4C129XNCZAD:使用优化时出现硬件CRC错误

Guru**** 2391835 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1083956/tm4c129xnczad-hardware-crc-error-when-using-optimizations

部件号:TM4C129XNCZAD

您好,

我们最近遇到了与使用硬件CRC相关的意外问题。

我们的代码非常简单,经过测试,没有任何问题....

	// Write the control register with the configuration
	M_HWPRegister(CCM0_BASE, CCM_O_CRCCTRL) = (CRC_CFG_INIT_1 |
	                                           CRC_CFG_SIZE_8BIT |
	                                           CRC_CFG_TYPE_P1021);

	// Feed the CRC module with data
	while (length-- != 0u)
	{
		M_HWPRegister(CCM0_BASE, CCM_O_CRCDIN) = *bytes++;
	}

	// Return post processed value
	return M_HWPRegister(CCM0_BASE, CCM_O_CRCRSLTPP);

....直到我们应用-O2优化。

应用-O2优化后,我们会检查汇编代码是否正确,但在运行代码时和在汇编中逐步进行时,计算出的CRC是不同的。

经过进一步调查后,在逐步执行时CRC是正确的,但在运行代码时,返回的CRC是阵列长度-1第一个字节中的一个,在本例中,当停止处理器时,CCM0模块寄存器中包含正确的CRC, 与函数返回的内容相反。

引用数据表中的内容:

"CRC在一个时钟中组合计算。"
"由于CRC计算是单个周期,一旦数据写入CRC数据输入(CRCDIN)寄存器,CRC/CSUM的结果将在CRC种子/上下文(CRCSEED)寄存器中更新,偏移0x410。"

这是否不正确? 读取 CRC后处理结果(CRCRSLTPP)寄存器时是否存在未记录的计时? CRC计算如何能进行一个周期而不是XOR或位反转?

我们在最后写入的字节和后处理结果的读取之间添加了一个NOP指令,它似乎起作用。 但是,由于我们在一家医疗设备公司工作,这是一个不可接受的修补程序,但没有提供任何其他信息来证明其合理性。

此致,

Matthieu Tardivon

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

    您好 ,Matthieu,

     阅读CRC模块操作的数据表,我不确定为什么不从CRCSEED寄存器读取CRC校验和。 在您的初始化过程中,我没有看到您选择任何 后处理功能。 您只能选择CRC_CFG_INIT_1 | CRC_CFG_SIZE _8位|CRC_CFG_TYPE_P1021。 如果您阅读的是CRCSEED注册而不是CRCRCRSLTPP,该怎么办? 您是否看到正确的校验和结果或它是否也受到-o2优化的影响?

    12.2 1 CRC初始化和配置
    CRC引擎在推送模式下工作,这意味着它可以处理流数据。 本节
    介绍了初始化CRC模块的步骤:


    1.通过在CRC模块(RCCGCCM)寄存器系统控制中设置R0位来启用CRC
    偏移0x674。


    2.配置所需的CRC数据大小,位顺序,端点配置和CRC类型
    编程CRC控制(CRCCTRL)寄存器,偏移0x400。


    3.如果尚未使用CRCCTRL中的INIT字段将CRC值初始化为全部0或全部1
    在CRC种子/上下文(CRCSEED)寄存器中注册初始值,偏移0x410。


    4.在CRC数据输入(CRCDIN)寄存器中重复写入数据字段,偏移0x414。 如果
    CRCCTRL寄存器中的大小位设置为SELECT字节,CRC引擎以字节为单位运行
    模式,并且只有最低有效字节用于CRC计算。


    5.完成CRC后,阅读CRCSEED注册表以获得最终结果。 如果使用后处理,
    原始CRC结果存储在CRCSEED寄存器中,最终的后处理结果CAN中
    从CRC后处理结果(CRCRSLTPP)寄存器读取,偏移0x418。
    后处理选项可通过CRCCTRL寄存器的OBR和OLNV位进行选择

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    这是否不正确? 读取 CRC后处理结果(CRCRSLTPP)寄存器时是否存在未记录的计时? CRC计算如何能用一个周期而不是XOR或位反向?[/QUOT][QUOTE userid="25.857万" url="~/support/pmspectors/arm-based mspectors/group/arm-based -byte/f/arm-based -forum-forum/108.3956万/tm4c129xnczad-hardware-crc-error-mspectors"我们在微控制器和NOP之间添加了最后一个工作后处理优化结果后添加了优化。 [/引述]

     我无法查看CRC模块的实际电路。 计算出的校验和可能先存储到CRCSEED寄存器,然后在将后处理数据捕获到 CRCRSLTPP寄存器之前进行后处理。 这可能导致CRCSEED和CRCRSLTPP之间的一个周期差。  我不是编译器专家。 我认为-o2可以改变顺序。 实施NOP是正确的做法。

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

    我尝试 用 CCM_O_CRCSEED替换CCM_O_CRCRSLTPP,并观察到相同的行为。 因此,这建议使用多个时钟周期来执行与数据表中所述相反的操作。 您能在您身边检查一下吗? 在读取寄存器中的正确值之前,我们必须知道读取时间是如何的,这一点很重要。

    此外,我们检查后处理寄存器而不是种子寄存器的原因是为了有一个更好的可移植代码,这样,如果我们决定更改控制寄存器中的配置,其余的计算将保持不变。

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

    您好,

     我认为CRC计算校验和不需要多个周期。 看起来,优化器似乎正在重新排列读取顺序。 您能否显示汇编代码?

     另请参阅下面有关内存障碍的文章。 如上所述,Cortex-M4F基于Armv7E-M架构,允许处理器进行顺序外存储器操作。 就处理器而言,写入CRCDIN和从CRCRCRSLTPP读取是两种不同的内存传输。 读取不取决于要完成的写入。  在我看来,添加记忆障碍指令或类似您对NOP所做的操作是正确的补救措施。 另请尝试声明变量volatile。  

    https://www.sciencedirect.com/topics/engineering/memory-barrier-instruction

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

    您好,

    注册表访问权限已声明为易失性:

    //! \brief Access a peripheral hardware register
    #define M_HWPRegister(peripheral, reg)     (*(reinterpret_cast<volatile uint32*>(static_cast<uint32>(peripheral) + static_cast<uint32>(reg))))

    代码未重新排列,说明按正确的顺序执行,您可以在下面的屏幕截图中查看。 您甚至可以注意到,在STR至CRCDIN寄存器和LDR至CRCSEED寄存器之间执行BNE指令。 由于在BNE和LDR指令之间添加NOP指令似乎可以解决问题,DSB指令 很可能会更好地工作,但这与数据表中提到的内容仍有矛盾:

    要正确解决问题,首先需要了解问题,这就是为什么我们希望得到合理的硬件解释,以确保执行正确的修复。

    此致,

    Matthieu Tardivon

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

    您好,Matthieu,

     正如我在刚才的答复中所说,由于设计是在相当一段时间前完成的,所以我不能看到设计的情况。 话虽如此,我看了TivaWare API CRCDataProcesses()如何返回处理过的数据,很明显,它最后调用了CRCResultRead()。 通过调用 CRCResultRead,它 显然会引入延迟,其效果与NOP相似。 可能是在API开发过程中故意执行的,当他们遇到您所面临的相同问题时,就会进行另一个函数调用来延迟校验和的读取。  我认为,如果您使用TivaWare读出数据,您不会遇到问题。 您是否可以尝试使用TivaWare? 如果您仍想保留自己的代码(DRM样式),添加NOP是正确的做法。

     

    uint32_t
    CRCDataProcess(uint32_t ui32Base, uint32_t *pui32DataIn,
                   uint32_t ui32DataLength, bool bPPResult)
    {
        uint8_t *pui8DataIn;
    
        //
        // Check the arguments.
        //
        ASSERT(ui32Base == CCM0_BASE);
    
        //
        // See if the CRC is operating in 8-bit or 32-bit mode.
        //
        if(HWREG(ui32Base + CCM_O_CRCCTRL) & CCM_CRCCTRL_SIZE)
        {
            //
            // The CRC is operating in 8-bit mode, so create an 8-bit pointer to
            // the data.
            //
            pui8DataIn = (uint8_t *)pui32DataIn;
    
            //
            // Loop through the input data.
            //
            while(ui32DataLength--)
            {
                //
                // Write the next data byte.
                //
                HWREG(ui32Base + CCM_O_CRCDIN) = *pui8DataIn++;
            }
        }
        else
        {
            //
            // The CRC is operating in 32-bit mode, so loop through the input data.
            //
            while(ui32DataLength--)
            {
                //
                // Write the next data word.
                //
                HWREG(ui32Base + CCM_O_CRCDIN) = *pui32DataIn++;
            }
        }
    
        //
        // Return the result.
        //
        return(CRCResultRead(ui32Base, bPPResult));

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

    您好,

    很抱歉,我对你的回答感到很失望。 这是我第一次收到这样一个含糊的答案,他在制造MCU的公司工作。

    "由于设计是在相当一段时间前完成的,我无法查看设计"
    您在公司工作,如果您不在公司工作,谁在工作? 我一直在处理您的产品,并与您讨论一段时间,这是我第一次动摇信心。

    "也许是在API开发过程中有意做到的"
    我在一家医疗设备公司工作,"也许"是不能接受的。 我们的发展必须在坚实的基础上进行,我们需要数据才能正确,专业地完成工作。

    "如果您仍想保留自己的代码(DRM样式),添加NOP是正确的做法"
    实际上不是,在进行一些调查并修改我的代码以 获得最少的汇编指令后,这不是正确的做法:

    此操作失败:

    它的作用是:

    结论,添加DSB指令似乎是正确的做法。 至少通过此测试,当我尽量减少指令数量时,应该足以证明我们文档中的变通办法是正确的。 但是,这再次证明,假设不足以解决问题,我希望TI能够做到专业,能够执行清晰的硬件分析并提供文档更新,从而准确地指定正确的操作。

    此致,
    Matthieu Tardivon

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

    您好,Matthieu,

     很抱歉,我无法提供您正在寻找的答案。 这款MCU的芯片设计 是近10年前完成的。 芯片的设计数据库库已在磁带存档中。 即使可以检索设计数据库,我也不确定打开和模拟数据库的障碍是什么,因为EDA工具在10年的时间内会发生变化。 最后,我是一名应用工程师,在过去几年中选择了此MCU支持,现在已经没有具备此MCU相关知识的设计工程师可以模拟数据库。 我知道您可能不会接受我的答案,但很遗憾,这是我能给出的最好解释。   

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

    您好,Matthieu,

    "我402.1163万我很久以前还没有对设计进行过任何了解,因为设计已经完成了"
    您在公司工作,如果您不在公司工作,谁在工作? 我与您的产品合作并与您讨论了一段时间,这是我第一次动摇信心。[/QUOT]

    查尔斯所说的关于这些设计存档的事实是这里不幸的事实。 在这样的时候,我们也感到沮丧,因为我们希望能够为这样的问题提供更好的答案。 我可以清楚地理解您的顾虑。

    "可能402.1163万可能是在API开发过程中有意完成的"
    我在一家医疗设备公司工作,"也许"是不能接受的。 我们的发展必须在坚实的基础上完成,我们需要数据才能正确和专业地完成工作。[/QUOT]

    让我们在这里将其分为两个方面。

    方面1:TivaWare API设计的意图

    我们不能肯定为什么要编写TivaWare API来在返回声明中进行额外的TivaWare API调用,但这显然与传统上处理TivaWare的方式不同。 因此,我们怀疑但无法确认这是为了避免您遇到的问题而进行的有意调整。 因此,「也许」的说法纯粹是关于过去的发展。

    第2方面:当前的问题和TivaWare API的功能

    您所介绍的是我们独有的案例。 我们之前没有关于这种行为的问题,使用TivaWare API的人也没有遇到过这种问题。

    我们所看到的问题似乎源于您在DRM级别开发自己的代码的方式。 因此,您所采取的步骤与我们的TivaWare API所采取的步骤不匹配可能会带来此问题,除非您(不太可能)是过去5年多来唯一使用此功能的客户。

    根据您在各种测试中获得的结果,很显然,需要额外的周期来更新CRC数据。 是的,这与数据表有所不同,但现在所有证据都表明,额外周期是获取数据的必要条件。

    我确实有意说'循环',因为很明显,单个NOP是不够的。 所使用的TivaWare API调用引入了多个周期,因此单个NOP不能完全复制使用久经考验的API所发生的情况。 DSB指令运行得更好,因为它有可能等待更多的周期,而不仅仅是一个周期。

    您还应该测试使用三到五个NOP。 我对久经考验的TivaWare API进行了组装分解,它在BNE和LDR指令之间至少增加了5个额外周期。 不清楚的是,DSB始终引入足够延迟的可靠性如何-如果您想使用它,请确保验证。 否则,我建议确保延迟超过1个周期。 至少五  个周期已通过TivaWare API证明有效,但我强烈怀疑,根据我多年的经验和您的评估结果,三个周期是足够的。 您当然可以测试DSB甚至两个NOP的稳健性,但我的官方建议是至少三个周期的延迟,并验证它是否正常向前发展。

    要回到您对本建议充满信心的话题...

    当查看TivaWare API时:

    1. 增加额外的周期
    2. 与 其他API的设计不同,它引入额外周期的方式
    3. 未报告有问题

    此外,您提供的数据表明,添加周期可在装配体级别工作,作为设备专家,您可以清楚地了解数据表中有关'soon s'语句的信息不正确,您需要引入额外的周期以确保获得结果。  

    虽然我们无法访问设计 来验证这一点,但我不会说这是您可能需要更多周期的原因。 非常明显,它是必需的,并且与基于您所做的详细调查的数据表不匹配。 因此,我们基于对设备的了解而提出的技术建议是:

    1. 如果可能,请使用久经考验的TivaWare API。
    2. 如果不是,请确保在BNE和 LDR之间添加至少三个周期 ,以使结果显示在CRC种子/上下文寄存器中,并验证该调整。 要复制TivaWare API延迟,至少需要五个周期的延迟。

    我知道这与在设计层面上进行验证的确定性不同,但我的目的是通过这一附加解释,让您对建议的解决方案更有信心。

    此致,
    Ralph Jacobi

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

    您好,Ralph,

    感谢您的详细回答。 如果您无法在运行中的服务器上访问任何最新设计的实时版本来完成您的工作, 这是一个遗憾,我希望您的管理层将来会考虑这件事,以便最终使您的团队和客户受益

    关于技术细节,我想CRC HW计算是通过结合多种方式完成的,主要是异步门和一级同步门/翻转,这将解释数据表中的“单周期”和“在一个时钟中组合计算”语句。 因此,限制来自Charles链接中的陈述:"但是,由于处理器具有写入缓冲区(如6.9 部分中所述 ),需要多个时钟周期的数据写入可能与后续操作的执行并行进行。" 这也是为什么我认为使用DSB指令可能是最可靠的解决方案,我们将坚持使用,因为它应该易于测试。 如果我们再次遇到一些类似问题,我们将按照您的建议行事,如TivaWare,并添加NOP说明。

    此致,
    Matthieu Tardivon