I wrote some code earlier and couldn't get it to work. It turned out that two of my buffers were overlapping. I've chopped it down to minimal code but can't see what I have done wrong.
Max memis 0x7F which is less than 0x80 by 1 byte so you are way over board here. Your 1 variable takes up entire access ram. And such the ID Variable takes over or points to the last 10 bytes.
MPLINK 4.20, Linker
Copyright (c) 2008 Microchip Technology Inc.
Error - section '.udata_main.o' can not fit the section. Section '.udata_main.o' length=0x00000050
Errors : 1
hi Mike,
As you know I am not a C person.
Looking at your IDbuffer & char buff[80] the only difference I can see is that you have defined a char_bfr as 80 long static and IBuff as[] undimensioned as dynamic.??
you will still get a overlap. (just tried it) I know it has to do with linker but i dont know how to fix. These linker things suck really. Where would one get the information from to make a linker script? The datasheet i suppose... so im off to read it to hopefully modify the link to work with it.
hi Mike,
As you know I am not a C person.
Looking at your IDbuffer & char buff[80] the only difference I can see is that you have defined a char_bfr as 80 long static and IBuff as[] undimensioned as dynamic.??
Even if I change it to IDbuffer[10] it's still the same. I'm guessing that there is something I don't understand about initialised global ram variables.
C generally puts local auto variables of a function on the stack. You stack has a max size of 64 (0x40) bytes so your buff[80] is too large to fit on the stack. Don't confuse this with the hardware stack. This stack is managed by the C compiler and uses the FSR registers.
EDIT: You can change the allocation size of the stack by editing the linker script file. You'll see the change in the "memory usage gauge" after you recompile.
I just downloaded the latest version of the C18 compiler (3.22) and you no longer have to include a linker script. This solved the problem without any changes.
<edit> Make sure you click the option to use the latest MPLINK in MPLAB.</edit>
It's the area of RAM that can be accessed by setting the access bit in an 18F instruction. It eliminates any need for bank switching. Variables that are used frequently are put in the access RAM for better code efficiency. The SFRs are also in this area which is split into two parts just to confuse things further.
Pommie said:
I just downloaded the latest version of the C18 compiler (3.22) and you no longer have to include a linker script.
It's the area of RAM that can be accessed by setting the access bit in an 18F instruction. It eliminates any need for bank switching. Variables that are used frequently are put in the access RAM for better code efficiency. The SFRs are also in this area which is split into two parts just to confuse things further.
Maybe I should have worded it better. What I meant was, what does the compiler use it for. The map file for the above code shows 2 bytes used out of 128 total and yet I get a stack crash because the compiler is cramming everything into the top 128 bytes. Even on the most complex program I have (using a 1320) there is still only 35 bytes of accessram used.
To put something in access RAM, you're supposed to use the near qualifier under main, but it doesn't appear to work in the version I have. Now I really have to try the updated version.
Otherwise, I think the compiler just uses the access RAM for internal scratch pad use.
Yes, it seems silly that the compiler will just ignore all that extra memory. I guess ANSI C has no definition of banked memory; but you would have thought MicroChip would have broken the rules a bit to make it work better.
C generally puts local auto variables of a function on the stack. You stack has a max size of 64 (0x40) bytes so your buff[80] is too large to fit on the stack. Don't confuse this with the hardware stack. This stack is managed by the C compiler and uses the FSR registers.
1) Because I am a bit confused, instead of FSR you mean GPRs right?
2) So that stack is used when a function is called so that it can pass around the variable?
3) If so, why is that a problem in Pommie's program since what is passed, it is actually the address of the first array element (i.e. the stack should be enough)?
The problem with my code was that the compiler places local variables on the stack and so my 80 byte variable overflowed the 50ish byte stack. You are correct that only the address of the array was passed but the function defined a local variable that had to be placed on the stack as well.
I'll try to answer your questions,
1. The FSR register is actually an indirect memory pointer and is used (by C) to access the software stack.
2. Yes. It's also used to return values.
3. See above.
You are correct that only the address of the array was passed but the function defined a local variable that had to be placed on the stack as well.
...
2. Yes. It's also used to return values.
...
Why is buffer placed on the stack if it only used locally? As you said in answer 2 (above) stack is used when data is passed or returned. However, buffer variable is just used locally and it's not passed or returned, so why is it placed in the stack?
It's placed on the stack because it is temporary and the only safe place to use is the stack area. When a function is called, the passed variables are placed on the stack, the local variables are then allocated (placed on) stack space and finally when the return directive is met the stack is cleared and the return value is added.
Imagine trying to sort out local variables in non stack area.
To add to Pommie's comments:
Another advantage of placing variables, local to a function, on the stack is that it saves memory. When the function returns, the memory for the local variable is freed, and ready to be used by the next function. ie: You could have 8 different functions, each with 128 bytes of local variables, on a chip with only 256 bytes of RAM. This assumes that only one function is called at a time.