Re: [bascom] UnderStanding the SRAM Usage and also STACK PART II


From "Baroni, Nicholas" <NBaroni@skm.com.au>
Date Fri, 24 Jan 2003 17:03:17 +0800

Patrick Timlin, myself and others had a discussion about SRAM usage back in 
October last year.
Also touched on data statements, simulator use, memory maps etc.

The list archive is at http://www.grote.net/bascom and is a good source of 
knowlegde for newbies although it can be a little "random"

Looks like the message from the 23rd October isn't in the archive though so 
it is reproduced below.

Regards,
N.

Subject: Re: [bascom] Memory useage calculations (stacks and Frame)
Date: Wed, 23 Oct 2002 10:11:36 +0800
From: "Baroni, Nicholas" <NBaroni@skm.com.au>
Reply-To: bascom@grote.net
To: bascom@grote.net
References: 1 , 2 , 3

Patrick Timlin wrote:
> 
> My replies embedded below...
> 
> "Baroni, Nicholas" wrote:
> 
> > There appears to be 4 distinct areas in a compiled bascom avr program's 
> > Ram space.
> > The areas are Hardware stack, Software stack, Frame and Global variables.
> >
> > Hardware Stack
> > Where the CPU holds return addresses, saves registers etc.
> > Use an interupt without the nosave option and you need at least 34 bytes 
> > of hardware stack.
> > You can usually get way with nosave and push the X Y Z registers R31 - 
> > R26 yourself - min of 8 bytes vs 34.
> 
> OK let's start with this one. In my very simply program I am not using 
> interrupts nor am I calling subroutines. So can I assume
that I don't need any hardware stack, or at least I can ignore it and except 
the BASCOM default value (64 bytes is what it comes up
with for the mega163)?

That would be a valid assumption.  Unless you are doing something complex, 
the defaults work ok. I use what ever Bascom comes up
with as defaults for the device and if the simulator tells me I have problems 
or the program physically doesn't work, then I go to
the effort of figuring out what is required. If I use an interupt, I 
automaticly alter the hardware stack size (+32) as the default
undersizes it for the sorts of devices I use.  64 is plenty for an ISR.

> 
> > Software Stack
> > The software stack is used to store the addresses of LOCAL variables and 
> > for variables that are passed to SUB routines.
> > Each LOCAL variable and passed variable to a SUB, uses two bytes to store 
> > the address.
> > So count the maximum number of locals and passed parameters to a sub and 
> > multiply by 2.
> > If you are nesting things, count everything down the line.
> > On top of this number, add 4.
> >
> > What you have now is the amount of memory assigned to pointers, you now 
> > need the actual variable location itself - these are in
the frame.
> 
> OK again, not using any subroutines or functions for that matter, so I am 
> not passing anything nor do I need any local variables.
All my program's variables are global, so again, can I just use the default 
for this or some minimal number?
>

In this case, there is probably little more than internal usage of the 
software stack - extent of which I don't know.  Again,
accept the defaults and if it aint broke don't try to fix it.  If you do run 
into problems then do the sums an see if your stack is
large enough.  
 
> Does BASCOM use the HW or SW stacks for internal stuff (things I don't 
> declare myself) that I always need to assign a little bit
of memory to allow for these internals?

I am unable to comment on the inner workings of bascom but I assume this is 
the 4 refered to in the help file, Mark Alberts,
Bascom's author would be better placed to comment.


> 
> > Frame
> > Sort of like scrap paper for working things out, contents only matter in 
> > the context of the current operation such as writing
LCD, doing some big complicated sum in a function etc.
> > Count the number of bytes required, depending on variable type of all the 
> > locals and passed parameters.  Add 16 to this number.
> >
> > Global Variables
> > Things you Dim in the start of your program occupy fixed RAM addresses.
> > Count number of bytes required for all dimmed variables depending on type.
> >
> > The total sum of hard and soft stacks, frame and global variables needs 
> > to be less or equal to the available controller
resources.
> 
> OK that makes sense, but where do the Global variables go? I mean I know 
> they go into SRAM, but do they factor into the frame or
the stacks?
 
