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/TM4C129XNCZAD: unaligned access usage fault error due to structure not being aligned on 4-byte boundary

Part Number: TM4C129XNCZAD

Tool/software: TI C/C++ Compiler

One of my functions is getting a usage fault error indicating unaligned access when the following line of code executes:

    *so2est = -1.0F;

The so2est variable is a parameter that gets passed into the function.

The calling function is passing a pointer to a struct member as the so2est parameter. The struct is defined as:

struct SO2Result
{
  FloatSP   fUAArrayCombNorm[5];

  FloatSP   fUAArraySrc1[5];
  FloatSP   fUAArraySrc2[5];

  FloatSP   fUSArraySrc1[5];
  FloatSP   fUSArraySrc2[5];

  FloatSP   fMinErrSqAvg;

  FloatSP   fSO2Estimate;
  FloatSP   fSO2ErrSq;
};

Note: FloatSP is typdefed as float.

For some reason, the struct variable, even though it contains all floating point members, is being stored at at non-4-byte-aligned address:

As you can see, the address of the variable is 0x20010C3B, and address of the member being passed to the function is 0x20019CA3.

I do not understand why the compiler/linker is not automatically aligning this structure. I tried changing the project settings in CCS Build>ARM Compiler>Advanced Options>Runtime Model Options>Generate unaligned loads and stores to off, but that did not make a difference.

I also tried to use #pragma DATA_ALIGN, but since the variable is on the stack it would not accept it.

Any idea how I can get the strucutre to align properly?

I am running CCS version 8.0.0.00016 and the TI v18.1.1.LTS compiler version.

Regards,

