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
If the two functions aren't calling each other and the compiler/linker can see that the two variables will never be needed at the same time - what is then wrong with optimizing the memory usage by using the same space for the two variables?
I see. In my case one of these functions is called by an ISR. So I changed my function declaration to
static U8 InhalationSampleHandler( volatile U16 u16Sample )
and now the locator keeps the data separate. Any idea if this is a guarantee that the linker will do the right thing?
Thanks for the help.
The Linker copes with that - or gives a warning when it can't.
What I meant was, does adding "volatile" to a parameter guarantee that the linker will not overlap it with another variable. Apparently it does not.
I un-did some of my work-arounds and those variables landed back on top of each other.
I guess I don't have a lot of functions called by ISRs, so a work-around is to use global variables. But I'd rather not. Is there a "right" way to do this?
Thanks.
"so a work-around"
why do you care, as long as the resulting code behaves correctly?
You seem to be trying to work around a problem that doesn't exist!
What the tools are doing is called Overlaying - it is a very well-established technique for getting around the fact that the 8051 has no stack suitable for the usual parameter passing & automatic variables.
Effectively, Overlaying does at link-time what "normal" compilers do with the stack at run-time. It does mean that parameters share memory locations - hence the name, "overlaying" - but exactly the same is true when a "normal" compiler uses the stack!
There's information in the knowledgebase; eg, the Application Note about function pointers discusses it - because it has a big effect on the use of function pointers...
http://www.keil.com/appnotes/docs/apnt_149.asp
http://www.keil.com/appnotes/docs/apnt_129.asp
http://www.keil.com/support/man/docs/bl51/bl51_ol_fp.htm
http://www.keil.com/support/docs/1026.htm
Note necessarily in DATA - the memory space used depends upon the Memory Model selected.
Yes, there is a problem. While the linker is correctly overlaying parameters, I don't want the linker to overlay the parameters for a few of my functions. The reason being that these functions are called by an ISR. So a parameter in use by one function gets overwritten by an ISR-called function because the linker overlayed the two parameters. Very bad.
So the question is, how do I instruct the locator to not overlay the parameters for these particular functions?
I don't see the relavance of this to my issue of overlaying parameters.
It is true that my ISR is calling the function by pointer. So it is necessarily passing the one parameter on the stack. Rather than leave this parameter on the stack, the compiler copies it into its DATA location. Unfortunately that location is overlayed with another, unrelated, function parameter.
Until now I thought I had a high lack of curiosity - now I find myself surpassed.
I care because it means the "volatile" did nothing for me. It was just a coincidence.
"So the question is,"
maybe you can post a short but complete piece of code demonstrating this problem you are facing. if you are right, you have identified a huge bug in the compiler and everyone of us could benefit its airing.
so post the short piece of code you can that demonstrate this problem of yours.
otherwise, talking theory doesn't do anyone any good.
It is true that my ISR is calling the function by pointer
The linker has a real problem with resolving the call table when functions are called by pointers.
I have, realizing how cumbersome function pointers are in the '51 architecture, avoided function pointers totally when working with the '51, and can thus not answer with a link. However from other posts I know there is something in the documentation about how to resolve this issue by special linker usage.
Erik
PS note "how cumbersome function pointers are in the '51 architecture" not the tools, although as seen above, that is true too.
global bit blah = 0
in the ISR: if (blah) { function_that_is_called_by_pointer(); }
at least do it as 'proof'. If that does not remove the overlaid variable, you will need to post code