Stack pointer area?
Posted:
Tue Jan 02, 2018 2:45 pm
by eriksl
Hello All,
This has been puzzling me more and more lately and I don't seem to find out anything about it (googled it...)
According to
https://github.com/esp8266/esp8266-wiki/wiki/Memory-Map:
3FFFC000h 4000h RAM ETS system data RAM.
3FFE8000h 14000h RAM RW User data RAM. Available to applications.
In other words: 80kbytes of RAM available to application, from 0x3ffe8000 on. Every other source I consult (including the linkmap) confirms this.
When I print the value of the stack pointer, I get values outside this area, some examples:
0x3fffff00 (parameter on stack)
0x3ffffef8 (variable on stack)
They are right inside the above mentioned "ETS system data RAM" area. I can get no information about this. I'd expect them to be right on top of the "user data ram" area, i.o.w. somehwere around 0x3fffbfff, growing downwards towards the heap.
Does this mean we have an additional (up to) 16kbytes of memory (more or less) dedicated to the stack? How much of this area is actually available? What if we overrun it (which is easily possible)? I must say 96 kbytes or RAM sounds more plausible than 80 kbytes, but who knows...
Re: Stack pointer area?
Posted:
Fri Jan 12, 2018 4:44 am
by eriksl
I've done some experimentation and I'd like to share what I found, maybe someone can comment.
To start with, during the very early boot process, some functions in user code can be called from the SDK code:
- user_spi_flash_dio_to_qio_pre_init
- user_rf_cal_sector_set
- user_rf_pre_init
During this period the stack pointer points to an area half way through the memory area designated as user ram area (dram0). Weird.
When the SDK code is done initialising, user_init() is called. After that, optionally a function user_init2() can be called from SDK code (after which all wlan initialisation has finished). In both functions the stack pointer is on the top of the memory area designated as "system ram" (as mentioned before) and remains there. So apparently "non-OS SDK" user code has it's stack there.
Now is the question, how big is the usable stack area? It could be anything between 16kbytes (where the sysram area starts and the dram0 area ends, writing beyond there will corrupt the heap) and 384 bytes (the max stack space I am using now and which doesn't seem to be a problem).
So I started "painting" the sysram area with a magic number (4 bytes) and watched the area. Conclusions from that:
- If you write anything in the area between the sysram start (3fffc000) and halfway through (3fffe000) the system will crash. Especially if started from the top of this area (3fffe000) downwards, so I suspect that's where the stack is that's used for system functions (interrupts, some sort of CPU supervisor mode, background SDK code?)
- Writing in the area between 3fffe000 and 3fffeb2c is "harmless", everything will keep working, but there is a huge caveat, somewhere in the process between user_init2 and regular execution of the user code, the last part (top area, a few bytes below 3fffeb2c) gets overwritten by the SDK code, with zero's. So you can't use it as stack area.
- The area between 3fffeb2c and 3fffffff is "clear".
My conclusion:
- The area between 3fffeb30 and 3fffffff is the designated area for the user stack and is 5328 bytes in size (not too bad anyway)
- The area between 3fffe000 and 3fffeb2c could maybe be used for some storage, but take care that a small part of it gets overwritten during the startup. When all is up and running, the SDK doesn't write there. So it's not suitable for use as stack, but it might be used for extra storage, outside the heap, of size of about 2.5 kbytes, when memory is really tight.
- The area between 3fffe000 and 3fffc000 is used for system/SDK usage, don't touch it.
To be able to keep monitoring this and just for info, I implemented "stack painting" where at system start I write the complete stack area with signature long words. Everywhere the stack has been, the signature will be overwritten, so the effectively needed stack size can be determined. From the other side of the area, everywhere the SDK has been written, the signature will be lost as well, so this can be monitored. As for the moment, I haven't seen that happening, luckily.
Re: Stack pointer area?
Posted:
Fri Jan 12, 2018 5:39 am
by btidey
Thanks for the investigation and sharing this. RAM tends to be the resource that runs out first.
Is there any code you can share around stack painting and determining user stack usage?
Re: Stack pointer area?
Posted:
Fri Jan 12, 2018 5:52 am
by eriksl
In the end it's all no rocket science
Here in this commit you'll find the relevant code. It also has some debug code for reading and writing random memory locations that I used, using peek and poke commands, they're not related to the stack painting.
https://github.com/eriksl/esp8266-unive ... 30d718c9b8If you think it's not clear, please yell and I'll add some explanation.
BTW I can understand that Espressif can't share some low level details, for purposes of FCC regulations (radio access) and for business model purposes as well, but it upsets me that they won't share obvious useful details like stack size, low level hardware timers and UART implementation etc. etc. It has nothing to do with above limitations and I think it's just lame.