sprintf and migration to IAR EWARM 5

frankandersen wrote on Thursday, March 27, 2008:

Hi,

I have a problem with using sprintf after the migration from v4 to v5, I think it is something with the new calling convention used by IAR EAWARM v5. When converting float to strings, it just outputs eg. 0.0

I have tried to set the portBYTE_ALIGNMENT to 8, and that did fix the problem for a while, until I discovered that I have forgotten to reserve room for the IRQ stack. I reserved 512 bytes for the IRQ and it is aligned with 8.

I am working on STR710.

From the Migration Guide:
Calling convention
The calling convention used by the compiler has changed. In version 4.x, the stack is by
default aligned to 4, but it is possible to align the stack to 8 according to the Advanced
RISC Machines Ltd Arm/Thumb Procedure Call Standard (ATPCS). In version 5.x, the
compiler instead follows the ARM Architecture Procedure Call Standard (AAPCS).
This means that the stack is now aligned to 8 bytes.

Does anyone has an idea or has the same problem?

Best regards,

Frank Andersen

jorick23 wrote on Thursday, March 27, 2008:

I had the same problem.  It’s much worse than you’ve been seeing.  The problem occurs when any 8 byte variable gets passed to a function.  This includes doubles, long longs, and even floats (which are converted to doubles automatically in printf and sprintf).

It appears to be an alignment problem, not on the stack but in the registers used to pass arguments to functions.  The first few arguments are sent in registers and the overflow (if any) is sent on the stack.

Here’s an example function:

void TestPrintf (void) {
   float FTest;

   FTest = 41235.7;
   printf ("%f", FTest);
}

When you run the code in the debugger, you will see that the double going into printf is sent in registers R4:R5.  But if you debug the printf function, you’ll see that it expects the variables in registers R3:R4.  You were lucky because you used a value that ended up being 0.  If you use 41235.7, the value you get is 26815622342248577624559400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 which crashes the processor miserably because the stack just got blown to the moon!

IAR gives you the ability to align the stack to either 4 or 8 in version 4 but took away that capability in version 5.  So the stack is stuck at 8.  Rebuilding the C Runtime Library didn’t help anything.

I sent a bug report to IAR on the issue but their tech support person sent back a very inane reply: "I am having no problems doing this with EWARM version 5.11A. This is also full printf formatter. Please see my screenshot. Thank you."  Included was a 5 MB bitmap showing that it worked on his machine (ever heard of jpeg?  Sheesh!).  What the heck???  My company is paying good money for tech support and I get a response like that?

After further communications with someone higher up at IAR, I couldn’t get a resolution to the problem.  So I regressed to version 4.  I suggest you do the same and avoid some big headaches.

My specs:

Processor: STR750 w/128K RAM
Current IAR version: 4.42a
Stack alignment: 4 bytes

frankandersen wrote on Friday, March 28, 2008:

Hi Ricky,

Thx, but I would really like to use the IAR 5.xx as we paid for this.

The thing I do not understand is why, it works when called from one task, but not from another. As I would think that the parameters always would end up in the registers?

Best regards,

Frank Andersen

jorick23 wrote on Friday, March 28, 2008:

The parameters don’t always end up in registers.  If you do an sprintf (Buffer, “%d %f”, Integer, Float), the buffer, format string, and integer end up in registers but the float gets passed on the stack.  The float has to be the first argument after the format string in order for it to be passed in registers.  So if your float is far enough down the line, it shouldn’t be affected because it isn’t in a register pair.

If you get a resolution to this problem, please post it.  I’d like to get it resolved too, but I don’t have the time to wrangle with a bunch of brainless tech people.

enrico_adelco wrote on Monday, July 07, 2008:

Hi,
I had same problems with IAR 5.xx and sprintf of float/double. I solved my problem patching "pxPortInitialiseStack" function in my port.c file of FreeRTOS source as follow:

portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
{
    portSTACK_TYPE *pxOriginalTOS;
#if (__IAR_SYSTEMS_ICC__ >= 6) /* if EW 5.x or higher */
    if (((portBASE_TYPE)pxTopOfStack) & 0x7)
    {
        pxTopOfStack = (portSTACK_TYPE *)(((portBASE_TYPE)pxTopOfStack) & ~0x7);
    }
#endif   
    pxOriginalTOS = pxTopOfStack;

    /* Setup the initial stack of the task.  The stack is set exactly as
    expected by the portRESTORE_CONTEXT() macro. */

    /* First on the stack is the return address - which in this case is the
    start of the task.  The offset is added to make the return address appear
    as it would within an IRQ ISR. */
    *pxTopOfStack = ( portSTACK_TYPE ) pxCode + portINSTRUCTION_SIZE;
    pxTopOfStack–;


So I’m sure that task’s stack will be 8 bytes aligned as required from IAR EW 5.x
I hope this modification will be soon available in some new ports for IAR EW 5.x + ARM

I’m using a NXP LPC2478  with IAR EW 5.11
Bye
Enrico Dalla Mariga

davedoors wrote on Monday, July 07, 2008:

Would simply setting portBYTE_ALIGNMENT to 8 in portmacro.h fix this?

enrico_adelco wrote on Tuesday, July 08, 2008:

No, as portBYTE_ALIGNMENT is not used in IAR-LPC2000 demo sources. In addition, i’m using heap_3.c as dynamic allocation so any changes to portBYTE_ALIGNMENT has no effect for me.
As you can see, with these changes, my sources will be portable for IAR EW < 5.x and I have not to remember to change macro if I use another compiler version…

zed0x00 wrote on Tuesday, July 08, 2008:

#if (__IAR_SYSTEMS_ICC__ >= 6) /* if EW 5.x or higher */
__________________________^^^ Mistake in IAR C Development Guide :(.

#if (__IAR_SYSTEMS_ICC__ >= 7) /* if EW 5.x or higher */

enrico_adelco wrote on Wednesday, July 09, 2008:

That’s right, thank you very much!

frankandersen wrote on Tuesday, July 15, 2008:

Hi Enrico,

Thank you very much, it seems to have curred by problem also.

Best regards,

Frank Andersen

vinay1 wrote on Tuesday, July 22, 2008:

Hi,

This may be resolved by changing the printf formatter option to "full" :

"project options->General Options->Library Options->printf formatter"

regards,
vinay