hello,
this the version of my keil µvision sofware:
IDE-Version: µVision3 V3.51
Tool Version Numbers: Toolchain Path: C:\Keil\C51\BIN\ C Compiler: C51.Exe V8.08 Assembler: A51.Exe V8.00d Linker/Locator: BL51.Exe V6.05 Librarian: LIB51.Exe V4.24 Hex Converter: OH51.Exe V2.6 CPU DLL: S8051.DLL V3.11 Dialog DLL: D500.DLL V2.46
my problem: I have a wrong compilation with the use a global bdata variable.
here is my code in multiple file:
global.c
#include global.h unsigned char bdata buffer; sbit buffer_0 = buffer^0; sbit buffer_1 = buffer^1; sbit buffer_2 = buffer^2; sbit buffer_3 = buffer^3; sbit buffer_4 = buffer^4; sbit buffer_5 = buffer^5; sbit buffer_6 = buffer^6; sbit buffer_7 = buffer^7; xdata struct struct_plateau plateau[6] _at_ 0x4001;
global.h
extern unsigned char bdata buffer; extern bit buffer_0; extern bit buffer_1; extern bit buffer_2; extern bit buffer_3; extern bit buffer_4; extern bit buffer_5; extern bit buffer_6; extern bit buffer_7; extern xdata struct struct_plateau plateau[6]; struct struct_plateau { unsigned char lampe_tilt_ou_bonus; unsigned char lampe_carte_et_stop; };
reglage.c
#include global.h void test_switch_bandeau_et_lampe_bandeau_et_tilt () { buffer = memorisation_lecture_switch_carte; plateau[0].lampe_carte_et_stop = buffer_0; //ligne 1 plateau[1].lampe_carte_et_stop = buffer_1; //ligne 2 plateau[2].lampe_carte_et_stop = buffer_2; //ligne 3 plateau[3].lampe_carte_et_stop = buffer_3; //ligne 4 plateau[4].lampe_carte_et_stop = buffer_4; //ligne 5 plateau[5].lampe_carte_et_stop = buffer_5; //ligne 6 buffer = memorisation_lecture_switch_stop; //don't compile this ligne 7 plateau[0].lampe_tilt_ou_bonus = buffer_0; //ligne 8 plateau[1].lampe_tilt_ou_bonus = buffer_1; //ligne 9 plateau[2].lampe_tilt_ou_bonus = buffer_2; //ligne 10 plateau[3].lampe_tilt_ou_bonus = buffer_3; //ligne 11 plateau[4].lampe_tilt_ou_bonus = buffer_4; //ligne 12 plateau[5].lampe_tilt_ou_bonus = buffer_5; //ligne 13 }
the problem is that the compilator don't take a look of the ligne 7. I have take a look in the desasembly file and It save the result of the ligne 1 to 6 in register R0 to R5 and restore this value in ligne 8 to 13.
I have try this second solution and all is ok
void test_switch_bandeau_et_lampe_bandeau_et_tilt () { unsigned char i; buffer = memorisation_lecture_switch_carte; for (i=0 ; i<6; i++) { if (buffer_0 == 0) { plateau[i].lampe_carte_et_stop = 0; } else { plateau[i].lampe_carte_et_stop = 1; } buffer >>= 1; } buffer = memorisation_lecture_switch_stop; for (i=0; i<6; i++) { if (buffer_0 == 0) { plateau[i].lampe_tilt_ou_bonus = 0; } else { plateau[i].lampe_tilt_ou_bonus = 1; } buffer >>= 1; } }
I have also try to declare directly de buffer in the reglage.c file without extern and all is ok, I have just this problem if the buffer_0 to buffer_7 are declare with extern in .h file.
what do you think about this ?
If you use extern, then the compiler will not know that the bit accesses are aliased with the "buffer" variable. So your function contains code that assigns multiple values to "buffer" but does not seem to make use of the value.
Are you sure that it isn't the first buffer assign that doesn't happen? I.e. that the compiler assumes that this value will be overwritten with the second value, and just assign this second value directly?
Having the variable volatile would force a need for performing all writes.
sbit buffer_0 = buffer^0; /*...*/ extern bit buffer_0;
Doesn't that look like a contradiction to you? sbit is not the same as bit. So what's happening is that, essentially, you're lying to the compiler while it's working on reglage.c. You've hidden from the compiler the information you now wonder it's not applying.
sbit doesn't follow the usual distinction between declaration and definition. It's the only memory class where you have to put the definition into the .h file.
If you see this page of the C51 user's guide :
http://www.keil.com/support/man/docs/c51/c51_le_bitaddrobj.htm
it's explain that using extern is ok for multiple file or module.
secondly, in the second solution (this solution work perfecly) with bit testing the value of buffer_0 to buffer_5 take the second value off buffer and all bit test are good.
in this page of the user guide: it's explain the use of sbit and bit
and here a exemple of declaration in .c file and extern in .h file
http://www.keil.com/forum/618/
See also: http://www.keil.com/forum/19527/
and: http://www.keil.com/support/docs/1175.htm
Yes, it does - but that is the way that Keil tell you to do it!
See: http://www.keil.com/support/docs/1175.htm
And see my rant at the end of this thread: http://www.keil.com/forum/618/ - that was 10 years ago; it doesn't seem to have improved.
I thing, with your response, that my syntax is corect,
for my problem, I think that is a bug of the compilator, Have I a too old version of keil ?
this problem is maybe not in the new version.
9.05
http://www.keil.com/download/product/
but that is the way that Keil tell you to do it!
Well, that means sbit and bdata cannot be used for the kind of thing the OP is trying to do.
In translation units other than the one holding the sbit definitions, there is no way for the compiler to know that those bit objects are actually sbits overlaying that particular bdata object. I.e. there's no way the compiler can know that writes to that bdata object cannot be interleaved with accesses to those particular bit variables.
What this example basically created is a secret union. It's a union because these are objects occupying the same space by design, and it's secret because the compiler doesn't know about it. And yes, that will cause problems as soon as the optimizer is used at all.
A possible solution to that might be to make both the bdata and bits volatile.