The globals (variables defined by DIM at the start of the program) go into 
the RAM in the order they are defined, starting at the
beginning of ram - address 0x60 / 96d (AT90 series at least) this can be seen 
from the compiler report where it gives the address
of all variables and lables.

> I think, if I am getting this, Globals get factored into the stack with the 
> addition of any "scratch work" that needs to be done
like PRINTBIN (var). For example, if I have three variables of type byte and 
at one point in my program I do a PRINTBIN (var) where
"var" is one of my byte type
> variables, then is my stack space 3 bytes for the variables plus 16 bytes 
> for the PRINTBIN command for a total frame space of 19
bytes?

As far as I can tell, the software stack is used exclusively for containing 
pointers (the addresses) of variables located in the
frame.
The globals live in lower ram.  Mark specifies a minimum frame size for 
certain functions to work.  I don't think it is nescessary
to increase the software stack in the manner you describe.
 

> 
> If later I then do a command of LCD (var) of that same byte variable, do I 
> need to add anything for that? My reading of your
reply was that I don't since after the PRINTBIN command, those 16 bytes are 
freed up and will be reused later by the LCD command.
Is that correct?

Yes.

> 
> > The controller's program will just consume memory as required. Stacks 
> > change size as the program runs, depending on what is
happening. The settings allow you to space the areas apart in RAM. If one 
area is too small, it will just grow into the adjacent
area, corrupting the data that was there.  The simulator tracks the maximum 
stack size during simulation and lets you know (via a
tick box) if either stack runs into anything else.
> 
> OK I will have to learn to use the simulator a bit more. I haven't been 
> using it much since my small programs are just as easily
programmed into the chip and tested out for real. Oh one quick question on 
the simulator you might be able to answer for me right
now. When I use WAIT statements, they take FOREVER in the sim. For example a 
WAIT 1 might take a minute before it goes to the next
command. How can I speed this up?

Use the $sim directive at the start of the program, complie, simulate. When 
happy, remove $sim, recompile, flash the chip.

> 
> > Stacks growing into the addresses occupied by other data is a common 
> > cause of weird behaviour.
> > Look at the compiler report and draw up a memory map from the information 
> > there and you will see how the memory is used.
> 
> OK I will take a closer look and see. Drawing up my own map will probably 
> be a big help if I can sort of visualize the full
memory space.

The compiler report has everything you need to do this. They typically look 
like this for a 2313...

+--------------+  Top of ram 0xDF  (0x25F for an 512 byte processor like the 
8535)
|   Hardware   |
|     stack    |
+--------------+
|   Software   |
|     stack    |
+--------------+
|    Frame     |
+--------------+
|              |
|  User Dimmed |
|   Variables  |
|              |
+--------------+  Start of ram 0x60

The potential for calamity is clear, 
Put too much on the hardware stack, the hardware stack pointer impails the 
software stack, corrupting the data there which then
causes subroutines to pull a value from anywhere in Ram.  Using interupts 
with a small hardware stack <36~38 bytes is disaster. The
simulator tells you the depth to which the stack reaches during simulation.  
If it falls below the end address of your stack, you
are in trouble.

Put too much on the software stack - too many locals and parameters and the 
software stack pointer impails the frame.  This
corrupts the local vaiables and the subroutines and fuctions will return 
incorrect results.  The simulator also tells you the depth
to which the stack reaches during simulation.  If it falls below the end 
address of your stack, you are in trouble.

Define more variables than you have memory for after the stacks and frames 
and your variables will suffer unexpected changes.
As a check, calculate the lower frame boundary from the info in the compiler 
results,

Framesize    : 18 hex
Framestart   : 207 hex

