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.

Bug in V6.1.15 of linux C compiler?

Other Parts Discussed in Thread: OMAP-L138

Build the following project (I use gnumake). Load the file (note the target is C6418) and add the p structure to the watch window. Then single-step through the line that assigns 1 to the "p->mbrToFirstSectorCount = 1;" line. Note that the endCyl element is modified instead of the mbrToFirstSectorCount.

****C File****

#include <stdint.h>
typedef struct
{
  uint8_t                   state;
  uint8_t                   beginHead;
  uint16_t                  beginCyl;
  uint8_t                   type;
  uint8_t                   endHead;
  uint16_t                  endCyl;
  uint32_t                  mbrToFirstSectorCount; 
  uint32_t                  sectorCount;           
} FAT_PARTITIONENTRY_T;

FAT_PARTITIONENTRY_T* p;

void main(void)
{
  p = (FAT_PARTITIONENTRY_T*)0x800001BE;
  p->mbrToFirstSectorCount = 1;
}

**** GnuMake File****

 

./test.out : ./test.obj
    /home/fat/dsp/code/tool/cgtools/bin/lnk6x   -I /home/fat/dsp/code/tool/cgtools/lib/  ./test.obj -o ./test.out -m ./test.map  -c -e _c_int00 -w -stack0x4000

./test.obj : ./test.c
    /home/fat/dsp/code/tool/cgtools/bin/cl6x -c ./test.c  -g -mu -mv6400 --mem_model:data=far -dCHIP_6418 -d_TMS320C6X -d_TMS320C6400 -d_6x_ -dTARGET_DSP_64X -dPLATFORM_LINUX -i/home/fat/dsp/code/tool/cgtools/include/

clean :
    -rm ./test.obj ./test.out

