The PROGMEM attribute is always a source of confusion for those beginning with AVR-GCC. The PROGMEM attribute is a powerful one and holds the potential to save a lot of RAM, which is something of a limited commodity on many AVRs. Before you can use the PROGMEM attribute, you must first understand what it does and why it is useful.

When strings are used in a program, they are commonly "hard-coded" into the firmware source code:

LCD_puts("Hardcoded String");

While this seems the most logical way of using strings, it is *not* the most optimal. Common sense and intuition would dictate that the compiler would store the string in the program memory, and read it out byte-by-byte inside the LCD_puts routine. But this is not what happens.

Because the LCD_puts routine (or other string routines) are designed to work with strings in RAM, the compiler is forced to read out the entire string constant from program memory into RAM, and then pass the string's RAM pointer to the routine (in this case LCD_puts). It certainly works but the RAM wastage adds up to significant amounts with each string. Why?

Initial variable values and strings are copied out from program memory into RAM as part of the C startup routines, which execute before your main() function. Those startup routines give your globals their initial values, as well as ensure that all strings are inside RAM so they can be passed to your desired string handling routines. As more strings are added to your program, more data must be copied to RAM at startup and the more RAM is used up by holding static (unchanging) data.

The solution to the problem is forcing strings to stay in program memory and only be read out as they are needed. This is not a simple task and requires string routines specifically designed to handle strings kept solely inside the program memory space.

Using the "const" modifier on your string variables is a natural solution - but a wrong one. A "const" variable can only not be modified by the program code, but it does not explicitly prevent the variable value from being copied out to the AVRs RAM on startup. Some compilers implicitly do this for you, but GCC needs to be explicitly told that the contents must live in program memory for the entire duration of the program's execution.

Entering pgmspace.h

The AVR-LibC library contains a header file, avr/pgmspace.h, which contains all the interfacing information needed to allow you to specify data which is to be kept inside the AVR's flash memory. To use the pgmspace.h functions, you need to include the header at the start of your C file(s):

#include

To force a string into program memory, we can now use the "PROGMEM" attribute modifier on our string constants. An example of a global string which is stored into program memory and not copied out at execution time is:

char FlashString[] PROGMEM = "This is a string held completely in flash memory.";

Although it is not an absolute requirement, we can remind ourselves - and possibly prevent bugs further down the track - that the string cannot be changed at all during execution by declaring it as a constant:

Now that the PROGMEM string has a "const" modifier, we cannot try to modify it in our code. The pgmspace.h header also exposes a neat little macro, PSTR, which by some GCC magic allows you to create inline strings:

LCD_puts(PSTR("Program Memory String"));

This stops you from having to clutter your program up with hundreds of variables which hold one-time-used strings. The downside to using the PSTR macro rather than a PROGMEM modified string variable is that you can only use the PSTR string once.

However, we now have a problem - now all your code doesn't work! What's wrong?

The problem is that your string functions are expecting the string to be inside RAM. When you pass a string to a routine, you are in fact just passing a pointer to the start of the string in RAM. The string handling routine then just loads the bytes of the string one-by-one, starting from the pointer's location. But our PROGMEM strings are not in RAM, so the pointer to them is invalid.

A pointer to a string stored in PROGMEM returns the address in flash memory at which the string is stored. It's still a valid pointer, it's just pointing to a different memory space. To use PROGMEM strings in our application, we need to make our string routines PROGMEM-pointer aware.

Again, pgmspace.h comes to our rescue. It contains several functions and macros which deal with PROGMEM-based strings. First, you have all your standard string routines (memcpy, strcmp, etc.) with a "_P" postfix denoting that the function deals with the FLASH memory space. For example, to compare a RAM-based string with a PROGMEM-based string, you would use the strcmp_P function:

strcmp_P("RAM STRING", PSTR("FLASH STRING"));

For a full list of the avaliable string functions, check out the AVRLibC documentation which is installed with your WinAVR installation.

But what if you have your own string function, like a USART-transmitting routine? Lets look at a typical example:

This relies on the routine USART_Tx, which for the purposes of this example we will assume to be predefined as a function which transmits a single passed character through the AVR's USART. Now, how do we change our routine to use a PROGMEM string?

