Running out of data space PIC16F1934

Thread Starter

Stuntman

Joined Mar 28, 2011
222
So I am rapidly approaching the memory limits of this particular chip. So in order to free up some additional (data) memory for a large buffer, I started reusing some global variables, and removing as much as possible. This as great as the compiler recognized this when I compiled.

However, I then found I had some local variables that could be reduced in size. When I did this (reduced some int to char), the compiler found no difference in data space. Intrigued, I moved these variables and made them global, only to find they then added to the data space.

What gives here? Why are my local variable seemingly being stored differently than my global variables?
 

joeyd999

Joined Jun 6, 2011
5,283
So I am rapidly approaching the memory limits of this particular chip. So in order to free up some additional (data) memory for a large buffer, I started reusing some global variables, and removing as much as possible. This as great as the compiler recognized this when I compiled.

However, I then found I had some local variables that could be reduced in size. When I did this (reduced some int to char), the compiler found no difference in data space. Intrigued, I moved these variables and made them global, only to find they then added to the data space.

What gives here? Why are my local variable seemingly being stored differently than my global variables?
IIRC, in C, globals have a permanent physical location in ram. Locals are stored on a stack, and are allocated/deallocated on an as-needed basis within the (fixed sized?) stack. Do you have a compiler option to adjust the stack size?
 

ErnieM

Joined Apr 24, 2011
8,377
Generally local variables are stored on the stack so they can be poped out of existance when the routine using them terminates. Thus they don't appear to use any RAM but still they do, if only for a short while.

Try declaring them static and watch your memory grow.
 

John P

Joined Oct 14, 2008
2,026
This type of PIC processor doesn't use a stack for assigning variables, only for storing return addresses during interrupts and subroutines. Anyone who knows the silicon, knows this.

I could explain what you're seeing if your compiler is like my way-outdated CCS compiler. With this compiler, an INT is actually 8 bits; if you want a 16-bit variable, you call it a LONG (nowadays they've gone to INT8 and INT16). If INT was just one byte, it would be the same as CHAR, so you wouldn't "reduce" anything by using CHAR instead.

A local variable isn't kept once a subroutine ends, and multiple subroutines can successively use the same memory space. I've noticed that my compiler doesn't do this as a first choice, but it will re-use memory if it's running short--just the way it should. But if you make a variable global, then it holds its value throughout the program and can't be re-used, and the result is that the program needs more RAM. I would bet that you'd see the same result if you declare a variable STATIC, as that would also forbid re-use of the same RAM location.
 

joeyd999

Joined Jun 6, 2011
5,283
This type of PIC processor doesn't use a stack for assigning variables, only for storing return addresses during interrupts and subroutines. Anyone who knows the silicon, knows this.
Ummm, it is well known here that I don't use C for PICs, but my understanding is that at least some compilers implement a software stack for function arguments and local scope variables. That the silicon does not have a built-in hardware stack is irrelevant.
 

ErnieM

Joined Apr 24, 2011
8,377
It is quite common for PIC C compilers to create a "soft" stack, one maintained in RAM rather than on the very limited hardware stack.

Concerning the PIC16F1934 device, check section 3.4.1 of the data sheet. It shows how to manipulate the hardware stack in ways that allow a software stack to operate on this core. Basically a function call prolog and return code change the hardware stack to make it do things that C would prefer it to do.

I cannot comment on this specific compiler working this way on the device, as the compiler is not specified.
A local variable isn't kept once a subroutine ends, and multiple subroutines can successively use the same memory space. I've noticed that my compiler doesn't do this as a first choice, but it will re-use memory if it's running short--just the way it should.
Consider two routines Foo() and Bar() that both use local variables. If Foo() calls Bar() then Bar() is free to mess with it's locals, which *may* be the same locals as Foo() is expecting to remain constant. That may lead to data corruption and soft errors. Yuck.

Unless the compiler is doing a full call chain search it is a very dangerous thing to reuse RAM like that. It may be doing that check, but I would be very careful before using that "feature."
 

Thread Starter

Stuntman

Joined Mar 28, 2011
222
Very interesting.

I am using HiTech C for PIC10/12/16 V9.83.

I have plenty of "time" in that I can use a capture/compute algorithm for each step instead of loading up a buffer, but I am curious about these kinds of things.

So how big is this "soft stack"?

Considering what I'm seeing on the output when I compile some of my variables (local) ARE being overwritten, IE, some kind of common RAM used for various variables.

Is there a good reference I can read up on how to customize the way this memory is used?

John P - When you say just for returning addresses after interrupts, are you referring to the hardware stack?

l understand where you are going with the char vs int vs int16. On the compiler (HTC), int variables are automatically assigned 16 bits, chars 8. Some of the variables in question were being converted from long to int, so there is certainly something else going on here.
 

spinnaker

Joined Oct 29, 2009
7,830
The size of the stack should be configurable. You should have a default linker file for your device that shows it's stack size.

In C18 compiler the extension for the file is .lkr

The entry looks something like this:

STACK SIZE=0x100 RAM=gpr12


Check the HiTech C user guide for methods on configuring memory.
 

ErnieM

Joined Apr 24, 2011
8,377
The soft stack is as big as you told it to be. HOW you tell it the size depends on which compiler you use. Both HI-TECH C and C32 have a setting in the Project | Build Options | Project menu item, while C18 seems to want a custom linker script to control stack.

Same applies to the heap, you define how big.

When all you have is 256 bytes of RAM most of these techniques are not of much use. In fact, the stack tab is greyed out when working with the PIC16F1934. Things do start to get interesting in a PIC18F4550 with 2K of RAM, and just awesomely great on something like a PIC32MX460L512 with 32KB of RAM.
 

John P

Joined Oct 14, 2008
2,026
Stuntman--yes, I meant the hardware stack. If a compiler implements a soft stack as part of its operations, that would be something else again. And I'm not surprised that it's unusable on smaller processors.

Re the example involving foo() and bar(), it's vital for the compiler to maintain a hierarchy of which functions call which other functions. It might be complicated, but it just has to be done. If main() calls both foo() and bar(), then they can share RAM, but if one calls the other, that's not going to be possible. CCS produces a list file as part of the compilation process, where all the variables are shown along with the addresses that they use, and you can see what's being used more than once. I don't know if other compilers do this. Anyway, with the smaller PIC processors the compiler should be watching the level of function calls, because the stack is so tiny. Another thing CCS does (others too?) is tell you what the maximum stack usage is going to be.

I remember reading about a problem where both main() and an interrupt need to call a given function. If main() calls the function and then gets interrupted, and the interrupt jumps into the same function, what should happen? Maybe the compiler indicates an error for this, I don't know.
 
Top