Dave

  • This looks like a bug in the compiler.  That structure should be aligned on a 4 byte boundary, but it isn't.  My guess is that when it is local to a function, and other kinds of variables precede it on the stack frame, something goes wrong.  For the source file with the function that has the local resultSO2Current, please submit a test case as described in the article How to Submit a Compiler Test Case.

    Thanks and regards,

    -George

  • Thanks for the quick response, George. I will try to get a test case submitted as soon as possible.

    Regards,

    Dave

  • FYI, I am able to temporarily work around this issue by declaring the structure as static. That results in a properly aligned address.

    Regards,

    Dave
  • The issue is occurring in a source file that contains extremely proprietary code, so I am not able to follow the recommendations in the link you gave me. I will try to recreate the issue in a separate file that contains no proprietary information.

    Regards,

    Dave
  • I was unable to reproduce the issue from a clean start, so I stripped out as much of the proprietary code from the original file as I could. I will send the pre-processed file via private message.

    The resultSO2Current structure is being located at address 0x2002FB77, as shown in the following debugger output:

    The version of the compiler is 18.1.1.LTS. The compiler options are:

    "C:\\ti\\ccsv8\\utils\\bin\\gmake" -k -j 8 MP_Application/src/MP_TaskO2SatCalc.obj -O

    Building file: "../MP_Application/src/MP_TaskO2SatCalc.c"
    Invoking: ARM Compiler
    "C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.1.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me --opt_for_speed=0 --include_path="C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.1.LTS/include" --include_path="C:/Firmware/TripleRing/VIO_TIVA/MP_Application/inc" --include_path="C:/Firmware/TripleRing/VIO_TIVA" --include_path="C:/Firmware/TripleRing/VIO_TIVA/COTS/Micrium-uCOS-II/Micrium/Software/EvalBoards/TI/DK-TM4C129X/BSP" --include_path="C:/Firmware/TripleRing/VIO_TIVA/COTS/Micrium-uCOS-II/Micrium/Software/EvalBoards/TI/DK-TM4C129X/OS2" --include_path="C:/Firmware/TripleRing/VIO_TIVA/COTS/Micrium-uCOS-II/Micrium/Software/uC-CPU" --include_path="C:/Firmware/TripleRing/VIO_TIVA/COTS/Micrium-uCOS-II/Micrium/Software/uC-CPU/ARM-Cortex-M4/CCS" --include_path="C:/Firmware/TripleRing/VIO_TIVA/COTS/Micrium-uCOS-II/Micrium/Software/uC-LIB" --include_path="C:/Firmware/TripleRing/VIO_TIVA/COTS/Micrium-uCOS-II/Micrium/Software/uCOS-II/Source" --include_path="C:/Firmware/TripleRing/VIO_TIVA/COTS/Micrium-uCOS-II/Micrium/Software/uCOS-II/Ports/ARM-Cortex-M4/Generic/CCS" --include_path="C:/Firmware/TripleRing/VIO_TIVA/COTS/TivaWare" --include_path="C:/Firmware/TripleRing/VIO_TIVA/COTS/TivaWare/inc" --include_path="C:/Firmware/TripleRing/VIO_TIVA/COTS/TivaWare/driverlib" --include_path="C:/Firmware/TripleRing/VIO_TIVA/Platform/inc" --include_path="C:/Firmware/TripleRing/VIO_TIVA/Platform/Device/src" --include_path="C:/Firmware/TripleRing/VIO_TIVA/BSP/inc" --include_path="C:/Firmware/TripleRing/VIO_TIVA/COTS" --include_path="C:/Firmware/TripleRing/VIO_TIVA/COTS/Micrium-uCOS-II" --include_path="C:/Firmware/TripleRing/VIO_TIVA/COTS/Micrium-uCOS-II/Micrium/Software/uC-CPU/ARM-Cortex-M4/CCS" --define=ccs="ccs" --define=PART_TM4C129XNCZAD -g --gcc --preproc_only --preproc_with_compile --diag_suppress=9 --diag_warning=225 --diag_wrap=off --display_error_number --unaligned_access=on --abi=eabi --obj_directory="MP_Application/src" "../MP_Application/src/MP_TaskO2SatCalc.c"

    Note that the compiler generated a lot of warnings about variables being declared but not referenced, because I stripped out the code that referenced them.

    One interesting thing that I noticed about the code is that there is a #pragma pack directive that temporarily sets the packing to 1. I thought that might be the culprit, but removing the #pragma statements made no difference.

    Hope the info I am providing will allow you to easily track down the problem.

    Regards,

    Dave

  • Thank you for sending in a test case.  This is user error.

    One of these ...

    #pragma pack ( 1 )
    

    ... is in effect when this structure definition is seen ...

    Dave Hohl said:

    struct SO2Result
    {
    FloatSP fUAArrayCombNorm[5];

    FloatSP fUAArraySrc1[5];
    FloatSP fUAArraySrc2[5];

    FloatSP fUSArraySrc1[5];
    FloatSP fUSArraySrc2[5];

    FloatSP fMinErrSqAvg;

    FloatSP fSO2Estimate;
    FloatSP fSO2ErrSq;
    };


    Since this structure type contains all float members, the pack(1) has no effect on the layout of the structure.  But it does mean the compiler does not align the base address of a variable of this structure type.  Then you pass the address of one of the members of this structure variable to some other function.  That function presumes the pointer to a float is aligned.  It isn't, and things go downhill from there.

    The fix is to make sure #pragma pack(1) is not in effect for this structure type.

    Thanks and regards,

    -George

  • Hmmm, somehow the file I sent you does not match the code I thought I was using. I actually had tried pushing and popping the pack size on either size of the bitfield definition. And I even tried removing the #pragma pack statements, and it did not work. Maybe I messed up and was accidentally compiling a different version of the file than I thought. I will look into this when I get back to work on Monday.

    Regards,

    Dave
  • OK, I think I have figured out what is going on. I am porting some legacy code from the Sourcery CodeBench compiler to CCS. The code has numerous instances where the following is used:

    #pragma pack (1)

    ... // a struct definition

    #pragma pack()

    The #pragma pack() directive is intended to restore the packing to its default state. This works for Sourcery CodeBench, as well as IAR and GCC. However, it appears that the TI compiler does not support this.

    In the file I was working on, even when I completely removed the #pragma pack statements I still had an alignment problem. This is because the file includes header files that use the #pragma pack directive. So I need to update all the files in the project to use push/pop rather than rely on #pragma pack() to restore the default.

    Perhaps a feature request could be entered in the TI database asking that the use of #pragma pack() restore the default pack setting, so it would be compatible with other commonly used compilers?

    Regards,

    Dave

  • I suspect you misunderstand how #pragma pack works.  The pack attribute attaches to the struct type.  It remains, even if the range of #pragma pack(1) is ended by a subsequent #pragma pack().  For example ...

    #pragma pack(1)
    struct struct_type {
       /* field definitions here */
    };
    #pragma pack()
    
    struct struct_type struct_variable;

    Even though struct_variable is defined outside the range of #pragma pack(1), it is packed.  This is because struct_type is packed.

    Thanks and regards,

    -George

  • Hi, George,

    I do understand that the packing applies to the structure definition. I didn't think that the struct containing the float arrays was packed. But when I looked at the definition of the struct I discovered that it is indeed in the midst of a whole section that is using pack(1). I don't know why the original author of the code did this, or why it seems to work using the Sourcery compiler. But I think I know now how to fix things.

    Thanks for your help.

    Regards,

    Dave