Pages: [1]   Go Down
Author Topic: How to tell where a variable is stored?  (Read 1075 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
God Member
*****
Karma: 17
Posts: 721
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Is there any test that can tell whether a pointer is pointing to a variable in SRAM or PROGMEM? 

Essentially what I want is a function that takes a pointer and if it is in regular ram then it just calls a regular print method but if it is pointing to progmem then it uses the appropriate macros to pull it out and then calls a print method. 
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 92
Posts: 4727
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Getting values out of PROGMEM (aka flash) is supposed to use special functions. Same as with EEPROM.
There should be no mystery.
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

0
Offline Offline
God Member
*****
Karma: 0
Posts: 594
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

you need to do research on data types and function overloading

but the problem is that data storage locations is not a part of the data type, it's a attribute, I'm not sure how you can do function overloading with attributes, hopefully somebody else can fill this part in.
Logged

Freelance engineer, consultant, contractor. Graduated from UW in 2013.

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Is there any test that can tell whether a pointer is pointing to a variable in SRAM or PROGMEM?  

It can't be done directly. A pointer (eg. to address 100) will just contain 100. You can't deduce from that which piece of memory to use.

Maybe you could make a class that takes an overloaded print method, but maybe not.

Why do you want to do this?
Logged

Offline Offline
God Member
*****
Karma: 17
Posts: 721
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nick,

That's exactly what I want to find out.  If I look at the value of the pointer without deference it first, then I just get a number that is the memory address for where the thing points to.  What I wondered if there's some way to tell where that address is.  Like for example address 0-63 is in RAM and 64-127 is in PROGMEM or something like that.  Then I could test and say, if the address is greater than 64 (the variable is in progmem) then do it with the PROGMEM macros way and if the address is less than 64 do it the other way. 

The thing I am trying to overcome is a function that has to print to the screen and sometimes prints canned stuff from PROGMEM and sometimes prints stuff that came from user input.  I would need two print functions and a way to tell which one I need to use. 
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 92
Posts: 4727
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

From what I see about using PROGMEM to store character arrays you must first copy the string from PROGMEM to SRAM before you can print it. Is that not true?
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Offline Offline
God Member
*****
Karma: 17
Posts: 721
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, that is EXACTLY true.  That's why I want to know, if I look at the address that the pointer is pointing to, is there any way to tell if that address is in PROGMEM or SRAM.  Because if it is in PROGMEM, then I need to call the function to copy it into SRAM.  If it is already in SRAM, then I shouldn't call such a function.

My program won't know until runtime whether it is dealing with a progmem string or with user input sitting in SRAM.  I can write code to try to keep up with it, but if there is a way to tell which set of memory an address is in that would be much simpler and sleeker. 


So the question is:

char* cptr = 'T';

uint_16t this_address = cptr;


Now, this_address contains the ADDRESS of where that T character is and not the T character itself.  Is there any way to tell whether that address is in SRAM or PROGMEM?  Of course I know in this example because I can see where I created the variable.  But my question is, can I tell from a variables address where it lives?  It would seem intuitively so.  Surely PROGMEM addresses are different from SRAM addresses right?  Or are they like houses in two different cities and they might have the same street address but with a different zip code.

Another way of asking the question is this.  Is there enough information in the address of a variable to tell which set of memory it is stored in?
Logged

Offline Offline
God Member
*****
Karma: 17
Posts: 721
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I should probably add that I'm only talking about an UNO with an atmega328 here.  I understand the addresses would be different on a different chip.
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 290
Posts: 25735
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

But you already know if a string is in PROGMEM or not, because you put it there.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

But my question is, can I tell from a variables address where it lives?  It would seem intuitively so.  Surely PROGMEM addresses are different from SRAM addresses right? 

No. They are two pieces of memory. Therefore there is an address 100 in each of them. It isn't the same piece broken into different bits, with different addresses.

If the following worked, you might have done it with function overloading:

Code:
#include <avr/pgmspace.h>

class foo
{
public:

  void print (char * bar);
  void print (prog_char * bar);
  
};  // end of foo

But it doesn't. It gives:

Code:
sketch_dec13a:7: error: 'void foo::print(prog_char*)' cannot be overloaded
sketch_dec13a:6: error: with 'void foo::print(char*)'

Program memory is an attribute, not a type. Therefore C++ doesn't let you overload on an attribute alone.

I think you need a different design. Storing the addresses of two different sorts of things in one place is asking for trouble.

However you *might* find in practice that SRAM addresses are lower than PROGMEM ones. Simply because you only have 2Kb of SRAM, and 32 Kb of PROGMEM. Now if the compiler happens to put PROGMEM strings into addresses above 2Kb then a simple address test could work (in other words, if they go above the code). But if the compiler puts them into PROGMEM first (and then follows them by the instruction code) then they both may end up in addresses which are in the range 0 to 2 Kb.

You might get away with a flag, eg. set the 0x8000 bit on SRAM addresses, and then check that in your function (and mask it out of course). The viability of that depends on how your code works, and why you are trying to mix the two sorts of addresses in the first place.
Logged

0
Offline Offline
God Member
*****
Karma: 0
Posts: 594
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

what if you define a new dedicated section and tell the linker to place that section somewhere fixed?

edit: I mean instead of .text, make a new attribute that says the location is withing .something, and place it somewhere such that it is guaranteed to have an address greater than SRAM
« Last Edit: December 12, 2011, 08:30:46 pm by frank26080115 » Logged

Freelance engineer, consultant, contractor. Graduated from UW in 2013.

Offline Offline
God Member
*****
Karma: 17
Posts: 721
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

But my question is, can I tell from a variables address where it lives?  It would seem intuitively so.  Surely PROGMEM addresses are different from SRAM addresses right? 

No. They are two pieces of memory. Therefore there is an address 100 in each of them. It isn't the same piece broken into different bits, with different addresses.

Thank-you Nick.  That is exactly the information I was looking for.  So it is like two houses with the same street address and the PROGMEM attribute is the "zip-code".  And since it is an attribute, I can't look at that zip-code in my code. 

The application I am thinking of is a large list tree with a few items being re-defined at run-time.  I guess I can store a flag that tells which ones have been edited and which ones have the default value and write two different functions to print them.  I was hoping for something sleeker, but I can't possibly store all the text in SRAM.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Search the SRAM list. If not found, search the PROGMEM list. You can't put flags on the PROGMEM part anyway, as you can't change it.
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 92
Posts: 4727
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You could possibly treat your PROGMEM stored data as the default and your buffers in SRAM as... buffers only. If you only want 1 buffer for printing then you could keep the pointer in PROGMEM where that was last copied from and then you could avoid copying data you already have but -- make it a NULL pointer if you change the buffer contents at all.

That way the only stored pointers you deal with for that purpose are in PROGMEM. With one or limited buffers you don't need pointers in SRAM as indexes at most should do.
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Offline Offline
Jr. Member
**
Karma: 0
Posts: 61
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Using PROGMEM is a design/compile-time decision, probably one you manually code by adding the PROGMEM qualifier to specific data items, hence I would avoid encumbering my code with run-time checks to find the various storage locations. I'd rather design a solution based on conditional compilation (#ifdef ... #endif) and/or corresponding macros.
Logged

Pages: [1]   Go Up
Jump to: