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

Solving L107 _DATA_GROUP Overflows

This is only my second project with Keil, so I am not an expert, but I have Please read the manual'ed. :) The code I'm working on was released by the manufacturer of the system, which includes an embedded 8051. The original code worked, but was poorly written and lacked functionality. As I am making changes, I find that I hit CODE and DATA overflows. I can solve CODE overflows by moving code to other code banks and simplifying things. DATA overflows are a little more difficult.

The Memory Model is "Small: variables in DATA" and the Code Rom Size is "Large: 64K program". I'd prefer not to mess with these, as I have to give the code back working and reasonably like how I got it. The main source file (which is not overlayed) has a small allocation of RAM/dataspace, most of it being used by the ROM code that I can't modify. I've gotten rid of local variables and used XDATA wherever possible. Suddenly, after days of development (and probably 100 builds), I've overflowed DATA by 9 bytes somehow.

*** ERROR L107: ADDRESS SPACE OVERFLOW
    SPACE:   DATA
    SEGMENT: _DATA_GROUP_
    LENGTH:  0009H

My RAM map looks like:

            * * * * * * *   D A T A   M E M O R Y   * * * * * * *
            REG     0000H     0008H     ABSOLUTE     "REG BANK 0"
            DATA    0008H     0018H     ABSOLUTE
            BIT     0020H.0   000FH.5   ABSOLUTE
            BIT     002FH.5   0000H.2   UNIT         _BIT_GROUP_
                    002FH.7   0000H.1                *** GAP ***
            DATA    0030H     0045H     ABSOLUTE
            IDATA   0075H     0006H     UNIT         ?ID?RAMPROG
                    007BH     0001H                  *** GAP ***
            DATA    007CH     0002H     ABSOLUTE
            DATA    007EH     0002H     ABSOLUTE
            IDATA   0080H     0043H     ABSOLUTE
                    00C3H     000DH                  *** GAP ***
            IDATA   00D0H     0030H     ABSOLUTE

I'm assuming that the ABSOLUTE DATA allocations are for C function arguments and local variables -- except that I have now very little/few of either. In fact, the module's compiler output says:

MODULE INFORMATION:   STATIC OVERLAYABLE
   CODE SIZE        =   8573    ----
   CONSTANT SIZE    =    284    ----
   XDATA SIZE       =   ----      16
   PDATA SIZE       =   ----    ----
   DATA SIZE        =   ----      10
   IDATA SIZE       =      6    ----
   BIT SIZE         =   ----       2
END OF MODULE INFORMATION.

which actually shows less DATA, IDATA and CONSTANTs used than when I first started. So I guess the question is:

1. If I've eliminated EVERY SINGLE local variable in the code, and
2. Reduced the C function parameters to just a small number, all BYTE data types.

what's left to do to eliminate the DATA overflow?

  • An update. I rolled back to a prior version and started slowly adding back code. I found that one small change (one line) caused the compiler to no longer be able to use registers to handle the function parameters, hence the need for 9 more bytes of RAM. Tricky, tricky :) I find myself changing a lot of code like

    void SomeFunction(BYTE x, WORD y)
    {
        <do something with> x
        <do something with> y
    }
    


    to

    #define SomeFunction(x,y) {XBYTEx=x; XWORDy=y; someFunction();}
    
    void someFunction(void)
    {
        <do something with> XBYTEx
        <do something with> XWORDy
    }
    

    where XBYTEx and XWORDy are defined in XDATA space.

    This is probably old hat to the more experienced among you.

  • This line:

                IDATA   0075H     0006H     UNIT         ?ID?RAMPROG
    

    doesn't really make sense. You have IDATA below the 0x80 barrier, but unused space above the barrier:

                        00C3H     000DH                  *** GAP ***
    

    It should be possible to move that block from 0x75 up to 0xc3, and thus ease the problem.

    Actually, I think something must be wrong with how your program uses DATA space --- there really shouldn't be that much ABSOLUTE usage.

  • Thanks, H-B. The memory layout is just as I received it (and I haven't changed it), but I had EXACTLY the same question about IDATA, as I understood it is always in the region > 0x80. That may fix a few other things, too, perhaps.

    One problem I have is that there is ROM code to which I don't have access that presumably chews up a lot of the DATA space.

    Thanks again,
    J

  • The compiler analyzes the call tree of the program to determine when it can safely overlay memory used by two functions. If the functions can't be active at the same time (they're down different branches of the tree), then the compiler can reuse the data memory for the parameters, locals, and temps.

    If you have functions that aren't called, those functions don't appear in the main call tree. They each act as the root of their own call tree (like an interrupt function or an RTOS task), and can't have their memory overlaid with any other function. Thus, unused functions can eat up a lot of memory.

    See the REMOVEUNUSED linker directive. If possible, don't compile or link in the unused code at all.

    Note that the memory model dictates where the parameters and locals live by default. If you switch the memory model to large, those will all move to XDATA. Best practice is generally considered to be to explicitly declare the memory space for every variable so that they are unaffected by changes in the memory model. You can also change the memory model function by function.

  • Thanks, Drew. I'll do that.

    I'm still left with the mystery of those IDATA areas below 0x80. Where would I look for answers?

    Regards,
    J

  • "The idata memory specifier refers to all 256 bytes of internal data memory"

    See: http://www.keil.com/support/man/docs/c51/c51_le_intdatamem.htm

  • His mystery was not that IDATA can address the full 256 bytes, but why one IDATA block was placed before a DATA block, resulting in the DATA address space becoming full.

  • the linker allocates variables in blocks = segments.

    Thus if you have a DATA segment that is larger than the available DATA space, the linker inserts IDATA there.

    The trick is to spread the data variables into several modules when you are squeezed.

    here is one case of mine where the linker used space below 0x80 (bdata to 0x20) for IDATA
    I used assembler to avoic the compiler assigning an identical segment name (maybe you can do it in C, I did not investigate)

    ;;////////////////////////////////////////////////////////////////////
    ;;
    ;;  FILE:     SXZDATA.A51
    ;;
    ;;  Copyright TwinVision N.A., 2007
    ;;
    ;;  Overcome the Keil inability to save DATA parts in gropus lexx than "hole"
    
    
    $NOMOD51
    
               PUBLIC GCDXdestListBeg
               PUBLIC GCDXdestListEnd
               PUBLIC GCDXprmsListBeg
               PUBLIC GCDXprmsListEnd
               PUBLIC GCDXcurrListBeg
               PUBLIC GCDXcurrListEnd
               PUBLIC GCDXothListBeg
               PUBLIC GCDXothListEnd
    
    ?DT?zdataf SEGMENT DATA
    
               RSEG ?DT?zdataf
    
    
    GCDXdestListBeg: ds 2
    GCDXdestListEnd: ds 2
    GCDXprmsListBeg: ds 2
    GCDXprmsListEnd: ds 2
    GCDXcurrListBeg: ds 2
    GCDXcurrListEnd: ds 2
    GCDXothListBeg:  ds 2
    GCDXothListEnd:  ds 2
    
               end
    

    Erik