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: Generated PREAD instruciton of memcpy doesn't work

Part Number: TMS320F28388D
Other Parts Discussed in Thread: C2000WARE

Tool/software:

Hi Team,

we recently encountered a non-expected behaviour when using memcpy function together with the Fast-Serial Interface (FSI) peripheral as a source and research did not reveal any related posts yet. We assume that the root cause is either a compiler- or controller bug, and hence would like to descript that situation here.

Setup:
Controller: TMS320F28388D
Compiler: TI v22.6.1 LTS
CCS: 12.6.0.8
C2000WARE: 5.1.0.00

Project:
We use the timer_ex1_cputimers example project as MWE. No modifications to the project configuration and the linker-file were made. The compiler optimization are turned off.

Goal:
Copy data from FSI RXA_BUF_BASE to an internal buffer of 16 words. The FSIRXA buffer still contains data (unequal 0) from previous tests not related to the MWE project. The data is considered to be valid and looks like that:

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

Approach:

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

Problem:
The dst buffer contains zeroes only instead of the data from the RX-buffer:

To be clear: Those zeroes are written by memcpy, meaning if dst contains arbitrary data before the memcpy, it contains 16x 0s afterwards.

The compiler generated assembly for that particular code looks like that:

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

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

We found a workaround to the problem, by using a non-constant size argument:

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

Behaviour:
The data is copied as expected:

The compiler generated assembly looks like that:

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

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

As seen, there is no repeated (RPT #15) PREAD instruction generated when using the workaround. Instead it branches to the memcpy-implementation of string.h which works fine and does not come with any generated RPT or PREAD instructions.

We analyzed that a bit further and came to the conclusion that the PREAD instruction causes the problem. Furthermore we wrote an own memcpy assembly-implementation using a repeated PWRITE function, which apparently works (data is copied from FSI buffer as expected):

; 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

Since the behaviour of the compiler generated PREAD instructions is extremly error-prone, I need to understand the reason. I found a possible explanation:


Since PREAD is defined as transfering a data value (instead of an instruction) from program space into a register (see SPRU430F 1.4.2), I assume that the FSI peripheral does not belong to program space, and/or the target-buffer does not belong to data space. As a consequence, I expect the compiler-generated assembly as invalid when using the FSI register as a source, pointing towards a compiler bug.

However, we don't have a clear picture of the situation yet. For example, we do not fully understand how that is related to the unified memory model (which is active in the compiler settings). In our understanding, there should not be a difference between PREAD/PWRITE when using a unified memory model and therefore it is unclear to us why PREAD doesn't work while PWRITE does.

We would like the raise the following questions to you:


  1. Using the RPT #15 ; || PREAD   *XAR4++, *XAR7 instruction as above: Is the behaviour of copying zeroes to the destination known or expected? If yes, why is that? Is there any document specifying that behaviour?

  2. Is the compiler correct to generate a RPT #15 ; || PREAD   *XAR4++, *XAR7 instruction when using memcpy from FSI data buffer with a constant size?

  3. Is there still any difference between PREAD and PWRITE when using the unified memory model?

  4. Is the behaviour oberseved restricted to the FSI peripheral only or may that happen for any other source and/or destination?

  5. How can the problem get fixex or at least avoided?

Pleas let me know when you need any additional information. Many thanks in advance! 

Best regards
Felix

  • Hi Felix,

    Generally, memcpy cannot (and should not) be used to read any peripheral register. Even though registers are addressed (share the same address space) with the regular memory, they are "physically" separate. Peripheral registers are contained in the peripheral's memory, with physically separate addressing lines connected to the CPU etc. Please see the thread linked here for more information about memcpy with registers, I believe it answers all the questions you have listed.   

    You should instead read the register using an HWREGH access and place the read data into your destination buffer, which is how the software drivers do it. In fact, I would suggest using this driver, it can do exactly what you are trying to do. Just make sure to import your starting timer_ex1_cputimers project from the driverlib/f2838x/examples/c28x/timer folder of C2000ware to be able to call these functions in your main file.

    Let me know if you have any other questions/want further clarification.

    Best Regards,

    Delaney

  • Hi Delaney,

    thank you very much for the response. I think, that answers all the questions we have.

    Best Regards,

    Felix