This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Locating 2 parameters at the same address

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

Parents
  • 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?

Reply
  • 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?

Children
  • SubVar2 = SubVar2 + 1;
    

    changed that to:

    SubVar2 = 0;
    

    and

            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.

  • 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.

    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.

  • 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!