Hi, I've recently been experiencing some concern regarding the behaviour of a program, for which the optimiser, when set to favour size [OPTIMIZE (6, SIZE)], occasionally leads to the contents of a global variable getting trashed/overwritten. If the optimisation settings are altered to favour speed, this no longer happens. It appears not to be an issue with specific XDATA address (where the variable resides), since changing the variables location doesn't prevent this from happening. The variable in question is only ever modified via a single increment within a timer interrupt function. Has anyone else experienced anything like this? IDE: uV2 Compiler: V6.23a Link/Loc: V4.23 Thanks for any illumination... David
OK- Found it! The problem was traced to two interrupt routines with different priorities both using the same register bank. One of the interrupt routines is responsible for the modification of the variable in question, so when this is pre-empted by the second higher priority interrupt, the contents of the common register bank get modified, with obvious consequences for the lower priority isr's data. Re-evaluating the isr priorities / register banks in order to safeguard against this has eliminated the problem. Just thought I'd let you all know, in case anyone experiences this sort of thing for themselves...
OK, I use Keil C on a Dallas 87C530 with proprietary hardware in an embedded system written mostly in C, but with some assembler. My code uses only one register set - set 0 - for the main thread and for ISRs. [I have some functions called from the main thread AND from ISRs, and this seemed the easiest way of avoiding problems.] Now I'm running out of program space, so I'm experimenting with optimisation. Current software works fine with optimisation level 1 (dead code elimination) and "favor speed". When I move up to the top - level 9 - I get the problem described in this thread. A local function variable changes value after an ISR is called. I need more optimisation to fit the code I have - and have yet to write - into the available space. So I need to track down and eliminate the problems I have. Any advice or suggestions gratefully accepted! TIA. Steve Merrick Software Designer Tribal Data Solutions
Calling functions from the main thread and from an ISR is potentially very dangerous. Personally, I only do this when I am very sure of what exactly is going to happen (e.g. assembly language functions I have written myself). How did you discover that a variable was getting changed by the ISR? Were you looking with the simulator for example? Does the function actually work OK? The optimiser can cause all sorts of odd things to apparently happen. For example, a variable may be assigned to registers, but when the function no longer needs that variable another variable may be assigned to the same registers. The program works OK, but looking at things using the simulator (etc) can get rather confusing. If you need to check things in detail, there is no substitute for looking at the object code itself. If you want everything to use just one register bank then you should never use the "using" keyword. The ISR should save and restore the value of all registers that it is going to use. If you do use the "using" keyword, the compiler just assumes that it can switch to that register bank safely and makes no checks that you are getting it right, so check very carefully.
<Calling functions from the main thread and from an ISR is potentially very dangerous.> Yes, I know. ;-) An example of a function called from the main thread and an ISR is a circular-buffer function. The main thread writes to the buffer, and the ISR reads from it (or vice versa). Thus the main thread (or an ISR) calls both the read- and write-buffer function. <How did you discover that a variable was getting changed by the ISR? Were you looking with the simulator for example? Does the function actually work OK?> Yes. Yes. With optimisation set to level 1, all works as expected. <If you want everything to use just one register bank then you should never use the "using" keyword.> Yes, I discovered this the hard way! Thanks anyway for the tip. :-) Are there any lists of 'general' problems that can occur with optimisation, and how they can best be avoided? Steve Merrick Software Designer Tribal Data Solutions
Do you receive ANY warnings from the compiler or linker? Jon
one register set - set 0 - for the main thread and for ISRs Which will guarantee erratic behaviour. The reason you see it more/only in some cases is purely due to timing which should be irrelevant to your code. Erik
Jon: I receive no compiler or linker errors or warnings. Erik: Please can you explain how "one register set ... will guarantee erratic behaviour."? It will certainly be less efficient, but if the context is saved and restored correctly, the use of a single register set should not introduce a risk of any sort, as I understand it. What am I missing, please? Steve Merrick Software Designer Tribal Data Solutions
View all questions in Keil forum