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
"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.
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.
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.
"Erik (who is not afraid of putting his name to his statements)"
how heroic you are!
on that basis along, they should award you the Nobel prize for Bravery and two Metals of Honor (not just one!)
:)
"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.