Stack Usage Calculator

Last post
21 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is there a good gcc AVR stack usage calculator out there?
I am trying to use the GCC switch -fstack-usage,
but when I compile, their is no ".su" file created as the gcc documentation said it would be.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You may want to read this recent thread:

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=74865

(moving this to GCC forum where it belongs)

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

12oclocker wrote:
Is there a good gcc AVR stack usage calculator out there?
I couldn't find one so I ended up writing it for my particular purpose. Computing stack usage by static code analysis can be fairly easy for specific use cases but is much more difficult for the general case. There is some discussion of the issues involved in this thread.

Also, see:
http://docs.tinyos.net/index.php/Stack_Analysis
http://www.cs.utah.edu/~regehr/stacktool

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I looked at all that stuff, but can't find anything that works for the at90s2313 or attiny2313 chips,

Anyone know how to get -fstack-usage to work?

I am familiar with techniques on watching a stack variable on the edge of the stack, and seeing it it's been modified to detect an overflow, but it's kind of a pain to implement every project.
It's really going to be a pain to have to write something that analyzes the assembly code myself.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

-Brad

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

12oclocker wrote:
It's really going to be a pain to have to write something that analyzes the assembly code myself.
It's not that bad, really. Especially so if you don't have to address the special cases (recursion, indirect jump/call, stacked interrupts), your application doesn't use crt functions that utilize the __prologue_saves__/__prologue_restores__ mechanism, and don't have any assembly language code that modifies the stack pointer in an unusual manner. You will have to track register content (essentially a simple-minded emulator) and be able to recognize/handle the stack pointer manipulation idioms employed by the avr-gcc code generator (several different cases).

The one that I wrote is integrated into the ZBasic compiler and thus is not usable as a standalone application. It utilizes information from the generated object code file and from the .sym file together with some information provided by the ZBasic compiler's code generator and knowledge about the multi-tasking structure to analyze stack use for one or more tasks in the user's program. After the analysis is done, it generates warnings if the stack size specified by the user for each task is less than the calculated maximum plus a user-specified padding value. It also detects situations where the calculation is indeterminate (recursion, indirect call/jump with no target data available, stack pointer manipulation involving values not known at compile time, etc.) and reports that fact.

As I indicated before, for a certain set of special cases it's simple, straightforward analysis. The more difficult challenge is in making a general purpose tool that works for a wide range of applications and programming styles.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

12oclocker wrote:
Anyone know how to get -fstack-usage to work?
A few months ago I was looking for the same thing, unsuccessfully. Also ended up writing my own utility that gets stack usage and call tree from the .elf file. You are welcome to try it. It is called ezstack and there is a link to it in this thread that Don Kinzer mentioned. Do not expect too much from it, however.

Eugene

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ezharkov wrote:
12oclocker wrote:
Anyone know how to get -fstack-usage to work?
A few months ago I was looking for the same thing, unsuccessfully. Also ended up writing my own utility that gets stack usage and call tree from the .elf file. You are welcome to try it. It is called ezstack and there is a link to it in this thread that Don Kinzer mentioned. Do not expect too much from it, however.

Eugene

Ah, the code looks very nice! do you have a compiled exe? does it support the at90s2313 and the attiny2313?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

12oclocker wrote:
do you have a compiled exe? does it support the at90s2313 and the attiny2313?
Well, I did not. But if you insist, there is one now: http://home.comcast.net/~ezstack/ezstack.exe Regarding attiny2313. Out of curiosity I tried it yesterday. It did not work. Because attiny2313 has less than 256 bytes of RAM and avr-gcc initializes only SPL. I fixed that. So, one could say it does support at90s2313 and attiny2313. On the other hand, there may be many other things that it does not support. I do use the utility myself and plan to support it for myself. But if you use any avr-gcc features that I do not use, then you may be on your own.

Eugene

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ezharkov wrote:
12oclocker wrote:
do you have a compiled exe? does it support the at90s2313 and the attiny2313?
Well, I did not. But if you insist, there is one now: http://home.comcast.net/~ezstack/ezstack.exe Regarding attiny2313. Out of curiosity I tried it yesterday. It did not work. Because attiny2313 has less than 256 bytes of RAM and avr-gcc initializes only SPL. I fixed that. So, one could say it does support at90s2313 and attiny2313. On the other hand, there may be many other things that it does not support. I do use the utility myself and plan to support it for myself. But if you use any avr-gcc features that I do not use, then you may be on your own.