This puts the lower edge of the frame at 0x1EF. (0x207 - 0x18)
If you have more than 400 bytes of variables (0x1EF - 0x60) the ones located 
about 0x1EF will get clobbered 

Sizing these things is critical for complicated programs and a first read of 
the help file it isn't obvious.
For simple stuff the memory utilisation isn't high you can usually ignore it. 
 I recently did a job in a 4433 where there were only
3 ram locations remaining and all this memory usage stuff became important as 
the hardware was already committed and I didn't want
a 40 PDIP on the board.



> 
> > > I have set up DATA statements to hold the data that
> > > goes into the arrays. So for each array, I do a RESTORE to
> > > point to the DATA line for that array, then do a loop to read in the
> > > data and fill each array. So I have three DATA lines with 12, 12, and 9
> > > elements respectively. Do these take up additional SW stack space? In
> > > other words, do I need the 36 bytes PLUS another 12+12+9 for the DATA
> > > statements? Do RESTORE and READ statements require stack space (RESTORE
> > > is basically a pointer right?).
> >
> > If these are dimmed they occupy fixed addresses - check the compile 
> > report to see where they are.
> > You have used 36 bytes, dedicated to your dimmed variables
> >
> > I'm uncertain but I think data statements are coded into flash and read 
> > with LPM into ram.
> 
> LPM?

LPM is an AVR opcode for loading a specified register with the contents of 
the flash memory location pointed to by the contents of
the Z register (R30/R31) pair - AVR only. The only obvious method I can see 
in the instruction set of getting data out of the
flash.

> Now that I am giving it more thought, I bet that the data lines are simply 
> stored in flash as constants and the RESTORE statement
is a pointer that is probably kept in one of the registers BASCOM uses 
(reserves) so I probably don't need to dedicate any memory
use to those other than to the 36 bytes needed to DIM my three arrays. Maybe 
Mark will comment on that for us.

That is also the way I understand it.

> 
> Thanks for your reply and in advance for next (I hope) reply.
> Patrick

Bascom is fantastic for quickly prototyping something, but the fact remains 
that although it is BASIC, it is running an a
microcontroller and the hardware and resource usage aspects are important and 
can't be hidden under the language in the same way
say programming for a PC can.





