-
Notifications
You must be signed in to change notification settings - Fork 2.6k
8051 Even More Stack
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:
- Getting rid of all variables between
0x08
and0x1F
and - 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.
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.
- Download this patch. This diff combines patches contributed by Philippe Retornaz [ 2,3,4 ].
- If you haven't previously downloaded SDCC's sources, do so as per the instructions in the 'prepare your system' guide.
- 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.
- Open
cpu/<your-cpu>/8051def.h
. Find this line:
#define CC_CONF_OPTIMIZE_STACK_SIZE 0
- Read the comments directly above this line.
- Set the define to 1
- Read the comments again.
- Did you remove all your printfs?
- Did you remove all your
__bit
variables, if you have any?
- 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
.