pgmspace.h exposes a macro which is important for PROGMEM-aware routines; pgm_read_byte. This macro takes a PROGMEM pointer as its argument, and returns the byte located at that pointer value. To mark that our new routine deals in PROGMEM strings, let's append a "_P" to it's name just like the other routines in pgmspace.h:

This should give you a basic idea of how to store strings and keep them in flash memory space. What follows is the second half of this tutorial, for more advanced uses of the PROGMEM attribute.

PART II - More advanced uses of PROGMEM

Ok, so by now you should be able to create and use your own simple strings stored in program memory. But that's not the end of the PROGMEM road - there's still plenty more to learn! In this second tutorial section, I'll cover two slightly more advanced techniques using the PROGMEM attribute. The first part will lead on to the second, so please read both.

Storing data arrays in program memory

It's important to realize that all static data in your program can be kept in program memory without being read out into RAM. While strings are by far the most common reason for using the PROGMEM attribute, you can also store arrays too.

This is especially the case when you are dealing with font arrays for a LCD, or the like. Consider the following (trimmed) code for an AVRButterfly LCD font table:

Because we've added the PROGMEM attribute, the table is now stored firmly in flash memory. The overall savings for a table this size is negligible, but in a practical application the data to be stored may be many times the size shown here - and without the PROGMEM attribute, all that will be copied into RAM.

First thing to notice here is that the table data is of the type unsigned int. This means that our data is two bytes long (for the AVR), and so out prgm_read_byte macro won't suffice for this instance.

Thankfully, another macro exists; pgm_read_word. A word for the AVR is two bytes long - the same size as an int. Because of this fact, we can now make use of it to read out our table data. If we wanted to grab the fifth element of the array, the following extract would complete this purpose:

pgm_read_word(&LCD_SegTable[4])

Note that we are taking the address of the fourth element of LCD_SegTable, which is an address in flash and not RAM due to the table having the PROGMEM attribute.

PROGMEM Pointers

It's hard to remember that there is a layer of abstraction between flash memory access - unlike RAM variables we can't just reference the contents at will without macros to manage the separate memory space - macros such as prgm_read_byte. But when it all really starts confusing is when you have to deal with pointers to PROGMEM strings which are also held in PROGMEM.

Why could this possibly be useful you ask? Well, i'll start as usual with a short example.

Here we have three strings containing menu function names. We also have an array which points to each of these three items. Let's use our pretend function USART_TxString from part I of this tutorial. Say we want to print out the menu item corresponding with a number the user presses, which we'll assume is returned by an imaginary function named USART_GetNum. Our (pseudo)code might look like this:

Those confident with the basics of C will see no problems with this - it's all non-PROGMEM data and so it all can be interacted with in the manner of which we are accustomed. But what happens if the menu item strings are placed in PROGMEM?

Easy! We add the PROGMEM attribute to our strings and then substitute the RAM-aware USART_TxString routine with the PROGMEM-aware one we delt with in part I, USART_TxString_P. I've also added in the "const" modifier as explained in part I, since it's good practice. But what if we want to save a final part of RAM and store our pointer table in PROGMEM also? This is where it gets slightly more complicated.

Let's try to modify our program to put the pointer array into PROGMEM and see if it works.

Hmm, no luck. The reason is simple - although the pointer table contains valid pointers to strings in PROGMEM, now that it is also in PROGMEM we need to read it via the prgm_read_x macros.

First, it's important to know how pointers in GCC are stored.

Pointers in GCC are usually two bytes long - 16 bits. A 16-bit pointer is the smallest sized integer capable of holding the address of any byte within 64kb of memory. Because of this, our "uint8_t*" typed pointer table's elements are all 16-bits long. The data the pointer is addressing is an unsigned character of 8 bits, but the pointer itself is 16 bits wide.

Ok, so now we know our pointer size. How can we read our 16-bit pointer out of PROGMEM? With the pgm_read_word macro of course!

Almost there! GCC will probably give you warnings with code like this, but will most likely generate the correct code. The problem is the typecast; pgm_read_word is returning a word-sized value while USART_TxString_P is expecting (if you look back at the parameters for the function in part I) a "char" pointer. While the sizes of the two data types are the same (remember, the pointer is 16-bits!) to the compiler it looks like we are trying to do the code equivalent of shoving a square peg in a round hole.

To instruct the compiler that we really do want to use that 16-bit return value of pgm_read_word as a pointer to a const char in flash memory, we need to typecast it to a pointer in the form of char*. Our final program will now look like this:

