Posted by JohanEkdahl: Fri. May 5, 2017 - 06:30 PM
1
2
3
4
5
Total votes: 0
I made this table illustrating the complexity and lack of "one-to-one" mapping between PC and AVR memory types. I'm sure it does not cover everything, and might be wrong in details. See it as an illustration rather than an absolute truth..
Memory type Volatile Speed[1] PC AVR
R W
---------------------------------------------------------------------------------------------------------------------
RAM Yes F F * Program code when executing
* Data for programs while running * Data for programs while running
Hard disk No S S * Permanent program code storage * n/a [2]
(must be loaded into RAM to be
executed)
* Permanent data storage
(e.g. store data between executions
i.e. when program is not running)
Flash No F S * n/a [4] * Program code permanent storage, and
is executed from here
EEPROM No F S * n/a [5] * Low volume read and write data
(e.g. store data between executions
i.e. when AVR is not powered)
External No S S * As hard disk above * High(er) volume read and write data
Non-volatile (e.g. store data between executions
Memory [3] i.e. when AVR is not powered)
Possibly for needing moveable/detachable
memory, or just for high volumes
----------------------------------------------------------------------------------------------------------------------
[1] R - Read, W - Write, F - Fast, S - Slow
[2] While technically possible attaching a "classical" hard disk (SATA/ESATA)
to an AVR is complex and in most all cases a memory card is more fitting
and definitively easier to do
[3] Memory cards, USB sticks/drives
[4] I'm avoiding a somewhat complex discussion on PC BIOS storage by simply ignoring it and
saying n/a while it might not be true :-)
[5] It's possible (or even likely?) that BIOS Setup data is stored in EEPROM on a PC
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
Posted by jasonkelly214: Wed. Oct 27, 2021 - 07:29 PM
1
2
3
4
5
Total votes: 1
I have no shame in posting on old threads when they're tutorials.
Thanks for this; cleared up a lot for me. Clear, concise and very helpful.
I have an application I threw an ATMega2560 in because I needed high io count and a good chunk of memory for data acquisition of many sensors, and to write that data to an SDHC card. I didn't have a lot of time to spend researching MCU's but I'm hoping to go with a smaller chip once I'm done writing the program. This goes a long way in helping me reduce my memory footprint along the way. PTSD from university CS classes 10 years ago still has me often dragging my feet any time I need to do memory allocation (*cough* segfault *cough*) so all the little things I can do to save space first are very welcome ;)
Posted by jasonkelly214: Thu. Oct 28, 2021 - 01:59 AM(Reply to #206)
1
2
3
4
5
Total votes: 0
Yes! I learned this in the few hours after submitting my comment. Took a while to figure out what I needed to do but I landed on still using _p functions for in-line string literals. Looking through the rest now to see what else could be set as __flash. I tend to be a #define guy, but I’m looking for places where I’m potentially using those defines repeatedly and moving them instead to constants in flash. My degree is CE and as such I have good CS knowledge and embedded really is my favorite but I’ve only done this work sporadically the last 8 years since college. All that to say I’m geeking out a bit on increasing my code efficiency with these methods.
A couple questions I still have:
how would I know when I need to use __memx vs __flash? I understand that memx is for data that crosses the 64 Kb boundary, but am I going to know when that happens?
I was also running into trouble trying to debug a variable, I thought the issue was due to it being in flash, but ended up being because it only lived in a register. So I guess my question is, if it’s static and constant, shouldn’t the debugger still know it’s location in flash? Or is the answer “maybe yes maybe no, it depends”. Which I think is the case…when I scattered my variable around a bit more I was able to break and see it in my watch list.
Posted by gchapman: Thu. Oct 28, 2021 - 03:25 PM(Reply to #205)
1
2
3
4
5
Total votes: 0
Welcome!
jasonkelly214 wrote:
... ATMega2560 ... but I'm hoping to go with a smaller chip once I'm done writing the program.
The follow-on to megaAVR is AVR Dx (AVRxt, up to 128 KB program space, up to 16 KB data space, up to 64 pins); AVRxm also has an EBI (16 MB data space, up to 100 pins)
how would I know when I need to use __memx vs __flash? I understand that memx is for data that crosses the 64 Kb boundary, but am I going to know when that happens?
You need to police the boundaries thing yourself so try to avoid creating anything that straddles a 64K boundary. __memx is most useful when you want to. for example, create a common printing routine that doesn't care if text is in RAM or flash - you can just pass a __memx pointer to it then use a __builtin to determine where it's located.
jasonkelly214 wrote:
I was also running into trouble trying to debug a variable, I thought the issue was due to it being in flash, but ended up being because it only lived in a register.
See my article (also in Tutorial) about the use of "volatile" in GCC. That is the quick/easy way to make something easily "watchable" by debuggers (though it impacts the efficiency of the code). There should not be a problem with const __flash data though - the debugger should always know the location of that (and if not read it to a volatile and look at that!).
I made a flash card program from a long list of English two-three word expressions. I used this format:
const char PROGMEM englishStr0000[] = "a babe in arms"; // extends up to 5850 expression strings
const char * const englishStrItems[ 1 ] PROGMEM = {englishStr0000}; // extends up to 5850 array elements
String proverbString; // construct an object of class String in order to word-wrap on OLED screen
uint16_t stringIndex = random(5850);
proverbString = String(FPSTR( englishStrItems[stringIndex]));
The final code for 5850 expression strings was about 100 K bytes. It loads and runs in a 32-bit CPU through Arduino.
It was my impression that the __flash constants don't work with string functions such as strcpy and strcat (or, that there aren't versions of those that work with __flash). Is that still true?
I often construct strings for serial IO from constant strings and ASCIIfied variables.
Thanks
Jim
Until Black Lives Matter, we do not have "All Lives Matter"!
It was my impression that the __flash constants don't work with string functions such as strcpy and strcat
avr-libc manual says
There are many string functions available that work with strings located in Program Space. All of these special string functions have a suffix of _P in the function name, and are declared in the <avr/pgmspace.h> header file.
In Imagecraft C, the string functions that use strings in flash start with c, such as cstrcpy, or cstrcat... so may vary with compiler used.
Jim, exactly that. You just use _P() functions with __flash data in exactly the same way you would have done with PROGMEM.
just for my curiosity......
if they do exactly the same and you still need the <avr/progmem.h> to get to the special _P functions why use __Flash instead of PROGMEM al together?
or is this a thing with portability of the code to other platforms that in the future you no longer need the visible <avr/progmem.h> but after defining 'variables' to be '__flash char' during compile time the right function is called
If you are asking that you have completely missed the point of __flash. You no longer need to use any of the pgm_read_XXX() nonsense when you use it. You don't even need pgmspace.h unless you choose to use something from it.
If you are asking that you have completely missed the point of __flash..........
well that is then why I never understood the advantages of using __flash.......
Till now I always was under the impression that __flash only replaced the "progmem" part but that in the end you still needed to use the special _P functions to have access....
That will make life a lot easier indeed.
so if I have a:
const __flash char txt1[] = "Hello";
and a
volatile char txt2[10] = "world/r/n/0";
can I then acces them both using the same function like
void sendit(* char tosend)
{
UDR = tosend[1];
}
Or do you on that end still do need the separation between the two as the pointers are different?
note I always have been strugling with pointers and I have not been coding for a while now as my time has been consumed by other hobbies.
but that in the end you still needed to use the special _P functions to have access....
No again. The thing you no longer need is pgm_read_xxx(). If you are going to use something like printf() hten you DO still need to use printf_P(). Here is an example:
const __flash char fmt[] = "x = %d";
int x = 123;
int main(void) {
UDR = fmt[2]; // no pgm_read_byte() neeeded
printf_P(fmt, x); // but you do still need to use _P
// by the way you could do this but it's pointless
UDR = pgm_read_byte(&fmt[2]);
}
meslomp wrote:
can I then acces them both using the same function like
No that is when you would use __memx which is a pointer that can point to both RAm and flash. At the point of dereference the compiler needs to know whether to generate RAM accessing LD code or flash accessing LPM code. It does that in __memx using the state of bit 23.
I made this table illustrating the complexity and lack of "one-to-one" mapping between PC and AVR memory types. I'm sure it does not cover everything, and might be wrong in details. See it as an illustration rather than an absolute truth..
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopI managed to solve my problem gracefuly!:_
const char PROGMEM ErrorArray1[] = "testa";
const char PROGMEM ErrorArray2[] = "testaaa";
const char PROGMEM ErrorArray3[] = "test";
const char PROGMEM ErrorArray4[] = "test";
const char PROGMEM ErrorArray5[] = "testdddddd";
const char PROGMEM ErrorArray6[] = "test";
const char PROGMEM ErrorArray7[] = "test";
PGM_P const ErrorArray8[][3] PROGMEM = {{ErrorArray1,ErrorArray2},{ErrorArray3,ErrorArray4},{ErrorArray5,ErrorArray6,ErrorArray7}};
- Log in or register to post comments
TopAND a 3 multi array of pointers and the 4th array being char array
const char PROGMEM ErrorArray1[] = "testa";
const char PROGMEM ErrorArray2[] = "testaaa";
const char PROGMEM ErrorArray3[] = "test";
const char PROGMEM ErrorArray4[] = "test";
const char PROGMEM ErrorArray5[] = "testdddddd";
const char PROGMEM ErrorArray6[] = "test";
const char PROGMEM ErrorArray7[] = "test";
PGM_P const ErrorArray8[][2][3] PROGMEM = {{{ErrorArray1,ErrorArray2},{ErrorArray3,ErrorArray4}},{{ErrorArray5,ErrorArray6,ErrorArray7}}};
- Log in or register to post comments
TopI have no shame in posting on old threads when they're tutorials.
Thanks for this; cleared up a lot for me. Clear, concise and very helpful.
I have an application I threw an ATMega2560 in because I needed high io count and a good chunk of memory for data acquisition of many sensors, and to write that data to an SDHC card. I didn't have a lot of time to spend researching MCU's but I'm hoping to go with a smaller chip once I'm done writing the program. This goes a long way in helping me reduce my memory footprint along the way. PTSD from university CS classes 10 years ago still has me often dragging my feet any time I need to do memory allocation (*cough* segfault *cough*) so all the little things I can do to save space first are very welcome ;)
- Log in or register to post comments
TopJust to remind you that if you use C not C++ then __flash is a far better option than PROGMEM these days. If it's C++ you don't get a choice.
- Log in or register to post comments
TopYes! I learned this in the few hours after submitting my comment. Took a while to figure out what I needed to do but I landed on still using _p functions for in-line string literals. Looking through the rest now to see what else could be set as __flash. I tend to be a #define guy, but I’m looking for places where I’m potentially using those defines repeatedly and moving them instead to constants in flash. My degree is CE and as such I have good CS knowledge and embedded really is my favorite but I’ve only done this work sporadically the last 8 years since college. All that to say I’m geeking out a bit on increasing my code efficiency with these methods.
A couple questions I still have:
how would I know when I need to use __memx vs __flash? I understand that memx is for data that crosses the 64 Kb boundary, but am I going to know when that happens?
I was also running into trouble trying to debug a variable, I thought the issue was due to it being in flash, but ended up being because it only lived in a register. So I guess my question is, if it’s static and constant, shouldn’t the debugger still know it’s location in flash? Or is the answer “maybe yes maybe no, it depends”. Which I think is the case…when I scattered my variable around a bit more I was able to break and see it in my watch list.
- Log in or register to post comments
TopWelcome!
Migration from the megaAVR® to AVR® Dx Microcontroller Families
Device Tables | AVR® Instruction Set Manual
"Dare to be naïve." - Buckminster Fuller
- Log in or register to post comments
Top- Log in or register to post comments
TopHow to mix C and C++, C++ FAQ
"Dare to be naïve." - Buckminster Fuller
- Log in or register to post comments
TopI made a flash card program from a long list of English two-three word expressions. I used this format:
The final code for 5850 expression strings was about 100 K bytes. It loads and runs in a 32-bit CPU through Arduino.
This is a good tutorial.
- Log in or register to post comments
TopIt was my impression that the __flash constants don't work with string functions such as strcpy and strcat (or, that there aren't versions of those that work with __flash). Is that still true?
I often construct strings for serial IO from constant strings and ASCIIfied variables.
Thanks
Jim
Until Black Lives Matter, we do not have "All Lives Matter"!
- Log in or register to post comments
Topavr-libc manual says
There are many string functions available that work with strings located in Program Space. All of these special string functions have a suffix of _P in the function name, and are declared in the <avr/pgmspace.h> header file.
In Imagecraft C, the string functions that use strings in flash start with c, such as cstrcpy, or cstrcat... so may vary with compiler used.
FF = PI > S.E.T
- Log in or register to post comments
TopThen the question is: (in gcc) does strcat_P work properly with __flash values?
Thanks
Jim
Until Black Lives Matter, we do not have "All Lives Matter"!
- Log in or register to post comments
TopJim, exactly that. You just use _P() functions with __flash data in exactly the same way you would have done with PROGMEM.
- Log in or register to post comments
TopAhh, big help! In previous project, I stuck with PROGMEM attribute not knowing that __flash would work.
Appreciate that.
Jim
Until Black Lives Matter, we do not have "All Lives Matter"!
- Log in or register to post comments
Topjust for my curiosity......
if they do exactly the same and you still need the <avr/progmem.h> to get to the special _P functions why use __Flash instead of PROGMEM al together?
or is this a thing with portability of the code to other platforms that in the future you no longer need the visible <avr/progmem.h> but after defining 'variables' to be '__flash char' during compile time the right function is called
- Log in or register to post comments
TopIf you are asking that you have completely missed the point of __flash. You no longer need to use any of the pgm_read_XXX() nonsense when you use it. You don't even need pgmspace.h unless you choose to use something from it.
You literally can just write:
See what the PROGMEM / pgm_read_byte() version of that looks like!
- Log in or register to post comments
Topwell that is then why I never understood the advantages of using __flash.......
Till now I always was under the impression that __flash only replaced the "progmem" part but that in the end you still needed to use the special _P functions to have access....
That will make life a lot easier indeed.
so if I have a:
const __flash char txt1[] = "Hello";
and a
volatile char txt2[10] = "world/r/n/0";
can I then acces them both using the same function like
void sendit(* char tosend)
{
UDR = tosend[1];
}
Or do you on that end still do need the separation between the two as the pointers are different?
note I always have been strugling with pointers and I have not been coding for a while now as my time has been consumed by other hobbies.
- Log in or register to post comments
Top- Log in or register to post comments
TopPages