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.

[参考译文] CCS/TMS570LS0432:无法将整个 UART 数据包存储到字节数组中

Guru**** 2322270 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/586154/ccs-tms570ls0432-unable-to-store-entire-uart-packet-into-byte-array

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

工具/软件:Code Composer Studio

大家好、

我目前正在使用 TMS570调试我们的一款汽车电池监控器的客户问题。  电池监控器件可堆叠、并将通过 UART 将电池电压、温度等信息发送到主机 MCU (TMS570)。  由于器件具有可堆叠特性、UART 数据包可能会很长。 出于某种原因、存储 数据的阵列会填充胡胡胡说、如下所示:

这 是一个字节数组、由~425个索引点组成、但良好 数据在  第18个索引之后停止存储。 对于 较小的阵列、我以前从未遇到过此问题。 我 已验证   电池监控器实际发送的数据 是否正常(使用逻辑分析仪)、 并将问题缩小到 TMS570。 我认为 这是一个基本的东西,我设法错过了.... 我们非常感谢您在该主题上提供的任何帮助!

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

    尊敬的 David:

    从器件的角度来看、没有会导致此错误行为的已知勘误表。

    为了提供帮助、除了简单的问题陈述外、我们还需要有关应用程序的更多信息。

    如何为阵列分配空间? 它是标准声明(无符号字节数组[425])还是根据可堆叠元件的数量动态分配?

    在启动时或使用之前、阵列是否初始化为全0或其他已知值?

    Rx 在第19个元素之后停止并且您只能看到 RAM 位置的默认内容而不是损坏的接收数据吗?

    您是否看到与 UART 相关的任何错误条件/标志? 即溢出错误、奇偶校验位错误等?

    发送器和接收器的实际波特率是多少? 即、是否存在轻微的不匹配导致字节流中的容差堆叠、从而导致随时间推移而出现同步问题? 即帧错误?

    如果数据包中的字节数是可变的、那么接收器如何知道数据包何时通过? 是否有数据长度代码作为数据包的一部分发送? 接收到的数据如何与每个可堆叠元件相关联? 数据包中是否内置了任何数据保护(即 CRC 或传输冗余?)

    如果将 UART 设置为环回模式并发送相同数量的字节、是否会发生相同的问题?

    您能否确认数组不会从代码中的其他位置溢出栈定义区域或某些其他已定义的内存缓冲区存储?

    此外、您是否尝试通过在第20个接收的数据字节(第19个索引)上放置一个断点来进行调试、以查看接收到的数据字节会发生什么情况、并在移动到 RAM 阵列期间确定它是否在 Rx 缓冲区中损坏、 还是在它移动到阵列后的某个时间?

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

    你好、Chuck、

    感谢您的详细回答。 在嵌入式领域工作超出了我的专业知识领域,所以我会尽可能回答我的问题。。

    正如您所说... 它只是一个标准分配。 字节 bFrame [423]……我不相信它之前被设定为0。

    我最初的想法是 TMS570的 RX 由于某种原因而停止、正如您所提到的...我假设它在代码中的某处"更深"、我错过了一点。 我不知道为什么它适用于较短的数据包。

    在我的逻辑分析仪中、TX 看起来就在500k 左右、但 RX 是526k。  

    新手问题...在哪里可以看到这些位的状态?

    正确、数据包长度作为第一个字节的一部分发送。 如果我们有 8个电池监控器器件、它们将同步在一起并从最高电池单元开始逐1发送信息。 CRC 实际上是由电池监控器发送的。

    我不确定如何将 UART 设置为环回模式、但这是我可以检查的。

    我认为 它不会超出堆栈定义... 再次展示了我对 MCU 的不经验。 我不确定我会在哪里实际检查这个... 阵列初始化为 bFrame [512]...因此 阵列本身应有足够的空间。

    谢谢、

    David

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

    尊敬的 David:

    那么、让我一次回答一个问题:

    [引用用户="David Wiest JR">正如您所说... 它只是一个标准分配。 字节 bFrame [423]……我不相信它在之前被设置为0。

    [引用用户="David Wiest JR">我认为 它不会超出堆栈定义... 再次展示了我对 MCU 的不经验。 我不确定我会在哪里实际检查这个... 阵列初始化为 bFrame [512]...因此 阵列本身应有足够的空间。

    因此、如果您使用标准的阵列定义方法、则不应出现栈或其他阵列/数据空间过度运行的问题。 链接器将在构建时处理 RAM 利用率/管理。 不过、有一个好奇心。 您在第一句中陈述 bFrame [423]、在第二句中陈述 bFrame [512]。 这并不是说它会产生很大的影响、但它应该是固定的、以避免不必要的复杂性。

    [引用用户="David Wiest JR"]从我的逻辑分析仪上可以看到 TX 大约为500k、但 RX 为526k。

    因此、这意味着电池监控器和 MCU 的波特率差异大于5%。 这可能会导致您看到的问题。 基本上、UART 有一个基于波特率/ SCI 时钟的采样点。 当时钟不匹配时、最终会发生位移、您要么会遇到垃圾、要么会遇到 UART 错误(组帧错误或奇偶校验错误)。  

    [引用用户="David Wiest Jr"]新的问题....在哪里可以看到这些位的状态?

    有一个可被检查的错误状态寄存器。 如果您使用的是 HalCoGen 驱动程序、则有一个函数(uint32 sciRxError (sciBASE-t * sci))会返回从 SCI 中的错误状态寄存器读取的状态标志。

    [引用 user="David Wiest JR"]我不确定如何将 UART 设置为环回模式,但这是我可以检查的内容。

    同样、如果您使用的是 HalCoGen、则有一个函数可启用环回(void sciEnableLoopback (sciBASE-t * sci、loopBackType_t Loopbacktype))。 它可被用于启用数字回路(只在回路中运行数字逻辑并且不会影响引脚)或者模拟回路(摘录模拟 IO 缓冲器和数字逻辑并且将影响引脚)。 有关回路的更多信息、请参阅 TRM。 基本上、您 Tx 的任何内容都将在 Rx 端接收。

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

    卡盘、

    再次感谢您的详细回答...这对我来说是一次很好的学习体验(如果不是很明显、我在模拟世界中更舒服)

    根据您的建议、我使用了 sciRXError 函数、它返回33554432或0x02 00 00 00 00的无符号输入。 如果我正在正确读取文档、这似乎是一个溢出错误。

    那么、现在我的问题是、如何纠正这一点? TMS570是否无法处理如此大的 UART 数据包?

    编辑:要 回答 上一个问题、将 bFrame 初始化为 bFrame [512]。 仅发送423个字节(因此、423个索引点)。

    此外、为了解决此问题、我需要调整 BRS 值中的预分频器、以便 两者更接近?

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

    尊敬的 David:

    [引用 user="David Wiest Jr"]根据您的建议、我使用了 sciRXError 函数、它返回33554432或0x02 00 00 00 00的无符号输入。 如果我正在正确读取文档、这似乎是一个溢出错误。

    那么、现在我的问题是、如何纠正这一点? TMS570是否无法处理如此大的 UART 数据包?[/quot]

    因此、如果您遇到溢出错误、这意味着您在接收下一个字节之前未足够快地读取 Rx 缓冲区、从而导致数据丢失。 这可能有几种原因、但具体取决于您如何设置 SCI。 您是否使用轮询方法或中断来接收数据? 如果您使用中断、何时清除中断标志(应该是第一件事)。 我建议您尽量减少处理传入数据的时间、只需从模块中的 Rx 缓冲区移动到阵列。

    请注意、您还可以设置中断、以便在发生错误时中断、从而可以对其进行处理。 您的协议是否提供了任何重试机制? 或者至少采用 ACK/NACK 机制、以便主器件能够与从器件通信、以确认数据丢失并重试?

    [引用 USER="David Wiest JR"]编辑:要 回答 先前的问题,bFrame 被初始化为 bFrame [512]。 仅发送423个字节(因此、423个索引点)。[/引用]

    好的。 谢谢。 这只是一个需要澄清的问题。 我认为这不会影响您的问题。

    [引用 user="David Wiest Jr"]为解决此问题,我需要调整 BRS 值中的预分频器,以便 两者更接近?

    如果您遇到溢出错误、而不是帧或奇偶校验错误、这很可能不是您的问题。 但是、最好查看您是否可以使波特率尽可能更接近对齐、但同时对预分频器进行高频处理。 如果由于工作频率的原因、您无法使其接近、则不要太担心它、并将其缩小为粒度问题。

    另一个问题、在收到的问题中、是否已验证数据是否准确? 即、在收集接收到的数据时、是否存在任何缺失的字节? 我很好奇、因为这可以告诉我们溢出问题的严重程度。 即、如果接收到的19个字节代表与数据包的字节0相对应的第一个字节、而字节18代表423字节数据包的最后一个字节、 然后、您在中间丢失了大量数据、并且代码存在严重的软件架构问题。

    最后、在您的系统中发送数据包的频率如何? 即、传输之间数据包的实际处理时间是多少? 同样、这也是处理 SCI Rx 缓冲器中接收到的数据的问题、如果有足够的时间在接收到下一个字节之前检索数据并将其移动到数组。

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

    我们使用的是中断、特别是 sci.c.中的 sciReceive 函数。

    以下是 sciReceive 函数(抱歉、如果格式错误、可能会有所帮助):

    void sciReceive (sciBASE-t * sci、uint32 length、uint8 * data)


    /*用户代码开始(17)*/
    /*用户代码结束*/

    if ((sci->SETINT & SCI_RX_INT)=SCI_RX_INT)

    /*我们处于中断模式*/

    /*清除错误标志*/
    SCI->FLR =(((uint32) SCI_FE_INT |(uint32) SCI_OE_INT |(uint32) SCI_PE_INT);

    G_sciTransfer_t.Rx_length =长度;
    /*SAFETYMCUSW 45 D MR:21.1 "仅此驱动程序允许有效的非 NULL 输入参数"*/
    G_sciTransfer_t.Rx_data =数据;

    其他

    /*SAFETYMCUSW 30 S MR:12.2、12.3 "用于发送/接收轮询和中断模式下的数据计数"*/
    while ((length--)>0U)

    /*SAFETYMCUSW 28 D MR:NA "找到可能无限的循环-执行序列的硬件状态检查"*/
    while (((sci->FLR & SCI_RX_INT)== 0U)

    }/*等待*/
    /*SAFETYMCUSW 45 D MR:21.1 "仅此驱动程序允许有效的非 NULL 输入参数"*/
    *data =(uint8)(sci->RD & 0x000000FFU);
    /*SAFETYMCUSW 45 D MR:21.1 "仅此驱动程序允许有效的非 NULL 输入参数"*/
    *DATA++;


    /*用户代码开始(18)*/
    /*用户代码结束*/


    我认为这是相当标准的、是由 HAlCoGen 生成的。 最后、我们使用"等待响应帧"函数、如下所示:

    int WaitRespFrame (字节*pFrame、UINT32 bLen、UINT32 dwTimeOut)

    uint16 wCRC = 0、wCRC16;
    字节 bBuf[512];
    uint32 bRxDataLen;

    memset (bBuf、0、sizeof (bBuf));

    sciEnableNotification (scilinREG、SCI_RX_INT);
    rtiDisableNotification (rtiNOTIFICATION_COMPARE0);
    rtiDisableNotification (rtiNOTIFICATION_COMPARE1);
    rtiDisableNotification (rtiNOTIFICATION_COMPARE2);
    rtiDisableNotification (rtiNOTIFICATION_COMPARE3);
    rtiInit();
    rtiEnableNotification (rtiNOTIFICATION_COMPARE1);
    /* rtiNOTIFICATION_COMPARE0 = 1ms
    * rtiNOTIFICATION_COMPARE1 = 5ms
    * rtiNOTIFICATION_COMPARE2 = 10ms
    * rtiNOTIFICATION_COMPARE3 = 15ms
    *
    rtiResetCounter (rtiCOUNTER_BLOCK0);
    rtiStartCounter (rtiCOUNTER_BLOCK0);
    sciReceive (scilinREG、bLen、bBuf);

    while (UART_RX_RDY = 0U)

    //检查超时。
    if (RTI_TIMEOUT == 1U)

    rtiStopCounter (rtiCOUNTER_BLOCK0);
    rtiDisableNotification (rtiNOTIFICATION_COMPARE0);
    rtiDisableNotification (rtiNOTIFICATION_COMPARE1);
    rtiDisableNotification (rtiNOTIFICATION_COMPARE2);
    rtiDisableNotification (rtiNOTIFICATION_COMPARE3);
    RTI_TIMEOUT = 0;

    返回0;//超时

    }/*等待*/
    rtiStopCounter (rtiCOUNTER_BLOCK0);
    rtiDisableNotification (rtiNOTIFICATION_COMPARE0);
    rtiDisableNotification (rtiNOTIFICATION_COMPARE1);
    rtiDisableNotification (rtiNOTIFICATION_COMPARE2);
    rtiDisableNotification (rtiNOTIFICATION_COMPARE3);
    UART_RX_RDY = 0;
    RTI_TIMEOUT = 0;
    bRxDataLen = bBuf[0];

    delayms (dwTimeOut);

    //重建 bBuf 以使 bLen 成为第一个字节、从而使用与 TX 相同的 CRC 函数
    //i = bRxDataLen + 3;
    //while (--i >=0)
    //{
    //bBuf[i + 1]= bBuf[i];
    //}
    //bBuf[0]= bRxDataLen;

    wCRC = bBuf[bRxDataLen+2];
    wCRC |=((uint16) bBuf[bRxDataLen+3]<< 8);
    wCRC16 = CRC16 (bBuf、bRxDataLen+2);
    if (wCRC!= wCRC16)
    返回-1;

    memcpy (pFrame、bBuf、bRxDataLen + 4);

    返回 bRxDataLen + 1;



    关于数据完整性、我验证了进入数组的前18个字节实际上是进入数据包的前18个字节。 我的逻辑分析仪显示它的字节与字节匹配、一直到那个神奇的第18个字节...。

    数据包之间有几毫秒的时间。 我认为这是 MCU 工作的充足时间。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢 David、

    上面的 sciReceievie 函数能够在中断模式或非中断模式(轮询)下使用。 第一个条件是检查是否处于中断模式、如果是、则它只将一个字节传输到 g_sciTransfer_t.Rx_data。 然后由更高的函数将数据从 g_sciTransfer_t.Rx_data 结构移动到缓冲区数组、并管理数据包的数据长度。

    在函数的备用部分(在检查是否处于中断模式后的 Else 部分)、它使用传递的长度参数对数据进行 pol 处理、直到接收到整个数据包并将其作为参数放入传入的数据缓冲区。 但是,此代码中有一个与我相关的检查,即它等待接收标志被置位(新数据可用)或错误标志被置位(while (((sci->FLR & SCI_RX_INT)=0U))。 如果我们认为错误标志被置位、那么数据仍会从接收缓冲器中读取到数据缓冲器中、缓冲器指针会递增、然后等待下一个字节。 因此、如果存在最初推测的同步问题、导致帧或奇偶校验错误、您基本上会将垃圾加载到数据数组中并继续。

    我也不认为波特率不匹配也是造成这个问题的原因、但是如果你可以将从器件的波特率调整到接近500kbps、那么这个问题就可以解决了。 我检查了 MCU、如果您在分频器中每改变1个计数、则最好选择500k
    将分频器调整~56kbs。 即、您可以最好地完成它500 +/-56。

    诚然、您的等待响应帧函数和 RTI 函数的使用让我有点困惑。 我看到您在这个等待响应帧函数内调用 sciReceive 函数并将其传递一个长度为 bLen 的长度、该长度将决定要接收的字节数。 此参数将传递到等待响应帧函数中。 然而、当你将 bBuf 数组复制到 pFrame (不确定这个新缓冲区是什么)时、你使用从 bBuf[0]分配的 bRxDataLen 中的值。 这可能导致由 bLen 指定的字节数量与数据包本身指定的字节数量(bBuf[0]或 bRxDataLen)之间不一致。

    如果启用了 RTI 中断、这些中断的 ISR 可能会阻止 sciReceive 函数的执行、因为它不是中断。 这也可能导致溢出错误。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    卡盘、

    感谢您与我保持联系... 到目前为止、这绝对是一个学习体验、希望它能在将来帮助其他人。

    我已将电池监控器波特率更改为250k、并已使用 sciSet波特 率函数将250000写入 TMS570。 现在、我的分析器显示两种器都能以252525 Hz 的频率愉快地工作。

    我与更熟悉代码的人交谈过、RTI 函数旨在作为超时、以防收到的字节数与请求的字节数不匹配。 我已将这些内容注释掉、并在 sys_vim.c 中将其替换为幻象中断 不幸的是、我的问题在两个更改后仍然存在...

    RTI 中断实际上是我所怀疑的...我还应该做些什么来确保这些中断被禁用吗? 如果我正确地记住、需要在 sys_vim.c 之外的其他位置启用中断

    LinHighLevelInterrupt 也会在 Sys_VIM.c 的通道13上设置。。。。。我认为这是将 SCI RX 中断设置为高优先级、对吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    David、

    您能否将您的项目发送给我、以便我可以在这里尝试一下? 具体而言、请同时包含您的 Halcogen 文件(HCG 和 DIL 文件)以及您使用的是什么版本的 Halcogen。

    我对中断很好奇、因为您提到的 LinHighLevelInterrupt 是用于 LIN 而不是用于 SCI 的。 我怀疑您没有真正使用您认为的中断、因为您正在手动调用通知函数、需要将其定义为 ISR、以便它们作为 ISR 正常工作。

    无论如何、如果您可以将其压缩并通过附加到此主题帖发送、或者通过 TI 电子邮件直接将其发送给我、那就行了。