I recommend looking through the AVR-lib-c documentation (included with the installation of WinAVR in the \docs directory) in the AVR/PgmSpace.h header documentation section for information about the other PROGMEM related library functions avaliable. Other functions (such as pgm_read_dword(), which reads four bytes (double that of a word for the AVR architecture) behave in a similar manner to the functions detailed in this tutorial and might be of use for your end-application.

And so ends the second part of this tutorial. Feedback and corrections welcome!

This is a very useful technique since it's easy to write code in which the stack bounces off the variables - and the real gotcha is that all those 'printf' statements you put in to try and trace it make it worse; they're eating the ram space. Indeed, my Coupe ECU monitor had to have a complete rewrite to cope with a change of language from English to Italian; the Italian was a couple of dozen characters longer and that was enough to break it.

There are pro's and cons for each approach.
The major drawback of the two-dimensional array versus the table-of-pointers-to-strings, is that the "inner" dimension of the array has to be large enough to accommodate the largest individual string, even if none of the other strings need that much space. In the table-of-pointers approach, each individual string only reserves exactly enough memory to accommodate itself.

The major drawback of the table-of-pointers approach is two-fold: First, you have these extra two bytes associated with each and every string, where the pointers physically reside. The two-dimensional array approach doesn't have to literally store these pointers.

Second, you have to dereference PROGMEM twice in order to access the contents of an individual string: Once to extract the start-address of the string you want from the "top-level" table, and a second time to get at the individual character you're interested in within the target string. With a two-dimensional table, the compiler can compute the starting-addresses for the indiviudal strings deterministically, so you only need to dereference PROGMEM once, at the point where you're actually extracting an individual character from the strings.

The trade-off in storage requirement can be decided rather easily: If most of the individual strings that you want to place in the table are within one or two characters in length, your best bet is to use the two-dimensional table. In that case, the wasted space involved in padding the ends of the shorter strings will be smaller than the space that would be wasted by adding an extra two bytes for pointers to each-and-every string in a look-up table.

If you have a string set where there is a wide discrepancy between the longest and shortest strings, and most strings would have more than one or two bytes of NULL padding at the end to match the length of the longest string, then you'd be better off using the table-of-pointers approach.

People might not want to fill this up with lots of "thanks" posts, but I want Dean and all those that helped to know that the time and attention that went into this are VERY MUCH APPRECIATED!! Stuff like this is great and exactly what I needed!

I recently dealt with the same error as rotamat brought up with USART_TxString_P(). pgm_read_byte() takes a pointer, which is pointed out in your explanation (that's how I figured it out). Dereferencing a pointer as a parameter to this function will give you some very funny output. :)

Might be worth updating this to save some people who don't understand pointers well some trouble, I didn't bother reading the unofficial errata in the rest of the thread. I saw a .pdf there so I instantly trusted it... bad habit.

I just looked it over again and can't spot the error you speak of - was it due to the PDF being out-dated compared to the thread? I just updated the PDF with the latest content so any errors in it that were corrected in my post should be fixed.

Cheers,
- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

A fan-blody-tastic tutorial. *cheers*
Three things come to mind.
1. In the pdf there is an intendation issue on page 3
2. You say nothing about the cost in instructions to get a byte/word from progmem contra ram. Im gessing it's a 5:1 ratio or something.
3. Could be nice to know what the pgm_read_byte actualy does.

1) Fixed the indentation issue - I assume you were referring to the code with the while loop body non-indented?

2) I should probably add in a footnote. Cost varies depending on the data's flash location and AVR architecture, but yes it's about 5:1 per constant. You're trading a small amount of execution time and flash space for a a (usually) large amount of precious RAM space.

3) Again, depends on the data location and AVR chosen. You can check out the code inside the pgmspace.h header, if you're so inclined. Basically it just loads the data's flash address into the high pointer register pairs (I think the Z pointer, r30/31, is required) then executes a series of LPM instructions. Each LPM loads one byte of flash data, and with the post-pointer-increment feature data of several bytes like a word just has several of these instructions in series.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

1. Yes, no worries.
2. Agreed, mostly it's an intresting question when doing somthing verry timeing critical.
3. Will do. Remember "Magic is just a technology that we have yet to understand" and I don't like too much magic in my code. ;)

