D
Dirk Zabel
Hi,
I get unexpected behaviour from some code which was part of a
manufacturer-supplied library for hardware-related functions
(programming internal flash memory). I would like to get your opinion if
compiler or the code is the culprit.
The compiler is gcc-arm 4.5.1. When no optimization is selected, the
generated code looks as expected (surprise!). If size optimization is
selected with argument "-Os", the getstatus() call inside the loop is
removed.
I stripped down the code as far as possible, so it is more or less
abstract now.
--------------- snip --------------------------------
typedef enum {
st_busy, st_complete, st_timeout
} status_t;
typedef struct
{
volatile uint32_t CR;
volatile uint32_t SR;
} hw_reg_t;
extern hw_reg_t statusreg;
/*
* Get status (busy or complete)
* from inspection of hardware status register
*/
status_t getstatus(void)
{
status_t rval;
if ((statusreg.SR & 1) == 1) {
rval = st_busy;
} else {
rval = st_complete;
}
return rval;
}
/*
* wait until hardware operation is complete or
* timeout occurred
*/
status_t wait_for_operation(unsigned long Timeout)
{
status_t status;
status = getstatus();
while((status == st_busy) && (Timeout != 0)) {
status = getstatus(); /* <- optimized out! */
Timeout--;
}
if(Timeout == 0 && status == st_busy ) {
status = st_timeout;
}
return status;
}
--------------- snip --------------------------------
If I remove the volatile qualifiers from the struct members and instead
put volatile in front of the variable declaration, the problem vanishes:
--------------- snip --------------------------------
typedef struct
{
uint32_t CR;
uint32_t SR;
} hw_reg_t;
extern volatile hw_reg_t statusreg;
--------------- snip --------------------------------
Btw, it also does not occur if I access the status register inline in
wait_for_operation() instead of calling getstatus().
Is this a compiler error or are the volatile declarations inside the
typedef unsufficient?
Regards
Dirk
I get unexpected behaviour from some code which was part of a
manufacturer-supplied library for hardware-related functions
(programming internal flash memory). I would like to get your opinion if
compiler or the code is the culprit.
The compiler is gcc-arm 4.5.1. When no optimization is selected, the
generated code looks as expected (surprise!). If size optimization is
selected with argument "-Os", the getstatus() call inside the loop is
removed.
I stripped down the code as far as possible, so it is more or less
abstract now.
--------------- snip --------------------------------
typedef enum {
st_busy, st_complete, st_timeout
} status_t;
typedef struct
{
volatile uint32_t CR;
volatile uint32_t SR;
} hw_reg_t;
extern hw_reg_t statusreg;
/*
* Get status (busy or complete)
* from inspection of hardware status register
*/
status_t getstatus(void)
{
status_t rval;
if ((statusreg.SR & 1) == 1) {
rval = st_busy;
} else {
rval = st_complete;
}
return rval;
}
/*
* wait until hardware operation is complete or
* timeout occurred
*/
status_t wait_for_operation(unsigned long Timeout)
{
status_t status;
status = getstatus();
while((status == st_busy) && (Timeout != 0)) {
status = getstatus(); /* <- optimized out! */
Timeout--;
}
if(Timeout == 0 && status == st_busy ) {
status = st_timeout;
}
return status;
}
--------------- snip --------------------------------
If I remove the volatile qualifiers from the struct members and instead
put volatile in front of the variable declaration, the problem vanishes:
--------------- snip --------------------------------
typedef struct
{
uint32_t CR;
uint32_t SR;
} hw_reg_t;
extern volatile hw_reg_t statusreg;
--------------- snip --------------------------------
Btw, it also does not occur if I access the status register inline in
wait_for_operation() instead of calling getstatus().
Is this a compiler error or are the volatile declarations inside the
typedef unsufficient?
Regards
Dirk