Skip to content

8051 Even More Stack

Benoît Thébaudeau edited this page Sep 23, 2019 · 5 revisions

By now you have built SDCC and you have started playing around with contiki examples. You may have noticed that after building contiki for one of the 8051-based platforms, there is a file with a .mem extension in the example's directory. This file looks something like this:

Internal RAM layout:
      0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00:|0|0|0|0|0|0|0|0|a|a|b|b|b|b|c|d|
0x10:|d|d|d|e| | | | | | | | | | | | |
0x20:|T|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x30:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x40:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x50:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x60:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x70:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x80:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x90:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xa0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xb0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xc0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xd0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xe0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xf0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0-3:Reg Banks, T:Bit regs, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack, A:Absolute

16 bit mode initial stack starts at: 0x21 (sp set to 0x20) with 223 bytes available.

Let's have a closer look at that:

  • 0x00 - 0x07: 7 bytes allocated for registers R0...R7 of register bank 0
  • 0x08 - 0x13: Allocated to variables residing in internal RAM. This is where we will find variables declared with __data
  • 0x14 - 0x1F: Not allocated
  • 0x20: Bit regs. More on that below
  • 0x21 - 0xFF: The stack

As discussed in the memory spaces page, the stack resides in internal RAM and occupies whatever's left once all other iRAM variables have been allocated. In this particular example, the stack starts at address 0x21 and has a maximum size of 223 bytes. We can also observe that there is a gap of unallocated space between 0x14 and 0x1F. The reason for this is the T symbol at address 0x20, which holds bit variables.

If you look at the SDCC manual and other resources on the 8051 architecture, among the 256 bytes of internal RAM, only 16 are bit-addressable (the range 0x20 - 0x2F). Thus, the lowest address that can hold bit variables is 0x20, resulting in the in the 0x14 - 0x1F gap.

When using contiki with the IPv6 code linked in, we could use as much stack as we can possibly come up with. This could be achieved by:

  1. Getting rid of all variables between 0x08 and 0x1F and
  2. Getting rid of the T at 0x20 (not so easy)

1 is easy, we simply move all those variables to external RAM by removing the __data storage class from their declaration. The reason 2. is not as easy is because those variables are used by libraries provided with SDCC. In order to remove them, we need to patch the toolchain.

OK, enough lessons. Show me the code

Only follow the instructions below once you've read them, you understand potential negative side effects and you know what you're doing.

This will mess up with your SDCC installation, will potentially harm code generation for other memory models and may break things. I strongly suggest maintaining two separate SDCC installations. One purpose-built as per the instructions here and a vanilla one. There are plenty ways to achieve this by playing around with SDCC's configure script.

  1. Download this patch. This diff combines patches contributed by Philippe Retornaz [ 2,3,4 ].
  2. If you haven't previously downloaded SDCC's sources, do so as per the instructions in the 'prepare your system' guide.
  3. Patch SDCC. I suggest a full distclean, configure, build cycle. From your SDCC sources dir:
  • make distclean (if you have previously built SDCC)
  • patch -p0 < sdcc-max-stack.patch (you will obviously need to specify the full path to the patch file here)
  • Configure. Play with the --prefix and --exec-prefix arguments of the configure script if you want two different SDCC installations.
  • Build, install.
  1. Open cpu/<your-cpu>/8051def.h. Find this line:
#define CC_CONF_OPTIMIZE_STACK_SIZE 0
  1. Read the comments directly above this line.
  2. Set the define to 1
  3. Read the comments again.
  • Did you remove all your printfs?
  • Did you remove all your __bit variables, if you have any?
  1. Rebuild contiki

If all goes well, your new .mem file will look something like this:

Internal RAM layout:
      0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00:|0|0|0|0|0|0|0|0|a|S|S|S|S|S|S|S|
0x10:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x20:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x30:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x40:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x50:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x60:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x70:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x80:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x90:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xa0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xb0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xc0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xd0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xe0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xf0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0-3:Reg Banks, T:Bit regs, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack, A:Absolute

16 bit mode initial stack starts at: 0x09 (sp set to 0x08) with 247 bytes available.

As you can see, T has disappeared and so have (almost) all other internal RAM variables. There is a variable allocated to internal RAM at 0x08, directly adjacent to R0-R7. Don't worry about this one, there is nothing we can do about it. The stack now starts at 0x09, compared to the previous 0x21.

More Reading

  1. SDCC Compiler User Guide
  2. exclude bits patch
  3. _divuint patch
  4. _divulong patch
Clone this wiki locally