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.

[参考译文] TMS320F28388D:生成的 memcpy PREAD 指令不起作用

Guru**** 2538930 points
Other Parts Discussed in Thread: TMS320F28388D, C2000WARE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1422939/tms320f28388d-generated-pread-instruciton-of-memcpy-doesn-t-work

器件型号:TMS320F28388D
Thread 中讨论的其他器件: C2000WARE

工具与软件:

大家好、团队成员:

我们最近在将 memcpy 函数与快速串行接口(FSI)外设一起使用时遇到一个非预期行为、研究尚未发现任何相关帖子。 我们假设根本原因要么是编译器错误、要么是控制器错误、因此我们要在这里描述该情况。

设置:
控制器:TMS320F28388D
编译器:TI v22.6.1 LTS
CCS:12.6.0.8
C2000WARE:5.1.0.00

项目:
我们使用 timer_ex1_cputimers 示例项目作为 MWe。 未对项目配置和链接器文件进行任何修改。 编译器优化已关闭。

目标:
将数据从 FSI RXA_BUF_BASE 复制到16个字的内部缓冲区。 FSIRXA 缓冲区仍包含来自先前与 MWE 项目无关的测试的数据(不等于0)。 数据被视为有效数据、如下所示:

0x000066C0 0040 0800 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0x000066D2 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0x000066E4 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0x000066F6 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

方法:

uint16_t dst[16];
memcpy(dst, (void*) 0x66C0, 16); // 0x66C0 is the address of the FSI RX A receive buffer

问题:
dst 缓冲区只包含零、而不包含来自 RX 缓冲区的数据:

要明确的是:这些零由 memcpy 写入、这意味着如果 dst 在 memcpy 之前包含任意数据、则在 memcpy 之后包含16个0。

编译器为特定代码生成的汇编代码如下所示:

memcpy(dst, (void*) 0x66C0, 16);

MOVL        XAR4,       #0x00a800
MOVL        XAR7,       #0x0066c0
RPT         #15
||  PREAD   *XAR4++,    *XAR7

我们通过使用非恒定大小参数找到了该问题的权变措施:

uint16_t dst[16];
volatile int x = 16; // volatile to prevent any optimizations
memcpy(dst, (void*) 0x66C0, x);

行为:
数据按预期复制:

编译器生成的汇编代码如下所示:

memcpy(dst, (void*) 0x66C0, x);

SETC    SXM
SPM     #0
MOVL    XAR5, #0x0066c0
MOVL    XAR4, #0x00a800
MOV     ACC, *-SP[1]
LCR     memcpy

因此、使用变通办法时不会生成重复(RPT #15) PREAD 指令。 相反、它分支到 string.h 的 memcpy-implementation、此函 数有效、并且不附带任何生成的 RPT 或 PREAD 指令。

我们进一步分析了这一点、得出的结论是 PREAD 指令导致了该问题。 此外、我们使用重复的 PWRITE 函数编写了一个自己的 memcpy 汇编实现、这个实现显然可行(按预期从 FSI 缓冲区复制数据):

; memcpy 16 words from SRC to DEST
; XAR4 = SRC pointer, XAR5 = DST Pointer, AL = Size
_fixed_memcpy:
	MOVL		 	XAR7, XAR4	
	SUBB			AL,#1
	RPT				AL
|| 	PWRITE        	*XAR7, *XAR5++
	LRETR

由于 编译器生成的 PREAD 指令的行为极易出错、因此我需要了解原因。 我找到了一种可能的解释:


由于 PREAD 定义为将数据值(而不是指令)从程序空间传递到寄存器(参阅 SPRU430F 1.4.2)、因此我假设 FSI 外设不属于程序空间、且/或目标缓冲区不属于数据空间。 因此、我预计在使用 FSI 寄存器作为源代码时、编译器生成的汇编代码无效、这指向编译器错误。

然而,我们还没有清楚的情况。 例如、我们不完全了解它与统一内存模型(在编译器设置中处于活动状态)的关系。 根据我们的理解、在使用统一内存模型时、PREAD/PWRITE 不应有区别、因此我们不清楚为什么 PREAD 不起作用而 PWRITE 起作用

我们希望向您提出以下问题:


  1. 使用 RPT #15 ;|| PREAD  *XAR4++,*XAR7 指令如上所示:将零复制到目标的行为是已知的还是预期的? 如果是、为什么会这样? 是否有指定该行为的文档?

  2.    从 FSI 数据缓冲区使用具有常量大小的 memcpy 时、编译器是否正确生成 RPT #15;|| PREAD * XAR4++、* XAR7指令?

  3.  使用统一内存模型时、PREAD 和 PWRITE 之间是否仍然有任何差异?

  4. 该行为是否仅限于 FSI 外设、或者是否可能在任何其他源和/或目标上发生?

  5. 该问题如何获得 fixex 或至少避免?

如果您需要任何其他信息、请告知我。  提前感谢!  

此致
Felix

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

    尊敬的 Felix:

    通常、memcpy 不能(也不应)用于读取任何外设寄存器。 即使寄存器是 与常规存储器进行寻址(共享相同的地址空间)、它们在物理上是独立的。 外设寄存器包含在外设的存储器中、通过物理上独立的寻址线连接到 CPU 等 请查看 此处链接的主题 、了解有关带寄存器的 memcpy 的更多信息、我认为它可以回答您列出的所有问题。   

    您应该改为使用 HWREGH 访问来读取寄存器、并将读取数据放入目标缓冲区、这就是 软件驱动程序的操作方式。 事实上,我建议使用这个驱动程序,它可以完全实现你想做的。 只需确保 从 C2000ware 的 driverlib/f2838x/examples/c28x/timer 文件夹中导入启动 timer_ex1_cputimers 项目、以便能够在主文件中调用这些函数。

    如果您有任何其他问题/需要进一步澄清、请告诉我。

    此致、

    Delaney

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

    尊敬的 Delaney:

    非常感谢您的答复。 我想、这回答了我们的所有问题。

    此致、

    Felix