Panther Electronics wrote:
> 
> PART II
> 
> Now that we have seen the usage of STACK, and its limitation, we shall look 
> at other method's of Saving Registers and also What, Where and How the 
> STACK is.
> 
> Fundamentals of the STACK:
> 
> The STACK is just a Storage Space in the SRAM, The STACK start's from some 
> address in the SRAM space available on the uC, this address of STACK memory 
> is stored in the "Stack Pointer" ( SP ). The SP is one of the I/O register 
> in the uC Hardware 64 I/O registers of the uC. This STACK memory space 
> cannot be used for any thing else.
> 
> POINTS to remember
> 
> 1.      In some uC there is no SP and in Some uC the STACK is limited in 
> the hardware itself to 2~3.
> 2.      In ATMEL AVR uC with SRAM < 256 the SP is 8 bit and in uC with SRAM 
> > 256 its 16 bit.  (SPL & SPH)
> Note: all 16bit registers must be read / write first to the Upper register 
> and then to lower register.
> 3.      It's advisable to initialize the SP to the last available SRAM 
> memory location. In 90at2313 it would be 223 (&HDF) ( 32+64+128=224 ie 0 to 
> 223)
> 4.      In any Case it must be above address of Start of SRAM and not more 
> than End of SRAM.
> 5.       The SP is decremented by one when a DATA is PUSHed on the STACK 
> and its incremented by one when a DATA is POPed from the STACK. This is 
> done by the uC itself.
> 6.      The SP is decremented by two when a ADDRESS is PUSHed on the STACK 
> and its incremented by two when a ADDRESS is POPed from the STACK. This is 
> done by the uC itself.
> 7.      The uC itself uses the STACK to save the "Return Address" from the 
> ISR ( Interrupt Service Routine ) and
> 8.      Also when Sub Routines ( RCALL ) are called. Hence its important to 
> initialize the SP on powerup in the RESET vector Before Enabling the 
> Interrupts or using RCALL.
> 
> BASCOM does this for you, and this STACK is Called The HW Stack in Bascom. 
> HW stack in BASCOM means that STACK memory used by the uC itself and also 
> while entering into Interrupts memory space to save the 32 general purposes 
> registers. (This is where the NOSAVE option can be used to disable PUSH of 
> all the 32 Registers).
> 
> BASCOM also Uses Additional STACK called "Softstack" and "Framesize".
> 
> I have little understanding of these, what I get is this much
> 
> "Softstack": The memory area begins immediately after the end of HW stack 
> area.
> 
> This is STACK area used temporarily by the calling "CALL SUB" or 
> "FUNCTION". It's used to store the address of the PASSED Variable and also 
> the address of the LOCAL Variables used in the SUB or FUNCTION.
> 
> Example:
> 
> Declare SUB Report ( byref Bugs as byte)
> 
> Main:
> Do
>         Temp = 35
>         Call report ( temp )
> loop
> 
> Sub Report ( byref Bugs as byte )
> Local Srikanth as byte
>         '/* send message to Mark */
> End sub
> 
> In the above example we are passing one variable hence 2 Softstack is 
> required ( note the size of the passed variable does not matter, because 
> the BASCOM passes the Address of the variable?). The Sub uses one local 
> variable hence 2 more Softstack is required. Hence the total Softstack 
> required would be 12.
> 
> Ha, yes there is no calculation mistake here, 12 = 4 because of me + 8 
> required by BASCOM.
> 
> Now if the sub was declared as "Declare SUB Report ( byVal Bugs as byte)", 
> then I think the softstack required would be 14 ( because ByVal makes the 
> Passed variable LOCAL to the SUB?)
> 
> "Framesize": boy, this is difficult and am not sure what happening here, 
> this space is used by BASCOM for lots of things, let me try to list it ( 
> please note this information is not vetted by Mark, hence tread with 
> caution )
> 
> 1.      Temp SRAM Space for usage by the SUB or Function to store the Local 
> variables, the address of which is stored in the "Softstack".
> 2.      PRINT, LCD and most String function  available in BASCOM uses this 
> area.
> 3. Bascom REQUIRES 16 bytes by default, hence in the example above the 
> frameSize = 17= ( 1 for Srikanth + 16 default ) and for ByVal 18 ( 1 for 
> Srikanth + 1 for ByVal + 16 default )
> 
> End of PART II
> 
> I hope the STACK and SRAM is understood a bit better.
> 
> ?. To be continued.
> Ran out of Time and also the e-mail Size restriction, will send the balance 
> parts of this next week. Requesting all Guru's to correct any error in 
> understanding of the general working of uC and its memory usage.
> 
> Srikanth Kamath T
> PS: Hi, I would like some feed back, to correct any mistakes, please use my 
> e-mail ID panther@vasnet.co.in for reply. ( please do not reply back to the 
> list )

-- 
 --
 Nick Baroni.
 
 Mechanical Engineer
 Sinclair Knight Merz,
 263 Adelaide Tce, Perth WA 6001, AUSTRALIA
 ph +61 8 9268 4517
 fax +61 8 9268 4495
 GSM 0438 877 263
 http://www.skm.com.au; mailto: nbaroni@skm.com.au
 
 NOTICE: This message contains privileged and confidential information
 intended only for the use of the addressee named above. If you are not
 the intended recipient of this message you are hereby notified that you
 must not disseminate, copy or take any action in reliance on it. If you
 have received this message in error please notify Sinclair Knight Merz
 Pty Ltd immediately. Any views expressed in this message are those of
 the individual sender, except where the sender has the authority to
 issue and specifically states them to be the views of Sinclair Knight
 Merz.