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.

Compiler/TMS320F280049: memcpy nuances...volatile vs non-volatile pointer arguments

Part Number: TMS320F280049
Other Parts Discussed in Thread: C2000WARE

Tool/software: TI C/C++ Compiler

I'm trying to copy out the adc results into a structure in my application using memcpy and I'm noticing different compiler interpretations depending on how my pointers are declared.  I have the code working, but I'd like to understand this better.  Let me explain....

    volatile uint16_t * vsource = (volatile uint16_t *)((uintptr_t)(ADCARESULT_BASE));
    volatile uint16_t * vdest = &(adcData.adcAData);

    uint16_t * source = (volatile uint16_t *)((uintptr_t)(ADCARESULT_BASE));
    uint16_t * dest = &(adcData.adcAData);

    memcpy(vdest, vsource, sizeof(adcAData_t));
    memcpy(dest, vsource, sizeof(adcAData_t));
    memcpy(dest, source, sizeof(adcAData_t));

Each call to memcpy above generates different ASM.

When both the destination and source are volatile pointers, a branch to the actual memcopy function is performed.  This copy works.

243             memcpy(vdest, vsource, sizeof(adcAData_t));
08659b:   8342        MOVL         XAR5, *-SP[2]
08659c:   0210        MOVB         ACC, #16
08659d:   76487611    LCR          memcpy

When the source is volatile and the destination is not, the copy is implemented using a repeat and PWRITE instruction.  This copy works.

244             memcpy(dest, vsource, sizeof(adcAData_t));
08659f:   8A42        MOVL         XAR4, *-SP[2]
0865a0:   C548        MOVL         XAR7, *-SP[8]
0865a1:   F60F        RPT          #15
0865a2:   2684     || PWRITE       *XAR7, *XAR4++
0865a3:   7700        NOP          
0865a4:   7700        NOP          

When neither the source or destination is volatile, the copy is implemented using a repeat and PREAD instruction.  This copy does not work.

245             memcpy(dest, source, sizeof(adcAData_t));
0865a5:   8A48        MOVL         XAR4, *-SP[8]
0865a6:   C546        MOVL         XAR7, *-SP[6]
0865a7:   F60F        RPT          #15
0865a8:   2484     || PREAD        *XAR4++, *XAR7

My C28x assembly is a little rusty but I looked at the instruction set guide and checked XAR4 and XAR7 and they have the correct values in them in all of the above cases.  However in the third case the memory at the destination address is zero'ed out instead of data from the adc result registers being copied over.  Can someone help me understand why the third case doesn't work?  I'm guessing this has something to do with the compiler not knowing what addressing mode to use?  Please enlighten me :)

Best,

Trey

  • What is the version of the compiler?  Please show the build options exactly as the compiler sees them.  Please copy-and-paste the text, and do not use a screen shot.

    Thanks and regards,

    -George

  • Invoking: C2000 Compiler
    "/Applications/ti/ccs1010/ccs/tools/compiler/ti-cgt-c2000_20.2.1.LTS/bin/cl2000" -v28 -ml -mt --cla_support=cla2 --float_support=fpu32 --tmu_support=tmu0 --vcu_support=vcu0 -Ooff --include_path="/Users/germanpm/ti/C2000Ware_3_03_00_00_Software/libraries/control/DCL/c28/include" --include_path="/Users/germanpm/ti/C2000Ware_3_03_00_00_Software/libraries/dsp/FixedPoint/c28/include" --include_path="/Users/germanpm/ti/C2000Ware_3_03_00_00_Software/libraries/dsp/VCU/c28/include/vcu0" --include_path="/Users/germanpm/ti/C2000Ware_3_03_00_00_Software/libraries/dsp/VCU/c28/include/common" --include_path="/Users/germanpm/Polymorphic_Labs_LLC/Sygnal/Firmware/MCM/Sygnal-MCM" --include_path="/Users/germanpm/ti/C2000Ware_3_03_00_00_Software/device_support/f28004x/common/include" --include_path="/Users/germanpm/ti/C2000Ware_3_03_00_00_Software/device_support/f28004x/headers/include" --include_path="/Users/germanpm/Polymorphic_Labs_LLC/Sygnal/Firmware/MCM/Sygnal-MCM/device" --include_path="/Users/germanpm/ti/C2000Ware_3_03_00_00_Software/driverlib/f28004x/driverlib" --include_path="/Applications/ti/ccs1010/ccs/tools/compiler/ti-cgt-c2000_20.2.1.LTS/include" --advice:performance=all --define=CPU1 --define=_FLASH --relaxed_ansi --printf_support=minimal --diag_suppress=10063 --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --gen_data_subsections=on --abi=coffabi --preproc_with_compile --preproc_dependency="drivers/mcm-analog.d_raw" --obj_directory="drivers"  "../drivers/mcm-analog.c"

    Thanks for taking a look George.

  • This code is generated ...

    Trey German8 said:
    0865a7:   F60F        RPT          #15
    0865a8:   2484     || PREAD        *XAR4++, *XAR7

    ... because you build with the option -mt (short for --unified_memory).  However, this instruction sequence must not be valid when this is attempted ...

    Trey German8 said:
    data from the adc result registers being copied over

    I lack the expertise needed to explain why that is the case.  I will notify the C28x device experts about this thread.  They will let you know the best way to copy data over from ADC registers.

    Thanks and regards,

    -George

  • Trey German8 said:
    However in the third case the memory at the destination address is zero'ed out instead of data from the adc result registers being copied over. 

    The TMS320C28x Optimizing C/C++ Compiler v20.8.0.STS User’s Guide has the following description for the --unified_memory option:

    Use the --unified_memory (-mt) option if your memory map is configured as a single unified space; this allows the compiler to generate RPT PREAD instructions for most memcpy calls and structure assignments. This also allows MAC instructions to be generated. The -- unified_memory option also allows more efficient data memory instructions to be used to access switch tables.

    Even under unified memory, memory for some peripherals and some RAM associated with those peripherals is allocated only in data memory. If –unified_memory is enabled, you can prevent program memory address access to specific symbols by declaring those symbols as volatile.

    Looking at the TMS320F280049 datasheet and TMS320F28004x Real-Time Microcontrollers Technical Reference Manual I can't seem to find a definition of which peripherals are only allocated in data memory.

    However, the C2000Ware_3_03_00_00_Software/device_support/f28004x/headers/cmd/f28004x_headers_nonbios.cmd linker command file shows all peripherals in Data Memory

    If the ADC data registers are only allocated in data memory, that would explain why the third case doesn't work, but the second case does.