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.
at least do it as 'proof'. If that does not remove the overlaid variable, you will need to post code
Erik
I was trying to avoid lengthy code, but here is a concrete example that demonstrates my point. Here is the code:
#include "compiler_defs.h" #include "C8051F930_defs.h" void Sub1( U8 SubVar1 ) { SubVar1 = SubVar1 + 1; } void Sub2( U8 SubVar2 ) { SubVar2 = SubVar2 + 1; } void main(void) { while(1) { Sub1( 13 ); } } static void ADC_ISR(void) interrupt 10 { U16 u16Result = 12; Sub2( u16Result ); ADC0CN &= ~0x20; }
And here are excepts from map file:
BL51 BANKED LINKER/LOCATER V5.12 07/14/2011 13:32:43 PAGE 1 BL51 BANKED LINKER/LOCATER V5.12, INVOKED BY: Z:\TOOLS\SOFTWARE\KEIL\BL51.EXE C:\Users\JeffT\Documents\Temp\Main.obj TO C:\U >> sers\JeffT\Documents\Temp\Main RS (256) PL (68) PW (78) MEMORY MODEL: SMALL ------- PROC _SUB1 D:0007H SYMBOL SubVar1 ------- ENDPROC _SUB1 ------- PROC _SUB2 D:0007H SYMBOL SubVar2 ------- ENDPROC _SUB2
The linker builds its call tree and don't think the Sub2 and Sub1 overlap. But obviously they can. When the ISR fires Sub2 will overwrite Sub1's value. I can turn off the variable overlaying entirely, but that would be a waste. I suppose most people don't call functions from within ISRs. I have my reasons for doing so.
Any ideas?
SubVar2 = SubVar2 + 1;
changed that to:
SubVar2 = 0;
SubVar1 = SubVar1 + 1;
to
SubVar1 = SubVar1 + 1; P2=SubVar1;
so if subvar1/subvar2 are indeed overlaid, you will see that subvar1/subvar2/P2 maintains 13 and then periodically (as the isr 10 is fired) gets reset to 0.
if the two variables are not overlaid, you will see P2 maintaining a value of 13.
I tried to use tmr0 isr and I got a constant value on P2.
The linker builds its call tree and don't think the Sub2 and Sub1 overlap. But obviously they can.
The problem is precisely that that is not at all obvious to the linker. Static call tree analysis pretty much always fails as soon as function pointers get involved, and deep down, it really has no chance --- there's an impossible task hiding in there, equivalent to the Halting Problem. Keil is no exception to that rule.
So what you should do is: do not call functions via pointer from inside an ISR. Not on a '51, anyway. If at all possible, avoid calling any functios from a '51 ISR, period.
If you really can't see any way of accomplishing that, see the app notes already referenced in this thread about ways to fudge the linker call tree data. And brace yourself, because this will hurt.
Hello,
You are focusing in on the wrong section of the memory map. You need to view the "overlay analysis" section
If the overlay analysis is incorrect, you can use the OVERLAY command to correct it:
http://www.keil.com/support/man/docs/bl51/bl51_overlay.htm
For example look at page 5 of this application note.
http://www.keil.com/appnotes/docs/apnt_129.asp
It explains exactly the issue you describe, a function called by a function pointer.
Page 5 -6 show how to use the OVERLAY command to tell the linker that these functions are not independent. Once the linker is made aware of this, it will not overlay those variables.
If at all possible, avoid calling any functios from a '51 ISR, period.
There's NO problem with calling a function from an '51 ISR.
However, like most tasks, the programmer needs to understand the mechanism(s) involved and take appropriate steps to ensure the cogs fit correctly.
FWIW, we have plenty of code that calls functions from ISRs. It's all written in assembler and there have been no reported problems. Quite a few of those functions are inherently re-entrant. They are called from both ISR and mainline code. Most importantly, parameters and local variables are passed in registers.
No problem, so long as you know what you're doing, period.
Disagree.
Because Keil C51 functions are inherently not reentrant (due to the Overlaying) there are potential problems with calling Keil C51 functions from ISRs - specifically, when those functions are also called from non-ISR code.
I think the Linker will warn of this: http://www.keil.com/support/man/docs/bl51/bl51_l15.htm
So, as a blanket statement, I think "There's NO problem with calling a function from an '51 ISR" is less helpful than, "If at all possible, avoid calling any functios from a '51 ISR, period"
There is also the general issue (not specific to Keil or the 8051) that ISRs should generally be "short and sweet" - and calling functions generally indicates that the programmer has forgotten (or not understood) this...
both of you are correct - with IB being more correct.
it is true that calling a function from within the isr should be avoided as much as possible. but that's not always possible, and I would further state that it is unlikely to be possible if you are relying pre-made code modules.
in that sense, IB is more correct that you can do the undesirable / risk thing of calling a function from within an isr, as long as you know what you are doing.
sometimes, it is optimal to do the sub-optimal thing.
I think it is unhelpful to say, "There's NO problem" with the big emphasis on the "NO" like that.
Especially as the forum has many novice/inexperienced readers - who might take that at face falue. (in fact, it sometimes seems that the novice/inexperienced readers are the majority)
There most certainly are problems to be considered - so, again, the emphatic "NO" is unhelpful.
True, the problems will not be significant in some designs but, again, just saying there are "NO" problems is unhelpful.
H-B B did, at least, qualify his statement with "If at all possible" and "avoid".
Can't you just hear the novice/inexperienced 8051 programmer posting,
"I read that there is NO problem with calling a function from a '51 ISR - so why do I get this L15 warning?"
"who might take that at face falue."
sounds like poor programmers, rather than the message itself, are the problem.
then the real cure is to educate the programmers or let them suffer through prolonged debugging to learn their mistakes is the solution.
rather than bastardizing a perfectly correct and reasonable message.
I disagree that it is perfectly correct, and I disagree that it is reasonable.
"the real cure is to educate the programmers"
Indeed - by not giving misleading statements.
"I disagree that it is perfectly correct, and I disagree that it is reasonable."
if you look at IB's statements in their totality, he essentially said that it is ok to call a function from within an isr, as long as you know what you are doing.
he may not have put the two statements physically next to each other, but I think if anyone were to think the two in separation, s/he has a deeper problem, with comprehension.
"Indeed - by not giving misleading statements."
people learn a lesson far better if they experience it in a painful way.
unless you can shield everyone from every misleading / less-than-truthful statement, it is probably to their interest for them to learn to identify and interpret such statements on their own.
you are talking out of both sides of your mouth. Here you say "let them suffer" in other places you criticise that a solution is not provided.
Erik (who is not afraid of putting his name to his statements)
"unless you can shield everyone from every misleading / less-than-truthful statement, it is probably to their interest for them to learn to identify and interpret such statements on their own."
You don't seem to know what foot to stand on. In this case, it's "close enough". In other threads, you are willing to spend hours fighting for the use - or nonuse - of a single word.
"You don't seem to know what foot to stand on. In this case, it's "close enough". In other threads, you are willing to spend hours fighting for the use - or nonuse - of a single word."
because each case is different. while doing something is in-material in one case, doing the same thing may be material in others.
so the seeming contradiction is fairly easy to understand, if you have common sense.
Indeed!
One moment, you're criticising fine detail and ignoring the context; then, just to be contrary, you decide to do the opposite!
Make up your mind!
"One moment, you're criticising fine detail and ignoring the context; then, just to be contrary, you decide to do the opposite!"
I thought I had answered that, in the post that yours above responded to.
but in case you missed it, sometimes fine details matter, and in other cases, they don't.
so it is hard and wrong to insist that one always pays attention to fine details - they are called "fine details" for a reason.
hope it helps.
Making a bold statement like "There are NO problems" - with the big emphasis on the NO - is not a fine detail. It is plain wrong.
this is exactly what IB wrote:
'There's NO problem with calling a function from an '51 ISR.
No problem, so long as you know what you're doing, period.'
vs. what you characterized what he wrote:
"There are NO problems"
come on. would any reasonably intelligent people equate the two?
as I stated before, the two of you said the same thing, with different emphasis. and there is no point in pushing any of your statements to the extreme to justify the other.
"Making a bold statement like "There are NO problems" - with the big emphasis on the NO - is not a fine detail. It is plain wrong."
Well, thanks for that vote of confidence ;)
However - I do not believe it is wrong at all. There aren't any problems - So long as everything about the situation is understood. Nothing specific about '51 architecture there.
If I were to say that there were no problems with boiling an egg I guess I'd get a complaint from someone pointing out that it shouldn't be done because someone might leave the gas on and the house might burn down.
View all questions in Keil forum