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.

Weird behaviour of 64-bit floating-point data in external memory

I'm using TMDXEVM6678LE board. Trying to make some data shared between cores, and I can't get the doubles in external memory to update to correct values. I use two projects - one holding all the data that is shared (and no executable code - it's compiled as a relocatable module), and a second one that uses this data.

Here is the code of the first CCS project:

#include <c6x.h>
#pragma DATA_SECTION(gptr_buffer, ".shared")
#pragma DATA_SECTION(glob_SNAFU, ".shared")
#pragma DATA_SECTION(glob_buffer, ".shared")
volatile double            *gptr_buffer;
volatile double            glob_SNAFU[4];
volatile double            glob_buffer[8000];

.shared is a section that's supposed to appear in EXT0 region of memory, everything else goes int L2

Here is the code of the second CCS project:

#include <c6x.h>
#include "memory.h"
void main(void)
{
    volatile double *vdref;
    vdref = glob_SNAFU;
    *vdref++ = 0.001;
    for(;;){}
}

Contents of memory.h:

#ifndef _MEMORY_H
#define _MEMORY_H
extern volatile double                 *gptr_buffer;
extern volatile double                glob_SNAFU[4];
extern volatile double                glob_buffer[8000];
#endif

Both projects are compiled with "-mv6600 -g -O0"

When I execute project on the hardware using debug mode of CCS via Blackhawk XDS560v2-USB Mezzanine Emulator and view the contents of glob_SNAFU[0], it's value at the end of execution is -518969491456.0 rather than expected 0.001. I currenly run it only on a single core. Both projects have the same sections included in the linker command file. The only difference being that the linker command file of the second project explicitly includes the .out file of the first project. Note: earlier attempts with integers and pointers resulted in correct values being assigned.

I'm using:

CCS Version: 5.0.1.201105110900

Code Generation Tools: TI v7.2.1 (according to project preferences)

C6000 Code Generation Tools: v7.2.0.0 (according to Eclipse Installation Details)

  • I'm not sure that marking a variable as volatile is sufficient for enforcing writebacks.  Have you tried turning-off or writeback-invalidating caches? The CSL library has some functions to provide this functionality.

     

    You might also want to try aligning each of the variables to a cacheline

    #pragma DATA_ALIGN(glob_buffer, 128)

  • I tried both writeback-invalidating the L2 cache and aligning the variables to a cacheline, but to na avail. glob_SNAFU[0] still starts as 0.0 when loading the program and gets changed to -518969491456.0

    current code, second project:

    #include <c6x.h>
    #include "memory.h"
    #define L2WIBAR (0x01844010); // SPRUGW0B, table 4-9
    void main(void)
    {
        volatile double *vdref;
        uint32_t *uiptr;
        vdref = glob_SNAFU;
        *vdref++ = 0.001;
        uiptr = (uint32_t *) L2WIBAR;
        uiptr[0] = (uint32_t) glob_SNAFU;
        uiptr[1] = 2;
        asm("    MFENCE");
        for(;;){}
    }

    current code, first project:

    #include <c6x.h>
    #pragma DATA_SECTION(gptr_buffer, ".shared")
    #pragma DATA_SECTION(glob_SNAFU, ".shared")
    #pragma DATA_SECTION(glob_buffer, ".shared")
    #pragma DATA_ALIGN(glob_buffer, 128)
    #pragma DATA_ALIGN(glob_SNAFU, 128)
    #pragma DATA_ALIGN(gptr_buffer, 128)
    volatile double            *gptr_buffer;
    volatile double            glob_SNAFU[4];
    volatile double            glob_buffer[8000];

     

  • There shouldn't be any particular reason that it's not working. I guess if the other data types worked, then your global memory is configured correctly.

    Is it absolutely necessary to avoid using CSL? Using it lets you avoid using error-prone explicit registers :/ Using the CACHE functions should get you the exact functionality you need -- and you do not need to include SYS/BIOS, just the library file (libCSL.a?) in the CSL directory

    And btw, using _mfence() should be good enough without using the asm() command

    Also try just going back to simple roots like:

    void main(void) {

      double *dp = glob_SNAFU;

      dp[0] = 0.01;

      // CACHE L1 writeback

      // CACHE L2 writeback

    for (;;) { }

    }

  • Found the problem.

    The value is only displayed wrong in Variables and Expressions views of the debugger. When the same spot in the memory is viewed through the memory browser it shows the correct value (in hexadecimal though, so it wasn't immediately obvious).

    I'm not sure this gives me much confidence in the debugger though.

  • Well, that's good to know that it's not incorrect.

     

    When you debug code that was built with optimizations, it's hard to replicate values exactly (that's why "Debug" is "Debug"!).  In my experience, when any of your values are stored in named registers in the variable monitor, then stepping through the code doesn't match what your original source code dictates.  For example, the final value may still be waiting until after the infinite loop to be written back.

     

    Summary: when you build with optimizations, don't expect debugging tools to work exactly.

  • This code wasn't built with optimizations (I explicitly specified -O0 to be sure that no optimizations would be present in the code), as I'm fully aware that once optimizations are used then the assembly won't match the c code line-to-line. I'm still not certain what causes this behaviour in the debugger. The problem persists when switching to non-volatile doubles.