Yes arrays are passed by reference but you aren't passing an array, you are passing one elemental element of that array. If on the other hand you tried-

tempChar0 = pgm_read_byte(font[cTemp]);

you'd find it worked, since you are passing the 5 element array (it's still an element in the larger array but it is an array itself).
Of course you could only do that to get the first byte of each character so not that usefull..

Thanks Alf, I fixed up the one incorrect reference to strings I could find, and added in a footnote about looking at the other avaliable functions. I didn't want to derail the paragraph about pgm_read_word with information about pgm_read_dword as the former was discussing reading out pointers from program space (hard enough as it is) so I went for the footnote.

Cheers!
- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

First, thanks for the tutorial. It was helpful in understanding how things are supposed to be done.

Second... YUCK! Trying to define any data structure more complicated than a string or an array of simple data types reminds me of Fortran programs trying to implement 'data structures' with shared common areas and such. Does C++ permit operator overloading enough (ie including pointer dereference/etc) that one could use some C++ magic code to make the use of PROGMEM space invisible to the users?

Many thanks for this great tutorial, that helped me to optimize my code and understand better how to use flash to store data. I have one question though: is there a size limit in using flash to store static data ?
While I was switching/improving my strings to flash, it then suddenly did strange things (printing a long list of unreadable cars, as if the string wasn't terminated properly...). I had to go back to RAM for some parts of code.
Is there something I'm not considering ? Maybe a mistake somewhere else, but I don't see it right now.

1) The hard limit of the amount of FLASH memory in the AVR - this is a physical limit
2) The 64KB limit due to GCC using 16-bit pointers - this can be worked around using special "far pointer" functions and macros

Your code is only 23KB long, so you're hitting neither. Does your code have any large RAM arrays which might be stepping on the stack or string if you're copying it into RAM before use?

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

Well, I don't copy anything myself to RAM. I just use large structure to store all states/transitions of the state machine driving the AVR. Something to do with mapping and 64k limit ? On the 64K limit, could you explain further the far pointer trick (is it in a tutorial I would have missed ?) ?

The avr-libc pgmspace.h module contains "far" versions of the existing methods - "pgm_read_byte_far()", for example. To use them on a string located over the 64KB barrier, you'd just OR the string's address (typecast as a long) with 0x10000 to create a psudo-pointer.

Which has the distinct advantage that it returns the correct address (albeit a long address) for any FLASH data whether it is over the 64KB boundary or not -- coupled with the far accessor routines and you have bulletproof code.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

If you want an array of structures, use the PROGMEM on the array instead.

To access the structure elements you can either read out the structs from FLASH into a RAM structure using pgm_read_block (and then use the RAM strucuture as you would normally), or use the pgm_read_* macros on the structure elements individually as you use them.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

Rule of thumb: when in doubt, add more PROGMEM. I think you'd end up with a PROGMEM array of structures, since you've got an actual array of structures, rather than an array of pointers to the structures (which *would* result in a SRAM array of pointers to PROGMEM space).

You cannot change the PROGMEM data at runtime (since it is embedded in the FLASH), but you can initialize it via standard C methods:

Now I have this. I have different mystructX foe different menu sizes (so different menupoints values)

I'm building my menu on lcd by copying the myarrayX[language] to LCD buffer using strcpy_P.
This works fine, but now I have for every menu one function where this is done.
What I want to do is to have only one function and give the myarrayX as a parameter to the function. I think I have to realize this using a pointer, because the myarrayX are all different in size as I mentioned before.

I think I can give a pinter to myarrayX to the function and give the size (menupoints) also to it.
But I couldn't figure out how to do this. So, if someone has an idea about that, please share it with me.

Then when you display(HELLO_ID, language) where language is 0=French, 1=English, 2=Spanish. You just first point to the right sting using "HELLO_ID" and then skip 'language' number of '$'s along the string to find the start point to display and then continue displaying characters until NUL or another '$' is encountered. Use something other than '$' if there's a chance it ever needs to be displayed.

In the code you present above, otherwise, you are wasting huge amounts of bytes for ' 's

I would do it a little differently in this case. (there are many ways to accomplish your goal) Since size is also of concern, I would create individual strings for each phrase in each language, then create an array of pointers (for each language) to the appropriate phrases. And finally create an array of pointers to each of the language arrays. Any other menu data is kept in its own array of structures. To select the current language to display a variable is loaded with the address of the desired language array. This pointer can be global, and then accessed by any display routines, or passed as an additional parameter to them.

