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.

[参考译文] MSP430F6747A:DMA 传输正常工作、无需中断即可进行处理

Guru**** 2391415 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1435543/msp430f6747a-dma-transfer-working-without-interrupts-and-bugged-with-interrupts

器件型号:MSP430F6747A

工具与软件:

您好!

我一直在尝试使用 DMA 进行高速的大型数据传输、而且在使用 DMA 的中断时遇到了问题。

我的程序正在尝试向配置为 UART 模式的 eUSCI A0模块发送缓冲区(9638字节)。 本身的 UART 配置

因为我能够使用串行电缆通过它向我的 PC 发送数据。

我制作了两个简单的测试函数来使用 DMA 发送相同的缓冲区、一个函数使用标志轮询、另一个函数使用 DMA 的中断。 下面是代码:

static void dma_send(const uint8_t *buf, size_t len)
{
    DMACTL0 = DMA0TSEL_17; // UCA0TXIFG

    DMA0SA = (uint32_t)buf;
    DMA0DA = (uint32_t)(&UCA0TXBUF);
    DMA0SZ = len;

    DMA0CTL = (
        DMADT_0        // single transfer mode
        | DMADSTINCR_0 // destination addess fixed
        | DMASRCINCR_3 // source address incremented
        | DMADSTBYTE
        | DMASRCBYTE
        | DMALEVEL     // trigger type: level detection
    );

    hw_toggle_led1();

    DMA0CTL |= DMAEN;
    while (!(DMA0CTL & DMAIFG));

    hw_toggle_led1();
}

PLACE_INTERRUPT(isr_dma)
#pragma vector=DMA_VECTOR
static void __interrupt isr_dma(void)
{
    __low_power_mode_off_on_exit();

    switch (__even_in_range(DMAIV, DMAIV_DMA0IFG)) {
    case DMAIV_DMA0IFG: {
        DMA0CTL &= ~DMAIE;
        break;
    }
    }
}

static void dma_send_irq(const uint8_t *buf, size_t len)
{
    DMACTL0 = DMA0TSEL_17; // UCA0TXIFG

    DMA0SA = (uint32_t)buf;
    DMA0DA = (uint32_t)(&UCA0TXBUF);
    DMA0SZ = len;

    DMA0CTL = (
        DMADT_0        // single transfer mode
        | DMADSTINCR_0 // destination address fixed
        | DMASRCINCR_3 // source address incremented
        | DMADSTBYTE
        | DMASRCBYTE
        | DMALEVEL     // trigger type: level detection
        | DMAIE        // enable interrupts
    );

    hw_toggle_led1();

    DMA0CTL |= DMAEN;

    __low_power_mode_0();

    hw_toggle_led1();
}
对于我的所有测试、MCLK 和 SMCLK (用于为 UART 提供源)都设置为 DCOCLK 在25 MHz 上运行、并使用 REFOCLK 作为基准、因此频率不是真的准确。
我将调用这些函数并将缓冲区作为参数传递。 使用"dma_send ()",我没有问题,它工作正常,我尝试了波特率57'600和高达3'000'000。
然而,使用"dma_send_irq ()",它似乎是从波特率57'600到1'382'400工作,但高于它完全被破坏,我在我的计算机终端上收到垃圾字符,有时 MSP 本身崩溃。
我也使用边沿触发检测进行了测试、但我得到的结果相同或更差。
我更喜欢使用中断、因为目标是在传输过程中使用低功耗模式、我们在实际应用中尽量快地实现最大数据速率、以大约2M 字节的数据传输。
是否对启用中断时的行为有解释?
谢谢。

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

    使用 DMALEVEL=1令我担心:"当 DMALEVEL=1时、会使用电平敏感的触发器。 为确保正常运行、电平敏感的触发器可以
    仅当外部触发 DMAE0被选作触发时才使用。'

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

    是的、我在初始消息中提到、我尝试使用边缘检测而不是液位检测、但平均结果更差。 它通常在较低的波特率下工作正常,但当更高的时候,我也会在我的电脑终端上得到垃圾字符。

    当使用边沿触发时、我将 DMA0SA 设置为"buf + 1"、将 DMA0SZ 设置为"len - 1"、并手动将缓冲区的第一个字符写入 UCA0TXBUF、以确保 DMA 的第一个边沿触发正确。

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

    我会执行一些操作来验证该 PC 终端在高比特率下的运行情况。

    或使用各种逻辑分析仪检查数据流。

    一个廉价的测试是将另一个 F6747在接收端。

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

    很遗憾、目前我还没有另一个 MSP、但我不确定如果从一个 MSP 到另一个 MSP 的传输成功完成、即使我无法用外部方法来直观地了解内部发生的情况、我也如何能够判断。

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

    发送校验和。

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

    看一下器件勘误表、我会发现 DMA9将会让我使用 DMA 进行串行 I/O 一个不同的问题(遗漏的触发器),但一个严重的问题。

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

    是的、我看了勘误表、也看到了 DMA9、但出于某种原因、我认为这可能是可以避免的。 现在我再看一下、我猜有一半的 DMA 功能无法用于此 MSP?

    编辑:实际上,我没有任何线索,因为 DMA 似乎是几乎工作正常,只要我不使用 DMA 的中断(即,使用 DMAIE 来知道  传输何时完成,而不是轮询 DMAIFG ),但这似乎不是与勘误表 DMA9有关...

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

    该勘误表仅影响 USCI、并与触发条件丢失有关。

    使用 DMA 中断也许不是问题、这不会改变 DMA 的操作。 使用低功耗模式可能。 但使用 LPM0时、最大 DMA 周期时间从4个周期变为5个周期、因此这种情况似乎不太可能。 虽然 LPM0不应更改时钟系统中的某些内容、但也可能改变了该值。

    DMA 无法混淆串行数据。 可能重复或跳过字节。 但是、由于它无法更改串行输出移位寄存器中的内容、因此无法改编位。