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.

TMS320F28379D: Copy from EMIF address produces wrong value

Part Number: TMS320F28379D


I've run into quite a confounding situation and would appreciate any advice. I have a EMIF CS2 configured for 32 bit interface, with all the timings set to the slowest possible options. Normal mode is being used with extended wait time enabled. When stepping through a debugger, a function that copies values from this EMIF occasionally copies an incorrect value, but actually checking the value at that EMIF address in JTAG shows the correct value.

typedef union Field {
    float32_t f32;
    int32_t i32;
    uint32_t u32;
} Field;

typedef union {
    struct {
        uint8_t id:8;
        State state:8;  // Enum defined elsewhere
        uint8_t _16:4;
        bool message_refuse:1;
        uint8_t _21:3;
        MessageType message_type:8;  // Enum defined elsewhere
    };
    uint32_t all;
    struct {
        uint16_t lower;
        uint16_t upper;
    };
} Header;

typedef union {
    struct {
        uint8_t bcc:8;
        uint8_t _8:8;
        uint8_t speed:8;
        uint8_t acceleration:8;
    };
    uint32_t all;
    struct {
        uint16_t lower;
        uint16_t upper;
    };
} Footer;

typedef struct Message {
    Header header;
    Field sections[6];
    Footer footer;
} Message;

Message volatile const* const RECEIVE_MESSAGE = SOME_EMIF_ADDRESS;

void readMessage(Message* message_out) {
    Message volatile const* in = RECEIVE_MESSAGE;
    
    message_out->footer.all = in->footer.all;
    DELAY_US(0.2);

    message_out->header.all = in->header.all;
    DELAY_US(0.2);

    // Read sections
    for (int16_t i = 0; i < 6; ++i) {
        message_out->sections[i].u32 = in->sections[i].u32;
        DELAY_US(0.2);
    }
}

Example definitions above showing a structured read of an EMIF address. Using the `readMessage` function, the `message_out` always produces the correct header/sections, but seems to occasionally fail in the footer's `bcc` code (always with the same value too, where it should be 0x3 but instead is 0x10). The most interesting thing is that setting a breakpoint and observing the value in debugger, the footer is correct within the actual EMIF address, but only in `message_out` the `bcc` code is incorrect. This is also somewhat random/infrequent.

To try to resolve this, I have tried lowering the EMIF timings configuration to the slowest available options, adding various amounts of delay within the read function, reordering the copies within the delay function, and copying the footer from the EMIF address multiple times within the read function. All of this produced no changes in the results (intermittent footer `bcc` error of 0x10 instead of 0x3, only in copied `message_out`).

Does anyone have experience with similar behavior? At this point I am not suspecting the EMIF itself as it produces the correct value when directly read, but I do not understand how a simple copy from one memory region to another can produce the exact same error with the same values at random intervals.

  • Further updates; interrupts disabling and restore added to driver message reading, with no difference made. Screenshot of JTAG values on breakpoint at end of message reading function, notice the footer's `bcc` value difference between `in` (EMIF address) and the just-copied `message_out`, but all other fields/header remains consistent.

    Additionally, reading the EMIF address's footer one more time at the end of the function just to a local variable also stores the value 16 (0x10), despite 3 being latched according to JTAG.

  • One more additional update: Changed the location of footer in message to be right below header, and the same issue occurs. Could this be a compiler bug related to using bitfields in EMIF? (Note: the actual EMIF read is 32 bit, only the struct definition contains a bitfield. Seems unlikely that this could be related, but also cannot understand how this issue could occur otherwise. Moreover, the header is also defined as a union with a bitfield, similar to the footer, but the header does not have issues).

    Edit: Tested with EMIF addresses defined as an array of `uint32_t` rather than the message struct. Identical issue occurs; seems unrelated to the use of bitfields.

  • Many microcontrollers have alignment restrictions on memory access. Is the address (RECEIVE_MESSAG) aligned to 32-bit boundary? Does your setup support byte read/write EMIF memory? 

  • Yes, it is 32-bit boundary aligned! And additionally, I do not do byte read/write EMIF; I only read/write in 32 bit chunks. Unless, does setting up the EMIF for 32 bit access still do reads/writes by byte?

  • Hi John,

    "const volatile" is normally used for pointers to memory-mapped hardware registers. I am not very sure if "volatile const* const " in you code is ok for a pointer to EMIF memory.

  • The "const* const" should have no impact; it is merely a denotation that shows both the values at the pointer address and the pointer itself should never be assigned to by the DSP programmer. Do you mean to say that "volatile" should not be used for EMIF memory? How would the compiler's optimizer then understand that such pointer accesses should not be re-ordered/optimized out?

  • Ah, additionally; the "in" pointer shown in the JTAG debug session screenshot is showing the correct value, and only the copy to "message_out" is causing issues. Could the "volatile const*" usage somehow impact only the copy but not a direct read in JTAG?

  • I run the test for couple minutes, the code doesn't reach the bkpt (line 143). 

    BTW, what is the advantage or use "volatile const* const" in your code?

  • Interesting, thank you for trying on your end. Perhaps there is an intermittent hardware failure on one of our related board components, although I am still not sure how JTAG debug can then show the correct value...

    As for the "volatile const* const", the "const* const" portion is just so that we can receive adequate compiler warnings if there are any accidental attempts to write to the EMIF address (should be a read-only address). The "volatile" is just to avoid any problems when raising the compiler optimization level; we previously encountered issues interacting with these EMIF addresses when increasing the compiler optimization to -O4, but these issues appeared to be resolved with proper "volatile" annotations.

    As of now, it the issue still appears intermittently without the "volatile" as well. I will continue to test, also without the "const* const", and see if I can find any new results.

  • The compiler doesn’t perform optimization for the volatile variables. Please try a test using "const*" instead of "const* const". 

  • Yes, that is the purpose of using "volatile"; specifically to avoid the compiler performing unwanted optimizations. I have also tested using "const*" and just "*", and both produce the same results. "const* const" really should not make any difference, as the second "const" just indicates that the pointer address itself should not change to point to a new address.

  • Hi John,

    When you find the root cause, please keep us updated. Thanks