It may seem tedious, and it is to do by hand. However it can easily be managed with a small generator app that takes text files and generates the necessary data tables. This allows you to edit the resource strings for each language easily.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

Since size is also of concern, I would create individual strings for each phrase in each language,

I don't get it glitch, your way to do it is very clean but it does take more space than what clawson has above. You need N_LANGAUGES * 2 + (N_LANGAUGES - 1) * N_STRINGS * 2 bytes extra for all the pointer arrays.
/Lars

Yes Cliffs solution is, slightly, more dense than mine, but it requires more processing time, as you have to search the string for the correct entry.

My comment about size is aimed at the 2 dimensional array approach shown earlier. In which case it only takes more space if all the strings are close to the same length. As long as the average length of a string is more than 2 shorter than the longest string, you will be saving space with my method. (you still may if it is not, but it is not guaranteed)

Note that some of that overhead you show is required for Cliffs solution as well. The solution "as proposed" does not work in progmem.

char * strings[] = {
"Salut$Hello$Hola",
"Aurevoir$Bye$Adios"
etc.
}

The above needs to be either stored as a 2 dimensional array (lots of wasted space, if the amalgamated strings differ in length greatly), or as an array of pointers (same as my method). Thus my method only adds one more level of pointers to the mix. The trade off here is a few hundred bytes, vs execution speed.

The parameters to pgm_read_byte()/pgm_read_word() don't need to be a variable name - it can just as easily be an absolute address. All you are doing here is calling a function that wraps an LPM instruction.

I was following this tutorial so I could create a COS table, as the COS function from math.h is taking up too much cpu time. But my program fails at runtime, even though it compiles, if I add in this statement:

Ya I'm on linux here, and unfortunately my windoze partition is completely borked. We have simulavr, but I have not had the most luck with it previously, maybe it's time I did some research on that end. By fail, I mean that when I upload it into the AVR I get continuous resets like I'm blowing the stack, which is the reason why I moved this array out to progmem in the first place (only 512 bytes of ram on the atmega168 so I could put the entire array in ram, but 256 16-bit values would be the entire RAM and I'm pretty sure that would not work in any instance I can think of ;). Before trying progmem I was using signed 8-bit values in half my eeprom and accessing like this:

myphase = EEPROM_read(ICR1L);

But after reading up on EEPROM corruption, and the very fact I have so much more progmem space, I'd like to be using progmem instead.

So far as static, I think you're right, so I'm going to switch out static for const (which still gives me continuous resets after I changed it out).

I will definitely get after simulavr in the morning and find out if the data is at least pulling out.

and get the warning that indeed shows what is happening:
"
../blink.c:27: warning: only initialized variables can be placed into program memory area
"
What the...?
This disagrees with all the theory I've ever read about it.
Now with all my C++ code big and fat, I have problems squeezing strings to PROGMEM desite few days of trials..
???
Compilation:

I will find the solution since we do not negotiate with terrorists. Still, the output from PROGMEM version is garbage. At least the compiler digested it.
----------OK now the solution for C++:
changing

----
at the end, the only thing that is really missing, is sprintf_P that would take format string directly from PROGMEM area.
-----
here is the BUG:http://www.mail-archive.com/gcc-...
it is not fixed even in the most recent
WinAVR-20081124rc3

I would like to verify that printf_P only changes the format argument to reside in program flash. And that if the format has %s, the following string pointer passed will be in RAM, and not program flash. The doxygen comments in the header seem to say only fmt is in program flash for print_P.

I would also like to ask about the var args functions vsnprintf_P/vsprintf_P, i assume since there is only one va_start() in the avr stdarg.h, that it doesnt care that its used with a program memory pointer or ram.

Correct - the only difference between printf and printf_P is that the format string of the second is stored in FLASH rather than ram. In the format string, you can use %s to denote a SRAM string argument, and %S to denote a FLASH string.

The va_args macros deal with parameters pass on the stack, which are pointers to data or (for the basic primatives) the data themselves. The variable arguments are stored in the SRAM stack, but the pointers may point to SRAM or FLASH memory -- the differentiation is how you use the pointer, not the pointer itself.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

