I've come across a bug in IAR (lastest version, latest patches).
I have reduced it down to a simple one-line function.
It appears at every optimization level except "None".
I have emailed John Regehr (see his papers on C compiler correctness) and Nigel
Jones (http://embeddedgurus.com/stack-overflow/) who concurred that this is a
compiler bug and not some C language ambiguity. I have contacted IAR
support/development but they don't acknowledge it is a bug.
I hope that the IAR gentleman (Anders) who posts in this forum can help to get
this resolved. This is a very common construct and I don't know if it affects
other IAR target platforms.
I found this since I tend to compile my applications with multiple compilers to
ensure that they always behave identically.
Buggy function
--------------------------------------------
void iar_buggy_func(unsigned char ch)
{
/* Some simple steps to initialze dma omitted.
* But occurs even if they are ommitted */
/* ..... */
DMA1SZ = (uint16_t) &ch;
/* .... */
/* Other steps omitted to wait for dma completion */
}
---------------------------------------------
It occurs with any volatile hardware register as in
----------------------------------------
unsigned char volatile * volatile v3;
void iar_buggy_func3(unsigned char ch)
{
v3 = &ch;
}
---------------------------------------------------
What is the Bug?
Note that the address of the parameter is taken.
The compiler should put this on the stack or some place in memory and then
assign the volatile hardware register this address.
The assembly generated by the above function is
------------------------------
iar_buggy_func3:
004080 8321 decd.w SP
v3 = &ch;
004082 4182 1102 mov.w SP,&v3
004086 5321 incd.w SP
004088 4130 ret
------------------------------
Note, that stack space is allocated at the beginning of the
function and released at the end of the function. But the value
of the parameter ch is not stored on the stack.
The volatile register is set to the SP (stack pointer), but
the paramter "ch" is NOT stored at this memory location.
The bug does not occur if
1) Optimization level "None"
2) Another function call f() or even intrinsic function like nop()
is present within the function.
The correct assembly should be
-------------------
iar_buggy_func:
00403E 124C push.b R12
__no_operation();
004040 4303 nop
DMA1SA = (uint16_t)src;
004042 4182 01EA mov.w SP,&DMA1SA
}
004046 5321 incd.w SP
004048 4130 ret
-----------------------------------------------
Note that in this case, the "push" instruction stores the parameter value
(passed in R12) onto the stack.
=====================================================
I've contacted IAR support, but they have blown me off by saying things such as:
1) It may be a glitch that may be fixed in the next release.
2) High optimization may not produce the code intended
3) Providing me with workarounds for this specific function.
and here is the response from IAR development.
>>>>> IAR development response ----------------------------
To condense the problem, we have a function that looks like the following:
volatile unsigned char * v;
void iar_buggy_func(unsigned char ch)
{
v = & ch;
}
In the report you correctly noted that the value of "ch" was never written to
the stack.
When it comes to "volatile", the basic rule is that anything that has some kind
of side-effect or could be accessed by the underlying hardware should be
declared to be "volatile".
In this case, when writing to "v", both "v" and "ch" is accessed by the
hardware. Hence, both should be declared "volatile".
As "ch" is a parameter, it is possible to assign it to a local volatile variable
before the assignment, for example:
volatile unsigned char * v;
void iar_buggy_func(unsigned char ch)
{
volatile unsigned char ch2 = ch;
v = & ch2;
}
>>>> Done IAR development response -----------------------
This is not correct. It doesn't matter if ch is volatile or not.
The correct assignment must happen.
--------------------------
----------------------------------------------------------
Thanks very much.
Ratish Punnoose
-------------------------------------------