Menu

Couldn't get XX bytes allocated in IRAM/DSEG

2005-04-16
2013-03-12
  • Craig Steiner

    Craig Steiner - 2005-04-16

    I'm working on a project in SDCC and, for a second time, I have gotten a message similar to:

    ?ASlink-Error-Could not get 96 consecutive bytes in internal RAM for area DSEG.

    When I look at the *.mem file, the graphical map shows that the stack has occupied virtually all of IRAM and has the message:

    ERROR: Couldn't get 96 bytes allocated in internal RAM for area DSEG.
    Stack starts at: 0x37 (sp set to 0x36) with 201 bytes available.

    The last time this happened I solved the problem by reducing the number of arguments I passed to a function, but this time I'm passing no arguments.  Now it seems the problem is in this area of code:

            SerialSendString("\r\nCSUM=");

    SerialSendHex(csum);
    SerialSendString(" Addr=");
    SerialSendHexLong(address);
    SerialSendString(" Bytes=");
    // SerialSendHex(bytecount);
    SerialSendString(" Type=");
    SerialSendHex(rectype);
    SerialSendHex(bytecount);

    Compiled as above, the program compiles.  If I uncomment the SerialSendHex(bytecount) line, it fails with the above error message.  However, if I change the "bytecount" variable in that line to "rectype", it compiles fine.  The definition for bytecount and rectype appear on the same line as follows:

    unsigned char bytecount, rectype;

    Can anyone give me an idea of what's happening?  It appears to me the problem is that for some reason, the space allocated to the stack is exploding to a huge size.  When I comment out the line in question to prevent the error, the *.mem file reports:

    Stack starts at: 0x96 (sp set to 0x95) with 106 bytes available.

    So what is it above the above line that causes the stack to explode to 201 bytes and leave no DSEG memory for any other variables?

    And is there any source or reference that can explain the errors produced by SDCC?  It seems that a few are mentioned in the online documentation, but not many.

    Thanks,
    Craig Steiner

     
    • Craig Steiner

      Craig Steiner - 2005-04-16

      It should be noted that even when I comment out the SendSerialHex(bytecount) line, I'm using the bytecount variable elsewhere in the function.  It doesn't seem to be the presence of bytecount that causes the problem but trying to pass it to SendSerialHex.  The SendSerialHex function just takes a byte and converts it to two ASCII characters and sends it to the serial port.  It is used throughout the program with no problem.

      If I try the following, it works:

      x = bytecount;

      If I try:

      x = bytecount;
      SerialSendHex(X);

      It fails in the same way. 

      Regards,
      Craig Steiner

       
    • Erik Petrich

      Erik Petrich - 2005-04-16

      The error message is from the linker, not the compiler itself. However, I just checked the linker manual and it doesn't seem to be listed there either. Another thing to add to the to do list.

      In any case, neither the compiler nor the linker keep track of allocations to the stack. The stack is simply allocated the largest contiguous block available after everything else has been allocated that can be allocated. It appears that something in your program is allocating a 96 byte object (probably an array or struct) in DSEG, which requires that it lie completely within the first 128 bytes of memory. Since the linker was not able to meet this requirement, this object was not allocated, leaving many more bytes available for the stack.

      Changing SerialSendHex(bytecount) is just causing the compiler to change how the local variables and temporary values are allocated between the registers and memory. Unless you are using --stack-auto or the reentrant function attribute, these values will also compete for room in DSEG if there weren't enough registers available.

      The easiest fix for your program is to find out which variable requires the 96 contiguous bytes and add the "idata" storage class keyword to its declaration. This will allow the linker to allocate it in any of the 256 contiguous free bytes of internal memory, rather than just the first 128. Assuming you don't recognize this size variable already, look at the .map file generated when you have no error message under the DSEG area. It only shows the starting address (in hexadecimal) rather than the size, so you'll need to look at adjacent starting addresses for a large jump (96 = 0x60).

      (This is all assuming you are using a version of the compiler package generated within the past half year or so)

       
    • Craig Steiner

      Craig Steiner - 2005-04-17

      Thanks for the help.  That actually confirmed that my thoughts were correct since I figured that something along those lines must be the problem.

      However, I have no structures that are 96 (0x60) bytes long and when the error does not occur, I find nothing that would lead me to believe that there is any block of 96 bytes needed. Almost all my variables are already either of "idata" or "xdata" type so that doesn't seem to be the issue either.

      I'll keep looking, but I'm finding this problem to come up from time to time.  Unfortunately I've gone too far to rewrite this in assembly so I'll have to wiggle my way out of this, but it would certainly be helpful if the linker gave more information of *what* it was trying to allocate and *why*.

       
    • Craig Steiner

      Craig Steiner - 2005-04-17

      I checked and while most of my global variables were xdata or ixdata, my local function variables weren't assigned.  I assigned some of them to idata and it seems to have helped.

      *BUT* it seems that some function variables *must* be in the first 128 bytes of RAM?  Why is this?  Does it depend on what I do with the variables in the function, or does it have something to do with what type or how many variables are passed to the function, etc.?  Adding some idata's to function variables got me down to 79h, but that tells me that if the linker needs another 7 bytes in lower IRAM for function data, I'm going to run into the same problem.  It'd be useful to know what *must* be in these lower 128 bytes of IRAM so I can avoid doing things that cause that situation to arise.

      Thanks.

       

Log in to post a comment.