If you press '0' what arrives at the AVR is not 0x00 but the ASCII code for character '0' which is 0x30. So it'll then try to read the 0x30th (48th) entry in your MenuItemPointers array (which doesn't exist). Try:

That's the thing about UART - if you are just using it as a terminal (rather than sending/receiving files with binary content) that everything going out of the AVR probably needs to be converted from binary to ASCII (printf, itoa, etc.) and everything coming into the AVR probably needs to be converted from ASCII into binary (atoi, scanf, etc.)

this is not the only way to handle this code, but it fits well in my project structure. I've got several of those arrays (12-15) and I have to pass 3 of them (selected by a comand) to some functions...
thanks again,
cheers!
bo.

First of all this is a great tutorial. Thanks.
I am a little bit confused though. I am having a project in which I intend to use a menu to interface the uC.
Should I use progmem or eemem. Which one is better for LCD, menu
and a Keyboard?

AVRs by in large don't have much eemem, so unless you needs are small, there is probably not enough room in eemem. If you do fit in eemem, then it is up to you which you use, but I think that most would choose progmem. Reading from eemem takes longer than reading from progmem.

Thanks so much for this tutorial. It explains stuff that other authors miss.
May I suggest that you emphasize that PROGMEM assignments MUST be global. It took me quite a while to figure out the warning (which I think should be an error as it breaks all use of the constant)
Thanks
Kirk

So I followed this tutorial to put some strings into Program memory and then read them with pgm_read_byte(). While the string is reads correctly (when optimization is not at -Os) I can't explain what I see in the debugger!

The .lss file shows that the string is put in program memory right after the interrupt vector table, at address 0x7c. When I single step with the disassembler I can see that the LPM instruction via the Z pointer reads from address 0x7c.

HOWEVER when I bring up a memory window or scroll the disassembler to 0x7c there is no string. Instead I find the string at address 0x38, apparently right in the middle of the vector table, and I find that address 0x7c is inhabited by code. When I add a break point at 0x00007b the debugger stops there, so I'm clearly executing from there.
javascript:emoticon(':twisted:')
What is going on? Why does it appear that my string in memory is not where the .lss file says it should be and why am I executing code where a strings should be. What magic is this ?

You are mixing up byte and word addresses. The simulator/disassembler presents you everything related to the flash with word addresses, the GNU tools use byte addresses. So 0x7c in the .lss file is 0x3e in the simulator/disassembler.

What about trying to store data in the bootloader section using PROGMEM? Is there a way to change PROGMEM's start location. I can recall strings and variables just fine from FLASH at 0x00000, but not from the bootloader section.

What about trying to store data in the bootloader section using PROGMEM? Is there a way to change PROGMEM's start location. I can recall strings and variables just fine from FLASH at 0x00000, but not from the bootloader section.

If you write a bootloader then you move the whole Flash stuff by relocating the .text section. This also moves the PROGMEM section. So what is you actual problem?

Or don't you write a bootloader but only want to place some data in the bootloader section (whyever)? Then simply don't use the PROGMEM section. Use your own section and place it there.

I have a Atxmega128a1 and the boot section starts at 0x020000.
I know that it doesn't work past 64k but my boot section is only 8k, so if I move the .text section to the boot section address I shouldn't have any problems right?

I have a Atxmega128a1 and the boot section starts at 0x020000.
I know that it doesn't work past 64k but my boot section is only 8k, so if I move the .text section to the boot section address I shouldn't have any problems right?

So you don't think that 0x020000 is beyond 0x010000 (64k)?

BTW: I am not familiar with the XMegas. Has an Atxmega128 more than 128k Flash? If not, how then can the boot section start at 0x020000?
EDIT: Forget this. Meanwhile I took a look into the data sheet. ;-)

About the eemem question above (in case your still following the thread) - That portion of memory can tolerate 100000 writes as opposed to 10000 in flash, so ultimately flash seems to me best for constant strings or at strings that rarely change.

Hello, first of all, thanks for the tutorial!
I didn't read the whole thread but did do some quick search in it.
I was wondering if there was an easy way to directly load a resource file into a program memory destination.

for instance, I have the file res.txt with 800 bytes in it. I would like to copy its contents into program memory at address 0x1000, is there any special instructions in avr studio / avr-gcc to do so?

