compilation with optimisation for size code

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

compilation with optimisation for size code

1,274 Views
lpcware
NXP Employee
NXP Employee

Content originally posted in LPCWare by sicotc on Tue Jan 06 09:18:12 MST 2015
Hello,

 

I'm using LPC11E14 with lpcxpresso V7.4.0 [Build 229]
Without any optimisation code, everything works.
But when I use "optimize for size", the software stop.
After searching, I saw a bug in the assembler code, adr=4bc, 'jump to itself" :

 

 

000004ac <delay_ms>:
 4ac:b510      push{r4, lr}
 4ae:4c06      ldrr4, [pc, #24]; (4c8 <delay_ms+0x1c>)
 4b0:1c01      addsr1, r0, #0
 4b2:1c20      addsr0, r4, #0
 4b4:f7ff fff2 bl49c <timer_reset>
 4b8:7923      ldrbr3, [r4, #4]
 4ba:2b02      cmpr3, #2
 4bc:d000      beq.n4c0 <delay_ms+0x14>
 [color=#f33]4be:e7fe      b.n4be <delay_ms+0x12>[/color]
 4c0:2301      movsr3, #1
 4c2:7123      strbr3, [r4, #4]
 4c4:bd10      pop{r4, pc}
 4c6:46c0      nop; (mov r8, r8)
 4c8:10000018 .word0x10000018

 

 

the source code is :

void delay_ms(uint16_t time)
{ 
timer_reset(& delay_ms_v,time);
while(timer_expired_task(& delay_ms_v)==0)
{
}
}

 

 

find attached the workspace directory with the simplified project.
In debug mode, it is easy to locate where the code stop.
Is it possible to have a solution for this problem ?
Thanks
Sicotc

Original Attachment has been moved to: workspace_testBUG.zip

0 Kudos
Reply
5 Replies

1,207 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by sicotc on Wed Jan 07 05:31:07 MST 2015
thanks for your explanation.
0 Kudos
Reply

1,207 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Tue Jan 06 23:54:24 MST 2015

Quote: sicotc
thanks a lot,
the following code solve the problem :


It may have solved the problem, but was it the best option, or even the correct one?  Now function delay_ms() is 40 bytes long!

On top of that the problem was not in function delay_ms().

Because the typedef struct timer_t, and specifically the structure member "state",  was not declared volatile the compiler optimizations caused the code to hang in a loop in function timer_expired_task().  The optimizations placed "state" in a register and the compiler thought that it did not need to load the value of 'state' any longer because the value was already in a register .  Therefore the comparison of "state != timer_task_expired", as far as the compiler could tell, was never going to be triggered and that is why the compiler generated code for the never ending loop at address 4be.

4be:e7fe      b.n4be 


If you change the typedef struct timer_t in file timer.h to this
/**
 * \struct timer_t
 * \brief défintion de l'objet timer
 */
[color=#f00]volatile[/color] typedef struct
{
uint16_t count;/*!< valeur du compteur */
uint16_t initVAL;/*!< valeur d'initialisation du compteur */
timerState_t state; /*!< état du timer */
optionIT_t option;/*!< option pour le lancement de la fonction associée */
void (*TASK)(void);/*!< pointeur vers la fonction qui sera lancée à expiration du timer */
}timer_t;


and change function delay_ms in file timer.c to this
void delay_ms(uint16_t time)
{
timer_reset(& delay_ms_v,time);
while(!(timer_expired_task(& delay_ms_v)));
}


then you will have a very efficiently working function delay_ms() that is only 24 bytes long and the code does not hang in function timer_expired_task().

It may be that you only need to make the structure member "state" volatile instead of the entire structure.  I will leave that up to you to test.
0 Kudos
Reply

1,207 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Tue Jan 06 23:29:22 MST 2015
After looking at the rest of the functions in file timer.c, I found that the only place that you actually perform a read of any of the structure members is in the function timer_expired_task() and that structure member is "state".  Therefore it is probably safe to say that only the structure member that needs to be declared volatile within the structure definition is "state".

So the structure definition then becomes
/**
 * \struct timer_t
 * \brief défintion de l'objet timer
 */
typedef struct
{
uint16_t count;/*!< valeur du compteur */
uint16_t initVAL;/*!< valeur d'initialisation du compteur */
[color=#f00]volatile[/color] timerState_t state; /*!< état du timer */
optionIT_t option;/*!< option pour le lancement de la fonction associée */
void (*TASK)(void);/*!< pointeur vers la fonction qui sera lancée à expiration du timer */
}timer_t;

0 Kudos
Reply

1,207 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by sicotc on Tue Jan 06 13:52:48 MST 2015
thanks a lot,
the following code solve the problem :
void delay_ms(uint16_t time)
{
volatile int status=0;
timer_reset(& delay_ms_v,time);
while(!status)
{
status=timer_expired_task(& delay_ms_v);
}
}
0 Kudos
Reply

1,207 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by lpcxpresso-support on Tue Jan 06 09:24:12 MST 2015
Make sure you are using the 'volatile' keyword….

http://www.lpcware.com/content/faq/lpcxpresso/compiler-optimization

Regards,
LPCXpresso Support
0 Kudos
Reply