ci :
    svn ci ../../. -m "structure testbench checkin"

  • This is a good example of why you should not hard-code addresses. You have violated the alignment requirement for the struct to which p is pointing, which should be at least 32-bit aligned. If you let the compiler allocate the space, it would work fine, such as changing a few lines to

    FAT_PARTITIONENTRY_T* p;
    FAT_PARTITIONENTRY_T PartEntry;

    void main(void)
    {
    //  p = (FAT_PARTITIONENTRY_T*)0x800001BE;
      p = &PartEntry;
      p->mbrToFirstSectorCount = 1;
    }

    The compiler assumes the proper alignment and the CCS watch window is not aware of that alignment requirement. The problem also goes away if you change the address to 0x800001BC which is what the compiler is assuming as an aligned starting address for the struct.

  • Randy,

    It is quite interesting that this is how you frame things.

    Here is how I frame this situation, after having been working in
    embedded since 1979. When the TI compiler designers decided to
    *constrain* programmers to align their structures to addresses based
    on the largest element in the structure, they began to create a tool
    that was a stumbling block to the programmer instead of a help.

    In case you hadn't noticed, this is a piece of a FAT16 file system. I
    am not at liberty to realign the data structures - they are specified
    by the FAT16 system.

    --Randy

  • Randy,

    I would enjoy a cup of coffee with you to go over the days before High-Level Languages and to hear about your experiences. I am sure they are numerous and fun. If you like trivia, the photo in my avatar is me looking at a new TI HLL debugger on an IBM PC-AT. Not taken in 79, but we're at least in the same fraternity.

    I *did not* notice the FAT16 relevance, but that may be forgivable, no? There must be a good reason why FAT16 dictates where the struct is stored in the DSP's memory, so no explanation is needed.

    If you want help completing the project, please let us know. The answers will either be with the STNxx/LDNxx assembly instructions that Mariana told you about in your Basic Machine Level Word Alignment Question thread, or the equivalent C intrinsics, _mem2/4/8. Those will be slower than dong aligned accesses but will get the data the way you want. Unfortunately, it will be outside the compiler's purity. Often, we use these to copy from/to a non-aligned struct to/from an aligned struct, especially when holes exist; in your case, it looks like you could just copy the struct to an aligned location and access it easily there.

    You might also prefer moving to one of our multi-core devices like the OMAP-L138. The C674x core would give you the high-performance-per-clock-cycle you need for DSP code and the ARM Cortex-A8 would give you a more familiar C experience for peripheral accesses like your FAT16. There are negative tradeoffs, too, but you can work through those for your application as needed.

    Randy

  • Hi Randy,

    I was just going to post a follow-up apologizing for my tone in my previous post. I'm pretty sure you didn't personally design the C6000 compiler, and I realize you are here to help us. I apologize for blowing off steam on your track.

    Are you near Raleigh, NC? If so, perhaps we could do just that (have a cup of joe). I'd like to hear your glory stories as well... :0

    Regarding your suggested solutions, I'm taking another approach: i've basically changed my paradigm from a) having structures representing the actual data structures located in the FAT media (SDRAM), to b) have structures having pointers to the actual elements but located in internal RAM. Setting the pointers correctly was a little painful but I believe I'm through it now.

    We can't change cores - firstly we can't respin the board, and secondly the current board is based on the Orsys module. FYI, our current design is based on a PIC32 with USB interface (implementing a MSD) talking via HPI. There are probably better ways to skin this cat today but this design was set to traces about 2 years back.

    Thanks for discussing the issues with me. The discussion helps me think through things and sort them out (and show me where I'm blind!).

    -Randy

  • Lemme ask another question. Forget about structures. Will the compiler allow you to write, e.g., a 32-bit variable at an unaligned place.

    Example:

    #include <stdint.h>

    uint32_t* x;

    void main(void)

    {

      x = 0x80000003;

      *x = 1;

    }

     

    Will this work correctly?

    --Randy

  • No. The compiler always assumes the alignment defined for the target device. And for the C6000 compiler it will always assume a 32-bit word is 32-bit-aligned.

    You can replace

    Randy Yates said:
    *x = 1;

    with

    new said:
    _mem4(x) = 1;

    to get an unaligned write.

  • I don't think this post is necessary, but just in case anyone thinks a compiler expert really needs to weigh in here ...

    I confirm that Randy nailed every point on this one.  He always does.

    Thanks and regards,

    -George

     

  • Randy,

     

    You wrote: " The compiler always assumes the alignment defined for the target device." What do you mean by "the alignment defined for the target device"?

    The problem, as I see it, is that the "device" allows alignment to the byte level (via STNxx/LDNxx).

     

    Let me make my point as simple as possible: the compiler prevents the user from accessing capabilities the basic machine has. Why? Why must I use a non-C intrinsic?Why must I go through data-copying hoops to do what should be a trivial access in a high-level language?

    I realize there may be optimization issues, but rather than hamstring an entire capability out of the compiler, why not provide alignment (or non-alignment, depending on the default) pragmas or somesuch? It just seems extreme to hamstring users this way, IMO.


    --Randy

  • The STNxx/LDNxx instructions are not as cheap as their aligned counterparts.  You can only have one non-aligned memory access instruction in an execute package (a group of instructions which executes in parallel).  You can have two aligned memory access instructions in an execute packet.  In a software pipelined loop, this is a significant advantage.

    You also have to consider history.  Older C6000 devices do not have non-aligned memory access instructions.  Thus alignment was absolutely required.  And since code across compiler releases must remain compatible, the alignment remains.

    The C language itself does not provide any way to indicate that data is aligned or not.  While it is easy to conceive of how you could handle alignment specification with regard to data definition, what about data access?  Particularly pointers?  The alignment property amounts to another address bit for which there is no storage.  I suppose you could consider using non-aligned access all the time, but that is just too expensive for what you get.  The point is that there are no good solutions at the language level.

    The x86 devices solve this problem throwing a bunch of HW at it.  If an aligned instruction sees an odd address, it handles it properly, but takes more cycles to do it.  I'm no HW expert, but I expect that takes more power, heat, cycles, etc. than DSP users are willing to pay.

    Thanks and regards,

    -George