I have a quick question, if anyone here can help. I have a program where I have a large configuration struct that houses several different data types. Right now, I have two copies of this struct in EEPROM, which correspond to different configurations. I would like store defaults for each configuration in program memory, so a function like pgm_read_block (analogous to the eeprom_read_block I already use) would be very handy. I saw it mentioned earlier in the thread, but can't find it in pgmspace.h included with WinAVR-20100110. Is it an extension that I could find elsewhere, or will I have to write it myself?

Looks pretty good to me - obviously the array of pointers itself has to be in RAM not PROGMEM if you plan to change language at run time. But you could keep the initialisers for each language themselves in PROGMEM and do something like a memcpy_P() to copy an entire set of language pointers into place in one go.

I am using avr-gcc 4.3.5 to compile a cpp sourcecode (inherited from my Arduino environment). The example in the HOWTO leaves me with mismatching typeconversion errors or section type conflicts when I use "const".

Questions:
1. Can we change the flash contents by changing the content of the variable using PROGMEM?
2. If question 1 is Yes, then correct me if I'm wrong, the flash sector has to be erased, then store data to it. So how does it work?

Please help!
I have a Atmega M1284P. Data changeable by user and it's used to store in EEPROM, but now decide to store in flash. Here is my Flash memory organize:
App Region: 0 - 0xFFFF
Data Region: 0x10000 to 0x1DFFF
Boot Region: 0x1E000 to 0x1FFFF
I provide 2 commands to user READ_Data and WRITE_Data with 3 parameters: U16_t ui16Address, U16_t ui16Len, U8_t * pui8Buffer
The READ_Data function has no problem, I can use pgm_read_byte_far( 0x10000 + ui16Addr) where ui16Addr is from 0 to 0xDFFF (used to be the EEPROM address).
For the WRITE_Data function, should I assign Data Region Address of the Flash to be 0x1000 to a PROMEM variable? How can I do it?
When initialize, the data is used to read to RAM data structure variables. To save RAM memory, so now I benefit to use Flash instead.

Is there my any chance some sort of "test suite" for the pgmspace.h functions and definitions? I'm working on a compatibility shim for non-AVR processors and prospect of testing everything is daunting...

Thank you Clawson,
SPM doesn't support or disabled in Application Section, it works only in Bootloader Section. So there is NO WAY to change data in the flash when an app is running, user has to jump to BL mode to write data, then jump back to an app section. How do I read the program counter (PC) to save to EEPROM, so I could jump back to the application?

SPM doesn't support or disabled in Application Section, it works only in Bootloader Section. So there is NO WAY to change data in the flash when an app is running, user has to jump to BL mode to write data, then jump back to an app section. How do I read the program counter (PC) to save to EEPROM, so I could jump back to the application?

It's easy to write code that updates the flash at run time. As you say it just needs to use SPM and it has to be located in the bootloader section which is why has the BOOTLOADER_SECTION macro. But this is not the correct thread to be discussing this.

NOTE:
This thread is ONLY for discussing the original article about PROGMEM so I'm going to lock this thread now. If anyone has anything to add to correct/improve the original article then PM js, plons or clawson and ask one of us to temporarily unlock this thread to add your contribution.

pgm_read_byte needs an address to an array element, not the array element itself.

Thanks, John and Larry. In the end it was kinda obvious ;-)

The two questions in the last part of my recent posting will be concerned elsewhere, right? It rather has to do with the handling and displaying of FLASH locations within AVR STUDIO, not with the PROGMEM attribute itself.

Whats the correct approach here? I tried every combination of const and PROGMEM attributes but always get this error.

For clarification: I could of course use the first mentioned alternative, but i want to create the pointer tables with a preprocessor macro, because there are a lot of them and it would make implementations of new languages easier.

If there really was some reason you needed something at 0x1F00 then you can do:

const uint8_t foo = 5 __attribute__((section(".myvar")));

then pass this to the linker:

-Wl,-section-start=.myvar=0x1F00

and finally:

var = pgm_read_byte((uint8_t *)0x1F00);

But like Alex says, why would you do this? Why not use PROGMEM properly as explained in the original article of this thread? If you do start specifying absolute addresses like 0x1F00 you may conflict with what the linker tries to do automatically - how do you know it wasn't already planning to place code or flash data at that location?

I wish that the customer can easily find some constants before program firmware with isp

