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/TMS320F2808:SPI 寄存器 RXFIFO 和 TXFIFO 问题

Guru**** 2522770 points
Other Parts Discussed in Thread: TMS320F2808, TMS570LS3137, C2000WARE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/748362/ccs-tms320f2808-spi-register-rxfifo-and-txfifo-problems

器件型号:TMS320F2808
主题中讨论的其他器件: TMS570LS3137C2000WARE

工具/软件:Code Composer Studio

大家好、

我的这一问题与我本月提出的问题有关。 我的问题是:

例如、我将3x1 uint16矢量从 Arduino (Master)发送到 TMS320F2808 (Slave)、数据接收没有问题、因为在 SPIRXBUF 上我看到了正确的数据、但由于我使用 FIFO、RXFFOVF 位始终为1、 这意味着即使我连续发送少于3个字、FIFO 也会接收多于16个字。 此外、我只需将这个3x1矢量乘以从器件侧的一个常数、然后将其发送回主器件。 第二个问题是:即使我向主器件发送3个字、在 FIFO 缓冲区中、我也会看到发送 FIFO 分别包含16个字和13个字并重复出现。 我不知道为什么会发生这种情况。 我愿意提供任何帮助。  

谢谢。

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

    是否反复发送相同的数据? 您是否曾看到数据损坏?
    传输后、您能否在 CCS 中发送 SPI 寄存器视图的屏幕截图?
    您是否复位/清除过 RXFFOVF 标志或 FIFO? FIFO 计数器是否以13/16结束?

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

    -是的,我不断地发送相同的数据。 我不时会看到数据损坏。 它有时会损坏、有时不会损坏、但会定期发生数据移位。 我的意思是、如果发生损坏、则发送0xAA、0xFF。

    -否、我不会重置/清除 RXFFOVF 标志、因为我从 Simulink 模型生成此操作的代码。 据我所知、我没有权限重置该标志。 我通过不断关注 CCS 中的 SPIA 寄存器来了解 FIFO 寄存器。

    这是一个传输后的 SPIA 寄存器。 可以看到、RXFFOVF 位(SPIFFRX.15)连续为1。 我只需发送[25 26 27] 3x1矢量并发回[50 51 52] 3x1。 我一直在寄存器中看到向量的最后一个元素。

    我忘了说、如果我将 NX1矢量从主器件发送到从器件并对其执行一些操作、它会像移位一样发回。 例如、[1 2 3 4]作为[4 1 2 3]发回。 我还注意到、当发生这种情况时、RXFFOVF 位为1、当我在数据表中阅读它的解释时、它说如果该位为1、则接收到的第一个字将丢失。

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

    我仍在赶上漫长的周末、感谢您的耐心。

    您的所有代码都是从 MATLAB/Simulink 模型生成的吗? 您能否实现 Simulink 代码或将其导出到 CCS 项目、以便测试 SPI 配置代码? 如果您能够将 SPI 代码导出到 CCS 项目中、您将能够直接使代码混乱。 它将帮助您更好地了解这里发生的情况。

    我想您可以通过 Simulink 访问 RXFFOVFCLR 位。 如果没有、我强烈建议联系 Matlab 支持以包含此功能。

    您告诉我的是您遇到了溢出。 这不是随机发生的。 您能否将 RX 中断级别设置为小于16个字? 尝试将其设置为8个字。 在到达 FIFO 的完整深度之前中断。

    我在键入此内容时曾考虑过的另一个问题:由于 F2808是从器件、因此您可以在启用中断之前很早地启用 SPI 模块。 即 SPI 已启用、但中断未启用。 仅在4个字的突发后、您就会面临溢出的风险。 请检查您的节目时间。 在与 SPI 初始化相关的代码中的不同检查点添加 GPIO 切换。 绘制 GPIO 与主数据传输的范围图。


    -Mark
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    -是的、我的所有代码都是从 Simulink 模型生成的。 我在 CCS 中以项目的形式实现了我的代码。 "SPI 配置代码"是什么意思? 您说的是哪个部分? 我相信、我也在使用它一段时间、但我还没有找到特定的解决方案。 我需要一些指导。

    -不,很遗憾,我无法通过 Simulink 访问该位。

    -好的、我将设置它并重试、但我认为它不会改变事情。

    -如何检查程序计时? 从哪里开始? 您能举个例子说明如何执行这些操作以及如何添加 GPIO 切换功能吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    1.我指的是配置 SPI 控制寄存器的代码。

    2.我建议将此文件作为错误/功能请求提交给 Matlab / Simulink 团队。 似乎应该包括故障检查和恢复。

    3.看起来您一般都不熟悉 C2000和 MCU 编程。

    我建议阅读 SPI 用户指南 http://www.ti.com/lit/sprug72
    运行以下任一 SPI 示例程序: http://www.ti.com/tool/sprc191 
    并查看 F2808技术讲座材料: http://processors.wiki.ti.com/index.php/C2000_Archived_Workshops#F2808_Workshops 

    通过 GPIO 切换调试、我指的是简单地使用备用 GPIO 并在初始化代码中的特定事件时将其从1切换为0。 您可以执行不同的切换模式或脉冲宽度来指示系统中的不同事件。 观察 GPIO 以及传入的 SPI 消息、以确定事件的顺序。

    -Mark

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

    在上一篇文章中、您提到了启用 SPI 模块和中断。 在本例中、您指的是哪个中断?

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

    Mark、

    您可以在 LinkedIn 上添加我吗? 我已经向您发送了一个请求。 我想从那里与您讨论它。

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

    很抱歉、我宁愿在这里保留所有与支持相关的问题。 这对可能提出同样问题的每个人都是有益的。

    我指的是 SPI RX 中断。 如果在启用 SPI 模块和启用中断之间接收到超过4个4字的突发、则存在溢出风险。 我不知道您的初始化方案或程序的运行顺序、因此这只是我对可能发生的情况的专业看法。

    -什么是 SPI 主器件?
    -在启用 F2808 SPI 从器件之前、主器件是否开始发送?
    -主器件是否有可能在启用 SPI 模块和启用 SPI 中断并首次提供服务之间传输4个突发的4个字? 使用 GPIO 切换调试方法和示波器确实可以帮助您回答这个问题。
    考虑将应用程序代码分解为基本代码。 创建一个简单的 SPI 从器件代码、该代码可以适当地接收和处理主器件数据。然后缓慢地添加到您的其余应用程序代码中。

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

    我有一个用于 SPI 模块的未使用 SPI RX 中断。 我一直运行的代码如下所示:

    我们需要看到的是第一    个 C2000_flash_init()和 init_board()函数被调用。 然后运行模型的初始化、步进和终止函数。 然后、我有一个模型、它接收来自主器件的内容、对其进行一些数学运算并将其发回主器件。 在此阶段、从它生成的代码实际上不会对我们有所帮助、因此我不会共享它。 我想和  大家分享 init_board()函数,也许它会帮助您更好地理解问题。

    此外、 init_gpio  和  init_spi_a  函数如下:

    在这些代码之后、我们的 Simulink 模型开始重复运行。

    我们的 SPI 主器件是 TMS570LS3137。

    -实际上我不知道。 主器件和从器件均与 CCS 分开运行。

    -可能会出现这样的问题,我不确定。 在共享我的代码后、您能不能给出在源代码中使用 GPIO 切换调试方法的位置。 接收中断? 或者在哪里?

    最后,我们目前的情况如下:

    1-当主器件向从器件发送向量时、从器件对其执行一些数学计算(此时不执行任何操作)并发送回主器件。 此时、在一开始、从器件向主器件发送16个字的虚拟数据。 然后、从器件处理的数据被发送到主器件。 此外、主器件接收到的数据被移位1个字。 示例:

    MASTER->[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]

    主器件发送此消息。 同时、从器件发送数据

    从器件->[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0](SPI 接收块的初始条件为0、可能已发送。)

    然后、操作数据以以下方式发送:

    从机->[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]

    下一个主器件样片:

    MASTER->[21 22 23 24 25 26 27 28 29 30 31 33 34 35 36]

    下一个从器件样片:

    Slave->[16 21 22 23 24 25 26 27 28 29 30 31 32 34 35]

    可以看到、SOMI 上第二个采样的第一个字是 MOSI 上第一个采样的最后一个字。 希望这澄清了情况。

    2 -当从器件向主器件发送任何内容而不管其接收到什么内容时、头16个字(1字=16位)将不会有任何延迟或移位。 接下来的16个字开始移位。 有时、它会发送相同的字两次、三次等 例如、从器件发送的内容与[10 11 12 13 14 15 16 17]类似。 其原理如下:

    [10 11 12 13 14 15 16 17]

    [10 11 12 13 14 15 16 17]

    [17 10 11 12 13 14 15 16]

    [10 10 11 12 13 14 15 15]

    等等

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

    [Çevikalp Sütunç 用户="k Ω"-实际上我不确定。 主器件和从器件均与 CCS 分开运行。[/quot]

    您能否尝试在主器件发送的每个字之后放置一个断点(该断点应在主 MCU 上)、让从器件自由运行。 本质上、由于没有 SPI 时钟、从器件将不会进行进度并自行发送数据。 观察从器件的状态。 它是否收到了这个词? 它是否按预期换用了它? TXBUF 中是否按预期分阶段/加载了正确的字?

    [Çevikalp Sütunç 用户="k Ω"-可能会出现这样的问题、我不确定。 在共享我的代码后、您能不能给出在源代码中使用 GPIO 切换调试方法的位置。 接收中断? 或何处?[/报价]
    您可以将 GPIO 切换代码置于任意位置。 有用的位置包括闪存初始化之前、电路板初始化开始时、PLL 初始化之后、SPI GPIO 初始化之后和 SPI 初始化之后、以及 SPI 接收函数开始和结束时。 与主发送数据相比、这些功能可让您了解代码的实时位置。

    [Çevikalp Sütunç user="k Ω]从图中可以看出、SOMI 上第二个样本的第一个字是 MOSI 上第一个样本的最后一个字。 希望这能澄清这种情况。[/引述]
    这是有道理的。 无论从器件将传输缓冲器中的任何内容、都是如此。 如果您尝试执行单字环回、您将看到主控方接收到的数据被移一。 (c2000ware/code 示例中的 SPI 环回示例)  

    [Çevikalp Sütunç 用户="μ"] 当从器件向主器件发送某些内容而不管其接收到什么内容时,将不会有任何延迟或移位地发送前16个字(1个字=16位)。 接下来的16个字开始移位。 有时、它会发送相同的字两次、三次等[/引述]
    在我看来、您好像在尝试替换主器件实时发送的数据。 从本质上讲、它将始终是一个词。 您尚未显示数据的任何范围捕获。

    • 16位字之间是否有任何时间间隔、以便从器件有时间抓取 RX 缓冲区中的内容、对其进行处理(或不对其进行处理)、然后在主器件开始下一个字之前将其放置在 TX 缓冲区中?   
    • 请仅分享代码片段、您的从器件将在其中处理接收到的数据并替换要传输的数据。

    我想我们正处于您需要将问题分解为最简单的阶段。 在您了解前一步骤的工作原理之前、请勿转到下一个部分。  

    1. 从简单的1主 器件到1从器件、将16个字发送到未修改的主器件。 -请注意,接收到的字从从器件移1。  
    2. 通过添加消息操作来增加复杂性。
    3. 通过添加其他应用程序代码增加复杂性。

    我所建议的一切实际上只是基本的调试技能-将问题分解为重要的部分、并对我们所做的工作进行细致的处理。 在进行任何测试之前、我们考虑该测试如果正常工作、应如何运行。 如果它不能按预期工作、您可以更深入地挖掘。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    供参考。 我将线程混在一起并编辑了这篇文章、删除了有关多个从器件的注释、因为我正在处理两个相当相似的线程。 很抱歉造成混淆
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    -没有,16位字之间没有时间。

    这是 SPI 接收部分:

    SPI 发送:

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

    您好!

    我认为我的 SPI 字之间的时间问题是错误的(我的线程混乱)、我应该问: 16字突发之间是否有时间?  

    您似乎没有使用中断、这是可以的、 但我不确定您是否有执行 TX 和 RX 代码的时间下调。如果您查看接收代码、请等到 FIFO 已满(或溢出)读取接收到的数据。 考虑进行小于16个字的多次读取(2次读取8个字、4次读取4个字、8次读取2个字、以及一次总突发计数、以确保您收到16个字。

    此外、查看之前共享的 SPI FIFO 使能代码、您无法正确启用 SPI TX FIFO 或 SPI RX FIFO 增强功能。 您的 SPI 初始 化代码不会触摸接收 FIFO 使能位。 请参阅头文件示例中提供的 SPI_loopback 示例。 它显示了一个简单的主器件回送示例、但 SPI 配置为接收16个字的 FIFO、并对 SPIRXFFST 位进行轮询、以确保您仅读取 FIFO 中接收到的内容。 您还可以查看 SPI_loopback_interrupts 示例、了解如何将 SPI 与中断配合使用。

    -Mark

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

    -您似乎没有使用中断、这是可以的、 但我不确定您是否有执行 TX 和 RX 代码的时间下调。如果您查看接收代码、请等到 FIFO 已满(或溢出)读取接收到的数据。 考虑进行小于16个字的多次读取(2次读取8个字、4次读取4个字、8次读取2个字、以及一次总突发计数、以确保您收到16个字。

    实际上、我想使用中断、但我认为在使用中断之前需要了解更多有关中断的信息。 例如、我认为与 SPI 相关的中断函数可能很方便、但我不知道如何使用它们。 我无法在 Simulink 中添加 RX 和 TX 之间的时序、我还需要查找该时序。 例如、通过说多次读取、可以考虑4次读取4个字、它是否会像这样

    IF (SpiaRegs.SPIFFRX.bit.RXFFST >=4)

    一旦 RX FIFO 包含4个以上的字、它将开始将 RX FIFO 中的字写入 RXBUF、这可能会阻止数据移位。 我是否通过检查 RXFFOVF 位来确保已经接收到16个字?

     

     

    好的、我会考虑您所说的内容、并尽快回复。 感谢你的帮助。

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

    如果不使用中断、这是一种方法。 它是对伪代码中完整16个字的阻塞式读取。

    循环直到读取16个字、然后读取4个字块中的数据、然后返回数据数组。   

    blockingRead16w (rxdataArray){
    wordsRead = 0
    while (wordsRead <16){
    while (RXFFST<=4){}//轮询 FIFO 中超过4个字
    对于(i=0、i<4、i++){
    rxDataArray[wordsRead]= SPIRXBUF //读取和存储 rxbuf 数据
    wordsRead++//递增计数
    器}
    }
    
    

    您不想等到达到溢出条件。 这意味着至少一个字已经被覆盖。

    上面的示例是一个分块函数、因此应用程序将在那里等待、直到接收到全部16个字。 在1MHz 或2MHz SPICLK 上、这将是一段很长的时间。 因此、我绝对建议使用中断方法。 将 RX 中断级别设置为4或8、然后读取并存储数据、直到 FIFO 中没有剩余字。 找到一些全局方法来跟踪您处于16个字、然后执行数据操作。 这一切取决于您希望数据流的外观:

    • 如果您需要环回每个字、只需立即加载 TXBUF 和接收到的字(如 SPI_INTERRUPTS 示例所做的那样)。
    • 如果您需要处理完全传输、然后在下一个16字传输中将其回路、然后存储数据、直到您接收到16个字、进行数据处理、然后将修改后的16个字写入 TXBUF。 您的主器件需要让从器件有足够的时间接收16个字、处理、然后加载16个字的数据、然后再开始下一次传输。

    请仔细研究 SPI 模块、在您掌握它的工作原理之前、请仔细检查它周围的情况。希望我提供的信息能让您离开现场。  

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

    我的问题现已解决。 感谢您的帮助、Mark。