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.

[参考译文] MSP430FR5994:将20位地址写入 DMA 寄存器失败+偏差 ASM 至编译器指南

Guru**** 2539500 points
Other Parts Discussed in Thread: MSP430FR5994

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1163014/msp430fr5994-writing-20bit-address-into-dma-register-fails-deviation-asm-to-compiler-guide

器件型号:MSP430FR5994

尊敬的所有人:

我有一个问题,我相信你可以帮助我,而且以前已经回答过了,但我找不到这个解决方案,所以我希望你能帮助我。

简而言之,我的问题(我理解):即使使用了__data20_write_long,我似乎也无法将一个20位地址写入32位寄存器。 此外、生成的汇编代码偏离了第137页编译器指南中显示的代码。 我尝试了建议的汇编器代码、但也不起作用。

有关我的问题的更多详细信息:我想对从 MSP430FR5994上某个地址开始的整个程序代码计算 CRC32 (256KB)。 因此、我想使用 DMA 来处理 CRC32寄存器、所以我想向 DMAxSA 寄存器写入一个拟合起始地址-这是失败的。


__data20_write_long((unsigned long) &DMA3SA, (unsigned long) 0x23fff);

//or this version taken from the compiler guide
__asm("	MOVA #DMA3SA+0, R15\n"
	"	MOVX.W #3FFFh, 0(R15)\n"
	"	MOVX.W #2, 2(R15)\n");

两个代码片段都写入 DMA3SA 寄存器、但只填充0x3fff ->、因此只写入16位部分。 系列数据表指出、它可以采用20位地址(在整个程序空间中使用 DMA 的其他方法)。 我使用 TI 编译器20.2.7和21.6.0以及21.6.1试用了它-在所有版本中、只有低16位被写入源寄存器。 我不知道调试器是否可以从寄存器正确读取32位数据、但执行的代码(不能按预期工作-从0x4500开始、而不是从0x3fff 开始)表明寄存器中确实没有高字节。

另一方面、为__data20_write_long 函数创建的代码偏离了编译器指南中编写的代码,因为生成"MOV.W"命令。 由于我的汇编程序知识是不存在的,所以我不知道这是否相关。

希望您能帮我找到解决方案。

祝你一切顺利

托比亚斯

P.S.:在调试模式下、我也不能向寄存器写入正确的值-这是预期的行为吗?

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

    所有写入 DMASA 或 DMADA 寄存器的字都将清零高16位。 我不知道编译器内在函数为什么会为您失败、但很明显、汇编是为什么失败的。 它执行了两次16位写入。 您必须将32位值写入寄存器、然后使用 MOVA 或 MOVX.A 执行对 DMASA 的写入。 对于常量值、您可以使用:movx.a #23fffh、&DMASA。

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

    我偶然发现了这篇帖子、其中 OP 有完全相同的问题... 即使使用__data20_write_long 函数(e2e.ti.com/.../ccs-msp430fr5994-load-the-20-bit-dms-register-with-right-not-wrong-value),加载值大于16位的 DMA 的 SA 和 DA 寄存器也不起作用。


    尊敬的 David Schultz:

    非常感谢您的回复! 正如系列数据表中描述的那样、清除高位的要点是我知道的-但它们对要做的事情有一些严格的限制。 根据您的提示,我怀疑_data16_write_addr()函数会执行该操作。 第一个测试支持它。 由于我的汇编器很糟糕、我不确定它是否真正完成了工作、还是只是进行了预测:

    //this is approx my code inside a loop:
    start_address = old_address+256; //block of words i want to calculate the crc over for each run
    __data16_write_addr((unsigned short) &DMA3SA, (unsigned long) start_address);
    old_address = start_address;
    
    //this is the compiler version of the __data16_write_addr() part:
    //with DMA3SA = 0x0542
    //with start_adress = 0x4004f which is somehow in SP?
    asm("   MOV.W #0x0542,R15");
    asm("   MOVA 0x0000(SP),R14");
    asm("   MOVA R14,0x0000(R15)");

    我不知道如何将 start_address 放入寄存器 R15、但我想我可以交换_data16... 使用 asm (" movx.a R15、&DMA3SA");

    感谢您的帮助! 如果您可以查看编译器完成的汇编代码是否有效、或者它只是一个 Fluke、我将不胜感激。 遗憾的是、即使使用16位 DMA3SAL、也会收到有关从指针转换为小整数(无符号短整型=无符号整型= 16位)的警告。 此外、名称 data16位写入地址使我不能使用它…

    祝你一切顺利

    托比亚斯

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

    GCC 生成以下内容:

      __data16_write_addr(&DMA3SA, 0x23fff);
        4178:       b1 40 ff 3f     mov     #16383, 0(r1)   ;#0x3fff
        417c:       00 00 
        417e:       a1 43 02 00     mov     #2,     2(r1)   ;r3 As==10
    
    00004182 <.Loc.38.1>:
        4182:       3c 40 42 05     mov     #1346,  r12     ;#0x0542
        4186:       00 18 ec 41     movx.a  @r1,    0(r12)  ;
        418a:       00 00 
    

    函数调用的诀窍是获取一个20位参数、您可以在其中使用它。 编译器倾向于在寄存器中传递参数、在两个寄存器中传递32位参数。 唯一的方法是将其存储到内存中。 因此会推入堆栈。

    slau646中的附录仅列出了内在函数、未说明它们的作用或工作方式。 似乎 data20函数的命名错误、因为它们以通常的两个16位输入方式处理32位参数。 另一方面、data16函数可满足您的需求。

    将额外的刀头移植到16位机器上时、总是会发生扭曲。 这可能是我一直更喜欢68000到8086的原因。

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

    尊敬的 David Schultz:

    再次感谢您的观看和回复! 因此,我要使用_data16_write_addr()函数,它的名称有点误导,我可能会对它很满意。 (抱歉、我不明白您想用上面的汇编器代码向我展示什么。)

    祝你一切顺利

    托比亚斯