Eugene

very nice job!,
I tested it with a new project I was doing on a attiny2313 elf file, I do have a question though, It does not seem to detect any ram usage in my interrupts, would this be because I am not using anything except 'volatile static global' variables in my interrupts? or does it not analyze interrupts for this chip? again, I'm very impressed, very nice work!

I also did test it with a at90s2313 elf file, and this was the output it generated...
ezstack version 2
Text size = 1944
Unreached block 0x2 - 0x14 (size=20)
Unreached block 0x32 - 0x32 (size=2)
Unreached block 0x11c - 0x122 (size=8)
Unreached block 0x170 - 0x288 (size=282)
ezstack.c:1961: error
sim.addr = 0x53e sim.opcode=962c

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

12oclocker wrote:
It does not seem to detect any ram usage in my interrupts [...]
In my implementation, the code analyzes the stack use of all ISRs. It then adds the maximum of the stack use of all of the ISRs to the maximum direct use by each task (including the stack space needed to save the context due to a task switch) to arrive at the potential maximum stack use for each task.

Obviously, this strategy involves several assumptions including that interrupts are not nested and that the interrupt whose ISR has the maximum stack use could occur at the point of maximum direct stack use of the task. Clearly, this represents a worst-case analysis that may or may not reflect the actual maximum use that would be seen when the application runs.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

12oclocker wrote:
or does it not analyze interrupts for this chip?
Version 2 expected "jmp" to interrupts. For tiny micros avr-gcc generates "rjmp". I added rjmp in version 3.
Quote:
ezstack.c:1961: error
sim.addr = 0x53e sim.opcode=962c
That I do not know. I would need to see the lst file generated by the compiler. Or at least a part of it around the 0x53e address.

Eugene

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ezharkov wrote:
12oclocker wrote:
or does it not analyze interrupts for this chip?
Version 2 expected "jmp" to interrupts. For tiny micros avr-gcc generates "rjmp". I added rjmp in version 3.
Quote:
ezstack.c:1961: error
sim.addr = 0x53e sim.opcode=962c
That I do not know. I would need to see the lst file generated by the compiler. Or at least a part of it around the 0x53e address.

Eugene

