stacks organization

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My understanding is that AVR compilers that are not avr-gcc use two stacks,

one for data and one for return addresses.

When divvying up SRAM, said compilers lump the heap with one of the stacks.

The pair have a combined memory allocation and corresponding size limit.

The other stack has a size limit of its own.

That would make sense if both stacks had to grow down,

but they do not.

The data stack can grow upward and the heap often has size zero.

To me, it would make the most sense to give the stacks the combined allocation.

Am I missing some constraint?

If not, is there a compiler that lumps the two stacks?

 

Edit: To be clear, this has no immediate application for me.

I'm just curious about something that seems strange to me.

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods

Last Edited: Fri. Sep 9, 2016 - 01:49 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I often recount the description of a sat TV recorder I worked on that had 8MB RAM. The software was basically two large components melded together. One part came from the company that did the scrambling/encryption system and they were paranoid about security to the point where they didn't want to share the heap where our code/OS would work. So at system start up they made a single 3MB malloc then operated their own "private" heap in that. This lead to stupid situations where one or other heap would run out of memory when the other had plenty free. I've never understood the thinking behind splitting data areas like this whether it's heaps or stacks or whatever.

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

For the good and the bad :) data on the heap can live after a function returns.

 

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

1)  How many AVR8 programs use a heap?

1a) How many "real microcontroller" AVR8 apps, say 16KB flash or smaller so about 1KB of SRAM, use a heap?

 

I'd speculate the answer is "virtually none" so heap discussions are almost moot.

 

2)

skeeve wrote:
When divvying up SRAM, said compilers lump the heap with one of the stacks.

 

Really?  I suppose if they are next to each other and heap grows up and stack grows down one could think of it that way.  But CodeVision doesn't seem to do it that way.  Taking an arbitrary test program and configuring for 128 byes of heap

...so the heap is stolen from the top of SRAM, never to be seen again.  Then going downward the hardware stack grows downward towards the global variables.

 

In CV we see that the data stack is allocated to a defined size at the lowest SRAM addresses.  It grows downward in that region.

                 ;HARDWARE STACK POINTER INITIALIZATION
000057 edef      	LDI  R30,LOW(__SRAM_END-__HEAP_SIZE)
000058 bfed      	OUT  SPL,R30
000059 e0e7      	LDI  R30,HIGH(__SRAM_END-__HEAP_SIZE)
00005a bfee      	OUT  SPH,R30
                 
                 ;DATA STACK POINTER INITIALIZATION
00005b e6c0      	LDI  R28,LOW(__SRAM_START+__DSTACK_SIZE)
00005c e0d2      	LDI  R29,HIGH(__SRAM_START+__DSTACK_SIZE)

So CV isn't as you described, but I have no idea what the rest of the bunch do.

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

theusch wrote:
...so the heap is stolen from the top of SRAM, never to be seen again.  Then going downward the hardware stack grows downward towards the global variables.

 

In CV we see that the data stack is allocated to a defined size at the lowest SRAM addresses.  It grows downward in that region.

Ouch.

The worst of all worlds: three separate fixed allocations.

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods

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

skeeve wrote:
The worst of all worlds: three separate fixed allocations.

 

From above:

theusch wrote:
'd speculate [heap use in AVR8] is "virtually none" so heap discussions are almost moot.

 

Thus, I'd opine "three two separate fixed allocations".  Why is that so?

 

I've done compilers and similar translators/interpreters in a past life.  Always tradeoffs, and one develops a "code generation model".  In this case, and perhaps lost in the annals of history, the AVR inventors (or maybe Atmel by that time) worked with IAR on refinements.  IAR developed the twin-stack model for AVR.  (I wonder if the white paper is still hanging around on the 'Net...)  That probably is the genesis for CV and the others.  Except GCC just adapted its inherent single-stack model to the AVR.

 

[edit] The "white paper" used to be at "/modules/FreaksFiles/files/608/RISCMCU.PDF"  IIRC that is a somewhat different document than http://www.compass-lab.com/pdf/A...

 

Aha!  http://www.atmel.com/Images/COMP...

The number of memory pointers

The AVR microcontrollers were originally equipped with two 16-bit memory pointers.

From a C Compilers point of view, one of these pointers must be used as a dedicated

software stack, leaving only one memory pointer for general usage. In many cases, you

need to copy memory from one area to another. Having only one memory pointer, you

would need to read one byte, set the pointer to the destination area, write the byte and

then set the pointer back to the source data area. By including a third memory pointer

(with reduced functionality), data can be copied from one memory area to another

memory area without having to set the pointers.

 

Now, you might ask, why "must" that pointer be to a "dedicated software stack", and not a pointer to a combined hardware/software stack?  Dunno.

 

 

I've been in AVR-world for the past 15 years.  Y'all that might have worked with x51 and Moto and MSP430 and PIC, with Keil and other mainstream compiler vendors, can comment on how many stacks are in those microcontroller combinations.

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Fri. Sep 9, 2016 - 07:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

On further thought, given the AVR instruction set, there is a case for two stacks and for both of them to grow down.

The SP stack grows down.  That is how it works, so no real choice.

Local variables suggest that a non-SP stack might be useful:

AVRs have no SP-relative addressing.

Displacements in the LDD instructions are positive.

 

If one really wants, there is a workaround that will let one have local variables on an upward-growing stack:

Use X for the stack pointer.  Use Y for a frame pointer.

When a frame pointer is needed,

the cost relative to the SP-Y model is the X registers.

When a frame pointer is not needed,

the benefit is having the Y register available instead of the X register.

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods

Last Edited: Sun. Mar 12, 2017 - 08:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The worst of all worlds: three separate fixed allocations.

Sort of.  I mean, either you know how much each section is going to use, and fixed allocation is fine, or you don't know how much they're going to use, in which case you risk collisions.

 

The AVR stack pointer is "accessible", but it's not really convenient for accessing local variables on a stack frames; you have to copy it to one of the index registers first, anyway (extra overhead!)  If you're going to use stack frames all the time, you might as well leave something in one of the index registers permanently.  (gcc probably survives because it usually manages to keep the local variables in registers?)

 

Displacements in the LDD instructions are positive.

And yes, that probably explains the "grow down."

I've sometimes wished that the AVR had a more "traditional" architecture where the SP, PC, and Status register actually appeared in the "register" part of the architecture.  37+ bytes worth of context is a lot for an 8bit CPU.