![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
AArdvark
Joined: 09 Mar 2015 Posts: 10
|
Running Low On RAM! |
Posted: Wed Mar 25, 2015 5:05 pm |
|
|
Hi,
i have been silent on here using this fantastic forum as reference for sometime now. Anyway i am new ish to pic c programming. i am having an issue with RAM running low and would appreciate some help. my application is a pic 18F4520 accepting commands via the serial port and then performing some routine based on the command received. the problem is i have just over 100 commands, this is how i have been handling it so far.
Code: |
void actioncmd(char cmd[20]){
char XXXXXXXXX[10] = "XXXXXXXXX"; //Define the string (100 lines of commands like this where XXXXXXXX is a different command)
clean_up_str(cmd); // this removes white space from cmd
IF (strcmp (cmd, XXXXXXXXX) == 0) // 100 more if statements similar to this where XXXXXXXXX is a different command
{
run_some_function();
}
}
|
i feel i don't need to put all the code here but basicly main is responsible for getting the cmd in via the serial port and passing to this function.
i understand i can't use a constant in the strcmd() which is why i have done it like this. but this method, when i have all 100 sections of code in place is using up 77% of RAM and i still have a few more functions to write. if i comment the above code out it falls right down to 13%.
so the big question is can i optimise this code in any way?
because i am unsure on how the code relates to RAM i wasn't sure what to search for on this forum to see if this sort of question has been asked before, so apologise if it has.
just in case if helps i am using 5.044
thanks in advance |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Wed Mar 25, 2015 5:35 pm |
|
|
have you read about
Code: |
CONST char XXXXXXXXX[10] = "XXXXXXXXX";
|
if the VARs in question are static in their content - this will place them in PROGRAM memory - of which you have quite a lot more
and use no static ram which is precious. |
|
![](templates/subSilver/images/spacer.gif) |
AArdvark
Joined: 09 Mar 2015 Posts: 10
|
|
Posted: Wed Mar 25, 2015 5:47 pm |
|
|
thanks for your reply, i tried this before thinking that's what it will do but it came up with errors all over the place.
i have just tried it again now and it seems to work i will test it out on the whole code and see what happens.
thanks again. |
|
![](templates/subSilver/images/spacer.gif) |
AArdvark
Joined: 09 Mar 2015 Posts: 10
|
|
Posted: Wed Mar 25, 2015 6:03 pm |
|
|
unfortunately that made no difference
i don't think its these taking up the memory. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Mar 25, 2015 7:40 pm |
|
|
You save RAM by putting your strings in flash memory with the 'const'
qualifier. You can pass a 'const' string to a function (without a compiler
error) if you add a #device statement. See the lines shown in bold below:
Quote: | #include <18F4520.h>
#device PASS_STRINGS=IN_RAM
#fuses INTRC_IO, BROWNOUT, PUT, NOWDT
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
#include <string.h>
void actioncmd(char cmd[20])
{
const char X_data[10] = "XXX";
if(strcmp (cmd, X_data) == 0)
{
printf("run_some_function \n\r");
}
else
{
printf("Invalid command \n\r");
}
}
//===================================
void main()
{
actioncmd("XXX");
while(TRUE);
} |
|
|
![](templates/subSilver/images/spacer.gif) |
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Thu Mar 26, 2015 3:05 am |
|
|
EDIT: PCM posted while I was writing, but here it is anyway:
Quote: | You save RAM by putting your strings in flash memory with the 'const'
qualifier. |
Hmm, not really. Its all about lifetime - i.e. how long variables have to exist in RAM. Const variables (and yes, in C that's how they are considered, as variables which are read-only - const is a qualifier) are like all varaibles, and in important respects are treated just the same as normal read-write varaibles. C doesn't have any mechanism for coping with actual read-only memories. Const wasn't in early Cs, it was added to the language later. Before that, #define was used to implement similar functionality. Const is a hint to compilers that the varaible is read-only and can be treated as appropriately as the underlying hardware allows. In most Cs I've encountered, that means that, just like "normal" variables, consts exist in RAM at all times, but is loaded at program start up from some outside storage. In systems without ROM, that means that consts are loaded from the program image on disc, or other backing store, in PICs, which don't have such storage, it means they are loaded from a value held as part of the program image in program memory.
All this means that consts, in a sense, take up twice as much room as normal variable and have two copies, one in program memory, one in RAM.
It would be possible to not have the RAM version. In other words const means "this is a special data thingy that never exosts in RAM, generate code that always gets it from program memory". That, though, means that any accesses to consts would be much slower and generate much longer code. Hence the treatment of consts with a RAM shadow - using a const is just the quick and code efficient as any other variable.
So, this means that consts use the same RAM as is they were normal initialised variables that you happen never to write to, which in C is what they conceptually are. Their RAM life time is for all the program scope.
How to reduce RAM usage? You need to reduce the effective scope of the data. One way of doing this is to explicitly store such stuff in program memory say with #rom, and then to read them into a some scratchpad in RAM when required. You manage this yourself. That way, you only need to have one scratchpad in RAM big enough to hold the longest constant, such as strings. I tend do this explicitly with strcpy() and other related routines. Here's a snippet from a command interpreter:
Code: |
// Compare_string is a scratchpad used to temporarily hold the string to compare with.
strcpy (compare_string, "*IDN?");
if(strncmp(single_cmd_array, compare_string, 5) == 0)
{
command_number = 71;
}
|
Another way of doing this is to use #device PASS_STRINGS=IN_RAM, which automates this process, i.e. the compiler does the same thing for you - it makes a temporary copy of a in RAM of a string literal, e.g. "This is a string literal", in program memory. That only works for strings however, and not, for example, with numerical menu tables.
A thing to remember is that the compiler cannot tell how long you need a varaible to exist and be accessible. The scope rules tell it some basic stuff - i.e. local variables in routines only exist while that rountine is running. So if you want to be clever about data lifetime, and save RAM by resuing RAM wher possible, generally you have to do it yourself.[/quote] |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Thu Mar 26, 2015 4:51 am |
|
|
From RF_Developer:
"All this means that consts, in a sense, take up twice as much room as normal variable and have two copies, one in program memory, one in RAM. "
Like all things, stuff is not simple.
In fact a _RAM_ variable that is declared as initialised, so:
char XXXXXXXXX[10] = "XXXXXXXXX"
Has two copies, one in the ROM (containing the values to initialise with), and one in RAM.
#device PASS_STRINGS=IN_RAM
Does _not_ create a complete RAM copy, it only uses a tiny RAM buffer, and passes the variable 'through' this buffer. So PCM_programmers comments are exactly right. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|