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.

[参考译文] MSP430F67471A:DMA 传输问题

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1054347/msp430f67471a-dma-transfer-issue

器件型号:MSP430F67471A

我正在尝试收集进入 SPI 端口的数据、并使用 DMA 将其从 SPI 端口传输。 最初、我使用的是 DMA 的通道0、它工作正常、但在长时间测试时、DMA 偶尔停止传输。 我现在处于 DMA 不再传输的状态。 甚至对电路板进行循环供电也没有什么帮助。

我找到了 DMA 勘误表9  :https://www.ti.com/lit/er/slaz574v/slaz574v.pdf?ts=1636610126959 、并尝试了第二次变通办法、也添加了通道2。 同样、没有传输发生。

在启用 DMA 的例程中、我检查是否已为任一通道触发标志、这将导致程序离开循环。 我知道我可以离开循环、在用户选择停止收集数据时使用中断、这会导致设置标志、从而程序离开数据采集模式。 相关条件为:

while ((((DMA0CTL 和 DMAIFG)=0)&&((DMA2CTL 和 DMAIFG)=0);

我在收集数据之前置位 DMAEN 位、并在循环条件后将其禁用、循环条件持续循环至置位并复位、直到用户完成。

我的其余 DMA 设置如下:

ADC 的// DMA 设置

 DMA0CTL &=~DMAEN;                               //禁用 DMA

 DMA0SA =(字)&ASPI_RXBUF;                     //源地址是来自 ADC 的 RX 缓冲器

 DMA0DA =(字)&ADCOUT[0];                      //目标地址是一个字节数组,将存储6个字节(L0、L1、L2、L3、R0、 R1)  

  DMACTL0 |= DMA0TSEL_16;                          //在 USCIB1RX 上启动 DMA 传输这意味着当一个字节被接收到 USCI B1 RX 缓冲器中时、传输将发生

 DMACTL4 |= DMARMWDIS;                            //在 CPU 的读取-修改-写入周期期间 DMA 传输被禁用

 DMA0CTL &=~DMAIFG;                              //清除任何潜在的挂起中断

 DMA0CTL |= DMADD_0 + DMADSTINCR_3 + DMASBDB;     //重复单次传输模式、包括目标地址、源是字节、dest 是字节、边沿敏感触发器

 DMA0SZ = 0x06;                                   //传输大小为6字节(L0、L1、L2、L3、R0、 R1)  

  

  //修复勘误表 DMA9: https://www.ti.com/lit/er/slaz574v/slaz574v.pdf?ts=1636610126959

 DMA2CTL &=~DMAEN;

 DMA2SA =(字)&ASPI_RXBUF;

 DMA2DA =(字)&ADCOUT[0];

 DMACTL1 |= DMA2TSEL_16;

 DMA2CTL &=~DMAIFG;

 DMA2CTL |= DMADD_0 + DMADSTINCR_3 + DMASBDB;

 DMA2SZ = 0x06;

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

    您好、Matthew、

    您能否尝试在此处运行其中一个 DMA 示例[链接]以查看您是否获得了任何 DMA 传输?

    谢谢、

    王国新

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

    您好、Urica、

    是的、我运行了示例 DMA_01并在示波器上的每次传输后观察到信号切换。  对于该示例、DMA 仍会进行传输。 有趣的是、如果我返回仅使用通道0而不是同时使用通道0和通道2 (我根据勘误表中的权变措施建议)、我仍然会获取传输、尽管它仍然在看似任意的时间点停止传输。  

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

    您好、Matthew、

    我在代码中注意到您正在使用 DMAxTSEL_16。 根据表6-14。 "DMA Trigger Assignments"在数据表中、这是 UCA0RXIFG 的触发器。 根据代码中的注释、我认为这应该是 DMAxTSEL_27、它是 UCB1RXIFG0的触发器。

    其次、您使用的是 DMADT_0、它实际上用于单次传输模式。 重复单次传输模式为 DMADT_4。

    您是否可以在没有勘误解决方法的情况下进行这些更改、并查看这是否可以解决您的问题?

    谢谢、

    王国新

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

    您好、Urica、

    再次感谢你的帮助。 触发应该在 UCA0RXIFG 上、但是注释从未改变。 对此我深表歉意。 我运行它只是为了以防万一、但是没有任何数据进入 UCB1RXIFG0。

    我使用 DMADD_4尝试了重复单次传输模式。 在经过一定数量的传输后、它仍然失败、在相同的 while 循环上被捕获、但这次只检查 DMA0CTL 标志。 我也为该测试注释了 DMA2的所有实例。  

    目前、我计划在 while 循环中对 DMA 传输执行超时、作为临时解决方法。 它远非理想、因此任何其他想法仍然有用。

    最棒的

    Matthew Lacek

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

    您好、Matthew、

    您能否检查您使用的是此器件的版本 B 还是版本 C? DMA9不适用于 Rev C 器件。

    如果您使用版本 B、我会针对类似的用例引用此线程、其中客户使用 DMA 通道0从 SPI RXBUF 读取数据。 此线程还包含针对 DMA9 [链接]实现的权变措施的源代码。 请仔细阅读此主题、因为此源代码中有一些错误会在该主题中解决。

    谢谢、

    王国新

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

    您好、Urica、

    我使用的是修订版 C、因此勘误表毕竟不能适用。 是否有人想知道在 RevC 器件上还会导致类似问题的其他原因?

    谢谢、


    Matthew Lacek

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

    您好、Matthew、

    根据我对表11-2的理解。 "DMA Trigger Operation"在用户指南和您的用例中、当 UCAxRXIFG 被置位时、一个 DMA 传输应该被触发。

    在您卡住的地方、我会检查 UCAxRXIFG 是否被置位、如果被置位、UCAxRXIE 是否也被置位(这会导致 RXIFG 不触发一个传输)。 我还会检查 DMAxSZ 是什么。

    由于 DMA 由 SPI 触发、因此有几个 USCI SPI 勘误表(在修订版 B 和 C 上)也可能是 USCI41、47、50等因素。

    谢谢、

    王国新

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

    您好、Urica、

    我已经查看了 UCAxRXIFG 来查看它是否被置位。 当故障发生时、UCAxRXIFG 未置位、并且我没有使用 UCAxRXIE、因此不应置位。 我与 DMAxSZ 一起仔细检查了这个以进行确认。 RXIFG 和 RXIE 均未置位、DMAxSZ 为预期的0x06。

    看来 USCI47应该给我带来某种问题。 希望这就是问题所在、但现在、我将研究如何使用我当前设置和配置的解决方案来解决这个问题。 我将告诉您在调整该勘误表的代码后错误是否仍然存在。

    谢谢、

    Matthew

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

    您好、Urica、

    我正在尝试针对勘误表 USCI47实施权变措施解决方案、但我遇到了类似的困难。   的时钟相位 UCCKPH = 1、并且 eUSCI_A 模块被配置为一个 SPI 从器件。 SPI 时钟引脚在空闲时被驱动为低电平。 由于 UCCKPL = 0、因此在空闲模式下、UCSWRST 位应该能够被清零。 之前、我在时钟周期期间将其清除、而时钟引脚处于未知状态、这说明了我所看到的内容的随机性。

    我无法使用提供的第一种权变措施、因为我必须使用 UCCKPH=1。

    第二种权变措施似乎是最可靠的解决方案、但是、在将 SPI 时钟引脚用于时钟输入之前清零 UCSWRST 位还没有工作。

    第三种变通办法似乎有时起作用、但在需要保持一致的循环中不一致。 无论如何、我还需要在空闲电平期间清除该位、这正是第二个权变措施所需的。 因此、根据第二种权变措施、我希望在时钟引脚仍处于低空闲电平时复位 SPI 从器件。

    一旦我在空闲电平期间复位 SPI 从器件、然后我设置我的 ADC、它使用时钟引脚、然后我尝试读取中的数据。 现在、似乎每隔6个字节就会将其发送给 DMA 供使用、然后它将被卡住。 我也检查了时钟引脚在空闲时是否处于低电平。 从勘误表中、我认为一旦 SPI 被复位到适当的电平、我就不需要再次复位它了? 它应该运行正常、直到 UCSWRST 位再次被置位。

    如果这一点不清楚、我们将感谢您的任何帮助。

    谢谢、
    Matthew

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

    您好、Matthew、

    我认为我们应该将这个问题分开、并确保在查看 DMA 方面之前正确设置 SPI 并使其正常工作。 为此,我将参考以下资源:

    -有关常见串行通信问题解决方案的应用手册: https://www.ti.com/lit/slaa734

    -有关 SPI 的 MSP Academy [链接]

    - Resource Explorer 上此器件的标准 SPI 代码示例[链接]

    您能否提供有关您的代码的更多详细信息? 例如、时钟的运行速度是多少、SPI 使用的时钟是多少、代码中是否使用了任何低功耗模式等?

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

    您好、Urica、

    感谢您的回复。 我已通过完全移除 DMA 将其缩小到 SPI 问题。 如果没有 DMA、问题仍然存在、因此我得出结论认为这不是问题。

    我创建了一个仅用于测试此问题的新项目。 该程序采用密钥输入来触发对 ADC (器件型号 PCM1804DB)单个4字节采样的读取(通过配置为 SPI 的 eUSCIA0端口)。 然后、程序将此4字节采样结果输出到 UART 模式下使用 UCA1的终端中。  

    MCLK 使用内部 DCO FLL 时钟以24.9MHz 运行。 SMCLK 在 MCLK /2下运行。 ACLK 被连接至一个外部32kHz 晶体振荡器。 SPI 端口的配置如下:

    UCA0CTLW0 |= UCSWRST; // set reset bit for config
    UCA0CTLW0 |= (UCMSB | UCSYNC | UCMODE_1 | UCCKPH);

    eUSCIA0配置为4引脚 SPI 从器件。 该系统的主器件(ADC)提供数据时钟、工作频率为5.12MHz195.31nsec。

    主器件还提供 STE 信号、该信号的频率为80kHz 或周期为12.5uC。

    您可以看到使用了与勘误表 USCI47相对应的有问题 UCCKPH

    此代码也没有使用低功耗模式。 该程序处于空闲状态、直到收到钥匙冲程。

    数据的实际读数如下:

    void CaptureFourByteSample(void)
    {
      while(P3IN & BIT2);       // wait for ADC data clock to settle to LOW
      UCA0CTLW0 &= ~UCSWRST;    // enable SPI interface
      Enable_ADC;               // turn on ADC
      TA0CCTL0 &= ~CCIE;        // disable capture/compare interrupts
      TA0CCR0 = 500;            // set capture/compare to 500 (15.17 msec)
      TA0CTL = TASSEL_1 | MC_1 | TACLR; // start timer A0 upmode, ACLK
      
      while(!(TA0CCTL0 & CCIFG)); // wait until timer expires which should be 1116/Fs
      TA0CCTL0 &= ~CCIFG;       // clear the interrupt flag after it occurs
      TA0CTL = 0;               // Reset timer
      while(P3IN & BIT3);       // wait for STE signal to go low
      
      while(!(UCA0IFG & UCRXIFG)); // wait for byte to be received
      ADCOUT[0] = ASPI_RXBUF;       // store in buffer
      while(!(UCA0IFG & UCRXIFG));
      ADCOUT[1] = ASPI_RXBUF;
      while(!(UCA0IFG & UCRXIFG));
      ADCOUT[2] = ASPI_RXBUF;
      while(!(UCA0IFG & UCRXIFG));
      ADCOUT[3] = ASPI_RXBUF;
      
      Disable_ADC;              // disable ADC
      UCA0CTLW0 |= UCSWRST;     // disable SPI  
      UART_SendData((BYTE *)&ADCOUT[0], 4, MSP_COM_UART); // send data to terminal
    }

    启用 SPI 接口(第4行)的操作在 ADC 使能(第5行)之前进行、目的是确保不满足勘误表 USCI47的条件、因为一旦启用 ADC、其数据时钟将会振荡、 因为它是 SPI 系统的主器件。 在此之前、我在线路14上的复位过程中产生了 SPI。  

    无论采用哪种方法、在读取看似随机的触发器数之后、程序将卡在第15行、等待 RXIFG、而这种情况从未发生。 重置程序会使其再次工作、直到出现下一个故障。 直到出现此故障、当 SPI 从线路14上的复位状态退出时、数据才有效。 当复位在第5行时、数据无效。

    如果 UCCKPH 设置为低电平、则不会在数据收集期间发生此故障、但是、由于时序要求、将 UCCKPH 更改为低电平不是解决方案。 进行此更改时、根据我的预期、从 ADC 读取的数据无效。

    感谢您花时间和精力帮助我寻找解决此问题的解决方案。

    如果您有空、可以致电咨询。 请告诉我这是不是可能的。

    谢谢、

    Matthew

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

    您好、Matthew、

    让我来看看这个、然后返回给您。 但是、您应该检查以下几点:

    -验证主器件和从器件是否同意时钟极性/相位、芯片选择极性以及 MSB 或 LSB 优先

    -您还需要考虑主设备和从设备之间的最大 SPI 通信速度

    此外,STE 信号与标准 CS 信号不等效。 这些线程更详细地介绍了此[link1link2]

    有关上述项目的更多详细信息、请参阅上面链接的应用手册 :https://www.ti.com/lit/slaa734

    谢谢、

    王国新

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

    您好、Urica、

    我想向您更新一下、已达成涉及 kill 计时器的解决方案。 我启用了 SPI 端口和 DMA、以6个字节进行同步、如果失败、kill 计时器会将其复位。 这样、它会一直复位、直到 SPI 正确同步、之后不会出现进一步的问题。

    感谢你的帮助。