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.

[参考译文] MSP430FR5964:将20位地址写入 DMA 寄存器失败& lt、时间占1%

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1392184/msp430fr5964-writing-20-bit-address-into-dma-register-fails-1-of-the-time

器件型号:MSP430FR5964
主题中讨论的其他器件: MSP430FR5969MSP430F6779

工具与软件:

我正在尝试分配 DMAxSA 寄存器的完整20位。 用户手册指定"读取或写入位19-16需要使用扩展指令"。
这已经令人困惑、因为 MSP430FR5XX_6XX DMA 代码示例使用了 __data20_WRITE_LONG ()内在函数、这是使用两个标准 MOV 实现的。 w 指令、这些指令不是扩展指令(CPU430X)的一部分。 当我尝试使用_data20_WRITE_LONG (&DMA0SA、0x10000)向 DMA0SA 分配一个20位值时、我得到的寄存器值为0x0。

在进一步阅读 MSP 文档和 本表单讨论后、我了解到我需要改用__ data16_write_addr ()。
在编译时、此内在函数实际上使用 MOVX。 或 POPX。 一条指令为扩展地址分配指令、现在可以看到它成功分配了完整的20位寄存器。
但是、在我的应用保持运行几天后、仍然会因为 DMA 地址分配操作失败而出现问题。 每10000个 DMA 地址分配一次、位19-16就会被错误地清除。

我已经验证__data16_write_addr ()的两个参数都正确,并且 DMA 通道被禁用,所以问题不在于应用软件本身。 此外、我已经按照编译器用户指南的建议禁用了中断。

将_data16_write_addr 替换为我自己的汇编代码不会改变这种情况。

   _asm ( "PUSHM. W   #2、R15\n"
           "POPX."     0 (R12)");

我可以解决此问题的唯一方法是读回 DMA 寄存器值并在循环中重新分配该值。

#pragma optimize=none
void Dma_WriteAddress(uint32_t destination, uint32_t source)
{
    __disable_interrupt();

    do
    {
        __data16_write_addr(static_cast<uint16_t>(destination), source);
    }
    while(__data16_read_addr(static_cast<uint16_t>(destination)) != source);

    __enable_interrupt();
}

当我向该函数添加日志记录时、可以看到分配仅在调用该函数时每5.000到50.000次失败一次。

当然、该解决方案不是最佳解决方案、因此不应该是必需的。 这是否是硬件错误(不在勘误表中)? 我缺少什么吗? 还有人会遇到这个问题吗?

这在硬件版本 C 上的三个 MSP430FR5964 IC 上进行了测试
编译器:IAR MSP430 7.21.1
数据/代码模型:小

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

    这绝对是非常奇怪的。 这可能是硬件错误、但问题在哪里? 此内在函数做了几件事、我看到(至少在 GCC 版本中)的一个危害是操作数放在堆栈上。 这通常不是一个问题、但是如果一个中断发生并且该中断不知何故使堆栈变得混乱、该怎么办呢? 当然不应该。

      __data16_write_addr(DMA0SA, 0x10000);
        440c:       81 43 00 00     mov     #0,     0(r1)   ;r3 As==00
        4410:       91 43 02 00     mov     #1,     2(r1)   ;r3 As==01
    
    00004414 <.Loc.34.1>:
        4414:       1c 42 12 05     mov     &0x0512,r12     ;0x0512
        4418:       1d 42 14 05     mov     &0x0514,r13     ;0x0514
        441c:       00 18 ec 41     movx.a  @r1,    0(r12)  ;
        4420:       00 00 
    
    

    不管怎样、对于汇编语言程序员来说、一个更好的代码编写方法是:

    movx.a #0x10000,&0x512

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

    我更改了函数、以实现 MOVX。 指令将20位从堆栈复制到寄存器。 然后、我使用 MOV 在不修改堆栈的情况下检查最高有效4位。 B 指令、如果它不匹配、则停止调试器。 在这些指令期间、中断被禁用。

    通过调试器、我可以清楚地看到、当 MOVX 使用堆栈中的所有字节时、最高有效4位为零。 A 正确(非零)、DMA 寄存器值错误。

    可能是 MOV/POPX 中的硬件错误。 但说明、我无法想象自该 MCU 的2021年发布以来不会注意到这个问题。

    我担心这不是硬件错误、还有另一个导致不稳定的因素。 您还有其他建议吗?

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

    我准备了一个简单的测试来在我手头的 fr5969上运行。

            push r6
            clr  r6
            mova #0x10000,r15
            mova #0x512,r14
    loop:   clrx.a @r14
            mova r15,0(r14)
            incx.a r6
            jz exit
            cmpx.a @r14,r15
            jz loop
    exit:  

    如果 R6在退出时为零、那么它运行了一百万次、切换 DMA 寄存器、没有错误。

    我尚未看到错误、因此这些(唯一)器件寄存器似乎不存在问题。

    随着设计得到重复使用、各器件之间往往有很多共性(因此相同的勘误表将出现在多个器件中)、因此这个问题不太可能只有单个器件存在。

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

    我想我应该补充一点、我想看看展示此问题的代码部分的完整示例。 不是 C 级代码、因为我没有您的编译器、而是它输出的汇编代码。 然后、我可以看看我是否可以在 msp430fr5969中重现问题。

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

    我已经解决了这个问题!
    我注意到 在禁用所有其他 DMA 通道时绝不会发生此问题。 借助这些信息、我进行了进一步的研究、并在 MSP430F6779 ( 2024年4月发布)中找到了以下 DMA4勘误表。



    从三种可能的权变措施来看、选项2似乎最适合我的情况。 在我的 MSP430FR5964 (它可能使用相同的 DMA 硬件)中设置 DMARMWDIS 后、问题就得到解决。

    感谢您发送编修。感谢您发送编修。

    对于任何观看的 TI 员工来说、回顾性更新勘误表以包含此信息可能会有所帮助。