AnsweredAssumed Answered

Issue with powerpc-eabivle-gcc.exe, revision 4.9.4: printf sets upper 32 Bit of GPR6

Question asked by Peter Vranken on Jan 29, 2018
Latest reply on Feb 22, 2018 by Peter Vranken

The function printf from the new(c)lib can set the most significant 32 Bit of GPR 6. The upper 32 Bit of the GPR are normally not touched by the code emitted by the compiler. All samples initialize the upper half of the GPR to zero and this value is usually kept as long as the SW is running. Most calls of printf don't touch these bits neither but depending on the argument list it can happen. I could reduce the effect to this code fragment:

 

void main(void)
{
    /* The first operation of the main function is the call of ihw_initMcuCoreHW(). The
       assembler implemented startup code has brought the MCU in a preliminary (...) */
    ihw_initMcuCoreHW();

    printf( "%.6fs: chn 1: %.3fV = %.1fC, chn 10: %.3fV (%hu), chn 15: %.3fV,"
            " TSENS_0=%.1fC, TSENS_1=%.1fC\r\n"
          , 0x3ff0000000000000ull
          , 0x3fede35400000000ull
          , 0x4040b33340000000ull
          , 0x3ff3d70a40000000ull
          , 26214u
          , 0x3ffb916880000000ull
          , 0x40440cccc0000000ull
          , 0x4043e66660000000ull
          );
         
    /* Halt code execution by assertion. */
    assert(false);
}

 

A breakpoint has been set on entry of printf and on the assertion after exit from printf. The register GPR 6 has been inspected at both breakpoints, see attached screenshots.


The call of printf changes GPR6 from 0x0000000002021000 to 0x4001fdd80000000f. The upper half of GPR6 seems to contain a stack frame pointer after return.

 

It is not generally an error to use the upper 32 Bit of the GPRs but it's likely undesired by the implementors of printf and by mistake only that the change of the upper 32 Bit is not undone prior to return. Regardless of the observation, my application is fine and running stable.


To my opinion, a sub-function must not return with changed upper half word of a GPR. Instead it should consider these half words as non volatile. The context switches in my application are based on the EABI conventions and do not save/restore the upper 32 Bit of the GPR. If my application code would make use of the SPE vector commands then a switch to a task using printf could make the preempted SPE task fail.

 

Please note, the test call of printf to reproduce the problem happens while the handling of all External Interrupts is still disabled in the MSR. The problem really is in printf itself.

 

The MCU is an MPC5643L in LSM, relevant linker settings are:


-mcpu=e200z4 -mbig-endian -mno-vle -mspe -misel=yes -meabi -msdata=default -G8 -mregnames -mhard-float -fshort-double -Wl,-g --sysroot=$(dir $(gcc))../powerpc-eabivle/newlib -lm

 

All other details can be found at https://github.com/PeterVranken/TRK-USB-MPC5643L/tree/master/LSM/ADC.
Please comment.

 

Regards

Peter

Outcomes