We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I am using an 8051 (C51/BL51) with no off-chip memory. I have two functions with parameters:
void Detect( U8 iLed )
and
static U8 INHSampleHandler( U16 u16Sample )
Now I understand that Keil will allocate a variable (in DATA) for these. The problem seems to be that the locator is using the same memory location for both. I cannot understand why.
Below are excerpts from the scratchpad showing 2 "D:0026H". These are the only places these symbols are declared. Any ideas what I'm doing wrong?
Thanks, Jeff
BL51 BANKED LINKER/LOCATER V5.12 07/14/2011 09:36:23 PAGE 1 BL51 BANKED LINKER/LOCATER V5.12, INVOKED BY: Z:\TOOLS\SOFTWARE\KEIL\BL51.EXE Z:\Software\FB_CPU_Init.obj, >> Z:\Software\Settings.obj, Z:\Software\Glo >> bals.obj, Z:\Software\Devices\Clock.obj, Z:\ >> Software\Devices\Flash.obj, Z:\Software\Devices\HMI.obj >> , Z:\Software\Devices\INH.obj, Z:\ >> Software\Devices\ADC.obj, Z:\Software\Devices\Timer.obj, Z >> :\Software\Builds\TestINH - 06-00039-21-09\Main.obj >> , Z:\Software\Test\Test_Button.obj, Z:\So >> ftware\Builds\TestINH - 06-00039-21-09\Version.obj TO Z:\ >> Software\Builds\TestINH - 06-00039-21-09\06-00039-21-09-xx.wsp >> RS (256) PL (68) PW (78) XDATA (?XD?SETTINGS (0X0)) CODE (?CO?VERSION (0X7 >> FC0)) MEMORY MODEL: SMALL Deleted for brevity ------- PROC _INHSAMPLEHANDLER D:0026H SYMBOL u16Sample C:0BF1H LINE# 150 C:0BF5H LINE# 151 C:0BF5H LINE# 207 C:0BF7H LINE# 208 ------- ENDPROC _INHSAMPLEHANDLER ------- ENDMOD INH Deleted for brevity C:09FEH PUBLIC _Detect C:074EH PUBLIC main ------- PROC _DETECT D:0026H SYMBOL iLed
Found the problem and fixed it. I had to remove the connection between the function that passed the function pointer from the function itself. This is explained in the App Note. (I was thrown off by the cryptic warning from the linker.)
Now both the parameter and local are unique in the data segment.
Call me happy.
"Found the problem and fixed it."
how about this little piece of code:
#include <regx51.h> #include <intrins.h> //test to see if var1/var2 overlay creates problems. //if var1/var2 overlaid incorrectly, P2 will be pulled down to 0 periodically. //otherwise, P2 = 0x22+1; #define NOP() _nop_() #define NOP2() {NOP(); NOP();} #define NOP4() {NOP2(); NOP2();} #define NOP8() {NOP4(); NOP4();} #define NOP16() {NOP8(); NOP8();} #define NOP32() {NOP16(); NOP16();} #define NOP64() {NOP32(); NOP32();} #define NOP128() {NOP64(); NOP64();} #define NOP256() {NOP128(); NOP128();} void sub1(unsigned char var1) { var1=0; //reset var1/var2 if (var1) var1=0; //make sure var1 is always 0 //P2=var1; //make sure tmr0 is working } void sub2(unsigned char var2) { var2=var2+1; //increment var1/var2 if (var2==0) var2=1; //make sure var2 is never zero NOP256(); NOP256(); //delay 512 ticks - create opportunity for tmr0 to fire at least once P2=var2; //output var2 on P0 } void tmr0_isr(void) interrupt TF0_VECTOR { sub1(0); //call sub1 periodically to reset var1/var2 } int main(void) { TR0=0; //turn off tmr0 TMOD = (TMOD & 0xf0) | 0x02; //tmr0 in mode 2 (auto reload tl0 with th0 TH0=-100; //tmr strikes every 100 ticks TL0=TH0; ET0=1; //enable tmr0 interrupt TR0=1; //turn on tmr0 EA=1; //enable global interrupt while (1) { sub2(35); } }
it follows the example you gave earlier, except that it uses a tmr isr to fire sub1() periodically.
you can play with the compiler settings to get var1/var2 to overlay. what do you think you will get on P2?
Having mocked you of having less curiosity than me, I could hardly ignore your request. (I had to change your header files as I don't have those - I'm using an 8051F930 - so perhaps it's not an apples-apples comparison.)
With optimization 4+ var1/var2 are at the same address. However the actual assembler code doesn't reference these and uses registers. Not a fair test.
With optimization at 2, var1/var2 do not overlay each other. I would not expect this program to write anything other than 36 to P2.
I have to change the code as follows to get the data to overlay:
static void (*mHandler)(unsigned int uData); void sub1(unsigned char var1) { var1=0; //reset var1/var2 if (var1) var1=0; //make sure var1 is always 0 //P2=var1; //make sure tmr0 is working } void sub2(unsigned char var2) { var2=var2+1; //increment var1/var2 if (var2==0) var2=1; //make sure var2 is never zero NOP256(); NOP256(); //delay 512 ticks - create opportunity for tmr0 to fire at least once P2=var2; //output var2 on P0 if ( var2 == 0 ) { P2 = 1; } } void tmr0_isr(void) interrupt 1 { // sub1(0); (*mHandler)(0); //call sub1 periodically to reset var1/var2 } int main(void) { mHandler = sub1; TR0=0; //turn off tmr0 TMOD = (TMOD & 0xf0) | 0x02; //tmr0 in mode 2 (auto reload tl0 with th0 TH0=-100; //tmr strikes every 100 ticks TL0=TH0; ET0=1; //enable tmr0 interrupt TR0=1; //turn on tmr0 EA=1; //enable global interrupt while (1) { sub2(35); } }
This code seems to suffer from the same problem as my program. In fact, from within Sub2 I got var2 == 0.
"This code seems to suffer from the same problem as my program. In fact, from within Sub2 I got var2 == 0."
if you really had curiosity, you probably would have run it on different platforms and observed the differences in behavior and asked yourself why.
I actually claimed to have a lack of curiosity - and proud of it.
Thanks to everyone here to for their contributions to a case solved. Especially to Ron who, strangely enough, found the solution but didn't recommend it.