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