1/* Copyright (c) 2007  Eric B. Weddington
2   All rights reserved.
3
4   Redistribution and use in source and binary forms, with or without
5   modification, are permitted provided that the following conditions are met:
6
7   * Redistributions of source code must retain the above copyright
8     notice, this list of conditions and the following disclaimer.
9   * Redistributions in binary form must reproduce the above copyright
10     notice, this list of conditions and the following disclaimer in
11     the documentation and/or other materials provided with the
12     distribution.
13   * Neither the name of the copyright holders nor the names of
14     contributors may be used to endorse or promote products derived
15     from this software without specific prior written permission.
16
17  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  POSSIBILITY OF SUCH DAMAGE. */
28
29/* $Id: pgmspace.dox 1420 2007-10-02 13:50:16Z arcanum $ */
30
31/**
32
33\page pgmspace Data in Program Space
34
35\section pgmspace_introduction Introduction
36
37So you have some constant data and you're running out of room to store it?
38Many AVRs have limited amount of RAM in which to store data, but may have
39more Flash space available. The AVR is a Harvard architecture processor,
40where Flash is used for the program, RAM is used for data, and they each
41have separate address spaces. It is a challenge to get constant data to be
42stored in the Program Space, and to retrieve that data to use it in the
43AVR application.
44
45The problem is exacerbated by the fact that the C Language was not designed
46for Harvard architectures, it was designed for Von Neumann architectures where
47code and data exist in the same address space. This means that any compiler
48for a Harvard architecture processor, like the AVR, has to use other means to
49operate with separate address spaces.
50
51Some compilers use non-standard C language keywords, or they extend the standard
52syntax in ways that are non-standard. The AVR toolset takes a different
53approach.
54
55GCC has a special keyword, \c __attribute__ that is used to attach
56different attributes to things such as function declarations, variables, and
57types. This keyword is followed by an attribute specification in double
58parentheses. In AVR GCC, there is a special attribute called \c progmem. This
59attribute is use on data declarations, and tells the compiler to place
60the data in the Program Memory (Flash).
61
62AVR-Libc provides a simple macro \c PROGMEM that is defined as the attribute
63syntax of GCC with the \c progmem attribute. This macro was created as a
64convenience to the end user, as we will see below. The \c PROGMEM macro is
65defined in the \c <avr/pgmspace.h> system header file.
66
67It is difficult to modify GCC to create new extensions to the C language syntax,
68so instead, avr-libc has created macros to retrieve the data from the Program
69Space. These macros are also found in the \c <avr/pgmspace.h> system header
70file.
71
72
73\section pgmspace_const A Note On const
74
75Many users bring up the idea of using C's keyword \c const as a means of
76declaring data to be in Program Space. Doing this would be an abuse of
77the intended meaning of the \c const keyword.
78
79\c const is used to tell the compiler that the data is to be "read-only". It
80is used to help make it easier for the compiler to make certain transformations,
81or to help the compiler check for incorrect usage of those variables.
82
83For example, the const keyword is commonly used in many functions as a modifier
84on the parameter type. This tells the compiler that the function will only use
85the parameter as read-only and will not modify the contents of the parameter
86variable.
87
88\c const was intended for uses such as this, not as a means to identify where
89the data should be stored. If it were used as a means to define data storage,
90then it loses its correct meaning (changes its semantics) in other situations
91such as in the function parameter example.
92
93
94\section pgmspace_data Storing and Retrieving Data in the Program Space
95
96
97Let's say you have some global data:
98
99\code
100unsigned char mydata[11][10] =
101{
102	{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09},
103	{0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13},
104	{0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D},
105	{0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27},
106	{0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31},
107	{0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B},
108	{0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44,0x45},
109	{0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F},
110	{0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59},
111	{0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,0x61,0x62,0x63},
112	{0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D}
113};
114\endcode
115
116and later in your code you access this data in a function and store a single
117byte into a variable like so:
118
119\code
120byte = mydata[i][j];
121\endcode
122
123Now you want to store your data in Program Memory. Use the \c PROGMEM macro
124found in \c <avr/pgmspace.h> and put it after the declaration of the variable,
125but before the initializer, like so:
126
127\code
128#include <avr/pgmspace.h>
129.
130.
131.
132unsigned char mydata[11][10] PROGMEM =
133{
134	{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09},
135	{0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13},
136	{0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D},
137	{0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27},
138	{0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31},
139	{0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B},
140	{0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44,0x45},
141	{0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F},
142	{0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59},
143	{0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,0x61,0x62,0x63},
144	{0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D}
145};
146\endcode
147
148That's it! Now your data is in the Program Space. You can compile, link, and
149check the map file to verify that \c mydata is placed in the correct section.
150
151Now that your data resides in the Program Space, your code to access (read)
152the data will no longer work. The code that gets generated will retrieve the
153data that is located at the address of the \c mydata array, plus offsets
154indexed by the \c i and \c j variables. However, the final address that is
155calculated where to the retrieve the data points to the Data Space! Not the
156Program Space where the data is actually located. It is likely that you will
157be retrieving some garbage. The problem is that AVR GCC does not intrinsically
158know that the data resides in the Program Space.
159
160The solution is fairly simple. The "rule of thumb" for accessing data stored
161in the Program Space is to access the data as you normally would (as if the
162variable is stored in Data Space), like so:
163
164\code
165byte = mydata[i][j];
166\endcode
167
168then take the address of the data:
169
170\code
171byte = &(mydata[i][j]);
172\endcode
173
174then use the appropriate \c pgm_read_* macro, and the address of your data
175becomes the parameter to that macro:
176
177\code
178byte = pgm_read_byte(&(mydata[i][j]));
179\endcode
180
181The \c pgm_read_* macros take an address that points to the Program Space, and
182retrieves the data that is stored at that address. This is why you take the
183address of the offset into the array. This address becomes the parameter to the
184macro so it can generate the correct code to retrieve the data from the Program
185Space. There are different \c pgm_read_* macros to read different sizes of data
186at the address given.
187
188
189\section pgmspace_strings Storing and Retrieving Strings in the Program Space
190
191Now that you can successfully store and retrieve simple data from Program Space
192you want to store and retrive strings from Program Space. And specifically
193you want to store and array of strings to Program Space. So you start off
194with your array, like so:
195
196\code
197char *string_table[] =
198{
199    "String 1",
200    "String 2",
201    "String 3",
202    "String 4",
203    "String 5"
204};
205\endcode
206
207and then you add your PROGMEM macro to the end of the declaration:
208
209\code
210char *string_table[] PROGMEM =
211{
212    "String 1",
213    "String 2",
214    "String 3",
215    "String 4",
216    "String 5"
217};
218\endcode
219
220Right? WRONG!
221
222Unfortunately, with GCC attributes, they affect only the declaration that they
223are attached to. So in this case, we successfully put the \c string_table
224variable, the array itself, in the Program Space. This DOES NOT put the actual
225strings themselves into Program Space. At this point, the strings are still
226in the Data Space, which is probably not what you want.
227
228In order to put the strings in Program Space, you have to have explicit
229declarations for each string, and put each string in Program Space:
230
231\code
232char string_1[] PROGMEM = "String 1";
233char string_2[] PROGMEM = "String 2";
234char string_3[] PROGMEM = "String 3";
235char string_4[] PROGMEM = "String 4";
236char string_5[] PROGMEM = "String 5";
237\endcode
238
239Then use the new symbols in your table, like so:
240
241\code
242PGM_P string_table[] PROGMEM =
243{
244    string_1,
245    string_2,
246    string_3,
247    string_4,
248    string_5
249};
250\endcode
251
252Now this has the effect of putting \c string_table in Program Space, where
253\c string_table is an array of pointers to characters (strings), where each
254pointer is a pointer to the Program Space, where each string is also stored.
255
256The \c PGM_P type above is also a macro that defined as a pointer to a
257character in the Program Space.
258
259Retrieving the strings are a different matter. You probably don't want to pull
260the string out of Program Space, byte by byte, using the \c pgm_read_byte()
261macro. There are other functions declared in the <avr/pgmspace.h> header file
262that work with strings that are stored in the Program Space.
263
264For example if you want to copy the string from Program Space to a buffer in
265RAM (like an automatic variable inside a function, that is allocated on the
266stack), you can do this:
267
268\code
269void foo(void)
270{
271    char buffer[10];
272
273    for (unsigned char i = 0; i < 5; i++)
274    {
275        strcpy_P(buffer, (PGM_P)pgm_read_word(&(string_table[i])));
276
277        // Display buffer on LCD.
278    }
279    return;
280}
281\endcode
282
283Here, the \c string_table array is stored in Program Space, so
284we access it normally, as if were stored in Data Space, then take the address
285of the location we want to access, and use the address as a parameter to
286\c pgm_read_word. We use the \c pgm_read_word macro to read the string pointer
287out of the \c string_table array. Remember that a pointer is 16-bits, or word
288size. The \c pgm_read_word macro will return a 16-bit unsigned integer. We then
289have to typecast it as a true pointer to program memory, \c PGM_P. This pointer
290is an address in Program Space pointing to the string that we want to
291copy. This pointer is then used as a parameter to the function \c strcpy_P. The
292function \c strcpy_P is just like the regular \c strcpy function, except that
293it copies a string from Program Space (the second parameter) to a buffer in the
294Data Space (the first parameter).
295
296There are many string functions available that work with strings located in
297Program Space. All of these special string functions have a suffix of \c _P in
298the function name, and are declared in the <avr/pgmspace.h> header file.
299
300
301\section pgmspace_caveats Caveats
302
303The macros and functions used to retrieve data from the Program Space have
304to generate some extra code in order to actually load the data from the
305Program Space. This incurs some extra overhead in terms of code space (extra
306opcodes) and execution time. Usually, both the space and time overhead is
307minimal compared to the space savings of putting data in Program Space. But you
308should be aware of this so you can minimize the number of calls within a single
309function that gets the same piece of data from Program Space. It is always
310instructive to look at the resulting disassembly from the compiler.
311
312
313
314*/
315