The 8051 family of micro controller have a minimum of 128 bytes of
internal memory which is structured as follows
- Bytes 00-1F - 32 bytes to hold up to 4 banks of the registers R7
to R7
- Bytes 20-2F - 16 bytes to hold 128 bit variables and
- Bytes 30-7F - 60 bytes for general purpose use.
Normally the SDCC compiler will only utilise the first bank of registers,
but it is possible to specify that other banks of registers should
be used in interrupt routines. By default, the compiler will place
the stack after the last bank of used registers, i.e. if the first
2 banks of registers are used, it will position the base of the internal
stack at address 16 (0X10). This implies that as the stack grows,
it will use up the remaining register banks, and the 16 bytes used
by the 128 bit variables, and 60 bytes for general purpose use.
By default, the compiler uses the 60 general purpose bytes to hold "near data". The compiler/optimiser may also declare some Local Variables in this area to hold local data.
If any of the 128 bit variables are used, or near data is being used then care needs to be taken to ensure that the stack does not grow so much that it starts to over write either your bit variables or "near data". There is no runtime checking to prevent this from happening.
The amount of stack being used is affected by the use of the "internal stack" to save registers before a subroutine call is made (-stack-auto will declare parameters and local variables on the stack) and the number of nested subroutines.
If you detect that the stack is over writing you data, then the following can be done. -xstack will cause an external stack to be used for saving registers and (if -stack-auto is being used) storing parameters and local variables. However this will produce more code which will be slower to execute.
-stack-loc will allow you specify the start of the stack, i.e. you could start it after any data in the general purpose area. However this may waste the memory not used by the register banks and if the size of the "near data" increases, it may creep into the bottom of the stack.
-stack-after-data, similar to the -stack-loc, but it automatically places the stack after the end of the "near data". Again this could waste any spare register space.
-data-loc allows you to specify the start address of the near data.
This could be used to move the "near data" further
away from the stack giving it more room to grow. This will only work
if no bit variables are being used and the stack can grow to use the
bit variable space.
Conclusion.
If you find that the stack is over writing your bit variables or "near
data" then the approach which best utilised the internal
memory is to position the "near data" after the
last bank of used registers or, if you use bit variables, after the
last bit variable by using the -data-loc, e.g. if two register banks
are being used and no bit variables, -data-loc 16, and use the -stack-after-data
option.
If bit variables are being used, another method would be to try and squeeze the data area in the unused register banks if it will fit, and start the stack after the last bit variable.