Hopefully I copied the correct thing for you...
If not let me know and I'll get you the entire file somehow (drop it on my webserver or something and post up a link)

	lcd_char('z');
 52e:	8a e7       	ldi	r24, 0x7A	; 122
 530:	9e dd       	rcall	.-1220   	; 0x6e 
 532:	10 e0       	ldi	r17, 0x00	; 0
	//fill the rest of the line with spaces
	for(i=0; i
	if(lenR > 6){ lcd_char('M');}//MHz
	else if(lenR > 3){lcd_char('K');}//KHz
	lcd_char('H'); 
	lcd_char('z');
	//fill the rest of the line with spaces
	for(i=0; i
	{ lcd_char(' '); }
}
 53e:	2c 96       	adiw	r28, 0x0c	; 12
 540:	0f b6       	in	r0, 0x3f	; 63
 542:	f8 94       	cli
 544:	de bf       	out	0x3e, r29	; 62
 546:	0f be       	out	0x3f, r0	; 63
 548:	cd bf       	out	0x3d, r28	; 61

I came across this while reading some of your notes in the program, have you contacted anyone over at WinAvr to see what they thought about this...

Quote:

/* fixme5: I do not quite understand what WinAVR-20080610 does.
Here it sets only SPL. But everywhere else, when it allocates
stack frame, it does in/out 0x3e. Looks like a bug.
Both in 20090313 and 20080610. */

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

12oclocker wrote:
ezstack.c:1961: error
sim.addr = 0x53e sim.opcode=962c
Well, apparently my generic RRR function does not give any useful info in this case. Sim.addr in this case contains an old value which is of no use at that point. I added another printf in version 4.

Quote:
Hopefully I copied the correct thing for you...
If not let me know and I'll get you the entire file somehow (drop it on my webserver or something and post up a link)
This may help ...

Quote:
Looks like a bug.
No, I have not contacted anyone. Also, a "bug" maybe a bit of a strong word. Maybe I should have called it "missed optimization" or something.

Eugene

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

humm, this is the output on version 4...
ezstack4.exe version 4
Text size = 1944
Unreached block 0x11c - 0x122 (size=8)
BlockAddr=718 size=5 change=-3
ezstack.c:1992: error
sim.addr = 0x53e sim.opcode=962c

Hopefully this will help...
Here is the link to my elf, and lss files...
http://24.223.190.157:81/2313_freq_counter_lcd.lss
http://24.223.190.157:81/2313_freq_counter_lcd.elf

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
BlockAddr=718 size=5 change=-3
ezstack.c:1992: error
Well, the short answer is that avr-libc is not currently supported.

The longer story. When I started on the whole thing, I thought that I would simulate the whole program. That was taking too long to implement and I needed something quickly. So, I gave up on simulation and instead decided to look for specific stack frame allocation/deallocation sequences generated by the C compiler. Avr-libc functions, written in assembly, do not use the same sequences. But I do not personally use avr-libc, so that works fine for me. I may come back to simulation in the future ... but I'm not sure if I will have any time for that any time soon.

This particular case does not look too bad and can be fixed relatively easy. Maybe I will look into that over the weekend. What ezstack does not like here is this. It "splits" the entire program into blocks (SimBlock). A SimBlock is a continuous set of instructions with a single entry point from outside. I.e., there are no jumps to the middle of the block from outside. The utility currently expects that there is one SimBlock at the beginning of each C function that allocates a stack frame and there is one SimBlock at the end that deallocates. The block at the end of the function must end with a "ret" (or "reti"). In your program, the block that starts at 0x718 does not have a "ret". Instead it jumps to another block. The fix is to check to see if the block it jumps to has a "ret". If yes, we are good...

Eugene

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah! I see...

Quote:
This particular case does not look too bad and can be fixed relatively easy.

not for me, lol, maybe easy for you, lol

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ezharkov wrote:
Maybe I will look into that over the weekend.
Well, did not have much time last weekend. Did not really have much time this weekend either. But there is a new version now, which does not complain about ultoa.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wek wrote:
I was about to ask you to include the "short" form of jumptables which occurs at the models where rjmp can reach through all the FLASH, into your stack occupancy calculator.
Well, this sort of was there even in the previous version. I made some more changes/fixes in the latest. But no guarantees.

Quote:
PS. Just a rough idea, once at it: couldn't the program at startup parse a simple file with manually provided stack usage at certain addresses (e.g. for hand assembly snippets), which then wouldn't be checked at the run of the program?
I guess it would be nice to implement something like that. But on my personal list of priorities this is low at this time (because I do not really use neither assembler nor avr-libc).

Eugene

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ezharkov wrote:
ezharkov wrote:
Maybe I will look into that over the weekend.
Well, did not have much time last weekend. Did not really have much time this weekend either. But there is a new version now, which does not complain about ultoa.

very nice work on the new version, ran it on my at902313, attiny2313, and attiny24 projects and everything looks good, nice job!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ezharkov wrote:
wek wrote:
I was about to ask you to include the "short" form of jumptables [...]
Well, this sort of was there even in the previous version. I made some more changes/fixes in the latest.

Thanks. Seems to be working. I was trying to track the ijmp logic in V4 and it appeared to me that the short form is not there, although the changelog hinted it should be there somewhere.
ezharkov wrote:
But no guarantees.

Come on, Eugene. Only a fool would expect explicit guarantees. I am very happy you shared your work, and it's great, I appreciate it. Thank you.

ezharkov wrote:
wek wrote:
PS. Just a rough idea, once at it: couldn't the program at startup parse a simple file with manually provided stack usage at certain addresses (e.g. for hand assembly snippets), which then wouldn't be checked at the run of the program?
I guess it would be nice to implement something like that. But on my personal list of priorities this is low at this time (because I do not really use neither assembler nor avr-libc).

Looking forward to it... ;-)

Jan