But ISP doesn't allow subsections of the flash to be changed/replaced?!? I'd go with Alex's idea of keeping config value in EEPROM which the customer *can* program separately.

Quote:

I saw that the compiler always puts constant from address 0x26 (ATmega8), then fine by me,

It's not the compiler that did that, it's the linker. This is because the linker is given a "linker script" that tells it how to lay things out in flash. That file is ..\AVRToolchain\avr\lib\ldscripts\avr4.x which contains:

This says that anything in a section called .vectors will be placed at the very start of flash - that includes the reset jump and the interrupt vector table - this is then followed by anything in .progmem* sections which means anything where you use PROGMEM which is similar to __attribute__((section(".progmem")). The reset+vectors on a mega8 are clearly 0x26 bytes long.

The PROGMEM attribute in the .h file means nothing to gcc, the symbol is just a hex offset from the start of a particular linker section and the code that refers to it still has to use the method appropriate to the hardware location of that section. Some compilers may do that automatically, but not gcc. For easier maintenance you can define both the attribute and the appropriate programmic references in the .h file and include that in all the c files.

This typedef is now deprecated because the usage of the __progmem__ attribute on a type is not supported in GCC. However, the use of the __progmem__ attribute on a variable declaration is supported, and this is now the recommended usage.

The typedef is only visible if the macro __PROG_TYPES_COMPAT__ has been defined before including (either by a #define directive, or by a -D compiler option.)

No one should EVER edit any library/system header file that belongs to the compiler or the C library. Just consider what happens next week when you upgrade the compiler and everything, including your edits, are replaced.

The fix for your "problem" here is to replace prog_char as you have been told. It was never a valid definition anyway as it applied an attribute (progmem) to a typedef. The correct way is exactly what that text from the user manual I quoted above says. Instead of:

#include
prog_char foo = 'A';

use:

#include
const char PROGMEM foo = 'A';

though this is now 2014 and a much better idea is:

const __flash foo = 'A';

With a __flash variable there's no longer a need to use pgm_read_byte() (or even include pgmspace.h). You can just say:

PORTB = foo;

and the compiler knows that foo was defined in __flash so will do the equivalent of a pgm_read_byte(&foo) anyway when it reads the 'A' character.

For this example, please forget about casts and stylistic questions. What causes me headaches is the question, whether I may do this or not. In my actual code this works. But perhaps I'm just lucky.

So my question is:

- can it happen, that the members within this (or any other) struct have different aligments if they reside in different storage-types??

I mean: is it possible, that intermixed datatypes in structs (8 bit, function(i.e. callback)-pointers, 32 bit values and so on) cause different memory-alignemnts within a struct of the same type, depending on the location where they originate from?

AND: Does this differ between different atmega-processors?

Or can I carelessly copy from

PROGMEM to RAM ||
EEPROM to RAM (with an extra EEPROM-version of course)

I would say it is a fantastic tutorial for the beginners. You are doing a good job. Helps me a lot to understand the basic concepts. I wish you to create much more tutorials on AVR GCC macros with relative examples as in this tutorial. You can also try to go little advance once you establish the basic concepts.

I wouldn't hold your breath. Dean has a real job working on things a bit more advanced than the humble AVR, so i don't think you see much from him.
Note this tutorial is *only* ten years old - there's the _flash attribute now. Time for some reading methinks.

But if you are sticking with PROGMEM then to be honest it doesn't really matter what you pass the pointers around as. In fact you might as well use "void *". The only time it's important what a pointer is pointing to is when you dereference it. So:

But you aren't going to be doing those operations on a pointer to data such as was being shown here. (but, yeah, you'll have too cast it from void * if you want to do arithmetic - but again it doesn't really matter what it points to as long as it's something of the same width).

When I said "it doesn't really matter what it points to" what I meant was RAM, flash, EEPROM or whatever. A "char *" is good for accessing 8bits whether it's in any of those memory spaces.

I attempted to do const char MyArray[2][2][5] PROGMEM = {{"Test",Test"},{"Test",Test"}}; but I now am unable to draw the strings out using (PGM_P)pgm_read_word(&(MyArray[1][1]))

Looks like you have a misconception about that three dimensional char array. There is no indirection involved. No need to read an address from flash first which then points to the text. &(MyArray[1][1]) is already the address of the text.