Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
futrtrubl
PostPosted: Jul 07, 2007 - 01:15 AM
Hangaround


Joined: Aug 29, 2006
Posts: 229
Location: Kingston, Jamaica

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-
Code:

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..

Edward
 
 View user's profile Send private message  
Reply with quote Back to top
swisst
PostPosted: Jul 09, 2007 - 10:12 AM
Newbie


Joined: Jul 06, 2007
Posts: 3


Explaine pls. how can I access fields of structure located in program memory ?
 
 View user's profile Send private message  
Reply with quote Back to top
lfmorrison
PostPosted: Jul 09, 2007 - 01:55 PM
Raving lunatic


Joined: Dec 08, 2004
Posts: 4502
Location: Nova Scotia, Canada

Code:
#include <avr/pgmspace.h>
struct MyStruct
{
   char x;
   char y;
   int z;
};

struct MyStruct foo PROGMEM = {'a', 'b', 312};

int main(void)
{
    int MyInt = pgm_read_word(&foo.z);
}
 
 View user's profile Send private message  
Reply with quote Back to top
swisst
PostPosted: Jul 09, 2007 - 02:54 PM
Newbie


Joined: Jul 06, 2007
Posts: 3


Code:
#include <avr/pgmspace.h>
struct MyStruct
{
   char x;
   char y;
   int z;
   void (*Procedure)();
};

struct MyStruct foo PROGMEM =
 {'a', 'b', 312, Read_Procedure};

int main(void)
{
    int MyInt = pgm_read_word(&foo.z);
}


If structure is located in RAM I can call read procedure:
Code:
int main(void)
{
    int MyInt = pgm_read_word(&foo.z);
   
    foo.Read_Procedure();
}


Tell me please how can I call read procedure if I locate structure in program memory ?
 
 View user's profile Send private message  
Reply with quote Back to top
lfmorrison
PostPosted: Jul 09, 2007 - 03:37 PM
Raving lunatic


Joined: Dec 08, 2004
Posts: 4502
Location: Nova Scotia, Canada

Note that this is off the top of my head so there may be some inconsistent syntax; I have done things similar to this before, but I don't have the source code in front of me as I write this.

Code:
typedef void (*function_pointer)();

int main(void)
{
   function_pointer Proc = (function_pointer)pgm_read_word(&foo.Procedure);
   Proc();
}


- Luke
 
 View user's profile Send private message  
Reply with quote Back to top
jdowns
PostPosted: Jul 31, 2007 - 11:26 PM
Hangaround


Joined: Dec 02, 2004
Posts: 284
Location: San Diego, CA

Dean, I just wanted to say thanks for writing this tutorial... It just helped me out a lot!!!!

- James
 
 View user's profile Send private message  
Reply with quote Back to top
lacis_alfredo
PostPosted: Aug 16, 2007 - 03:05 AM
Rookie


Joined: Aug 10, 2007
Posts: 35
Location: Brisbane, Australia

Hi, Dean, Thanks for the tute.
You say, in two places:
Quote:
pgm_read_byte. This macro takes a PROGMEM pointer as its argument, and returns the string located at that pointer value.

It should say something like:
Quote:
pgm_read_byte. This macro takes a PROGMEM pointer as its argument, and returns one byte located at that pointer value.


Also maybe add pgm_read_dword() beside pgm_read_word(), something like. "Similarly, for 4-byte values, we can use prgm_read_dword()."

-- Alf
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
abcminiuser
PostPosted: Aug 16, 2007 - 05:03 AM
Moderator


Joined: Jan 23, 2004
Posts: 7028
Location: Melbourne, Victoria, Australia

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 Evil

_________________

 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
CirMicro
PostPosted: Oct 07, 2007 - 05:59 PM
Posting Freak


Joined: Jun 04, 2007
Posts: 1075
Location: Cincinnati, Ohio - USA

Hi Dean,

Is there any reason that this correction was never made to the tutorial:

Quote:

void USART_TxString_P(const char *data)
{
while (pgm_read_byte(*data) != 0x00)
USART_Tx(pgm_read_byte(*data++));
}

The body of the function should read:

Code:
while (pgm_read_byte(data) != 0x00)
USART_Tx(pgm_read_byte(data++));


Very nice tutorial overall though!

Thanks
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Oct 07, 2007 - 11:52 PM
Moderator


Joined: Jan 23, 2004
Posts: 7028
Location: Melbourne, Victoria, Australia

Quote:

Is there any reason that this correction was never made to the tutorial:


Yes, an extreamly good one - I forgot! It's now fixed, thanks!

- Dean Twisted Evil

_________________

 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
CirMicro
PostPosted: Oct 09, 2007 - 04:04 AM
Posting Freak


Joined: Jun 04, 2007
Posts: 1075
Location: Cincinnati, Ohio - USA

Thanks Dean,

I was working on the IAR to GCC Converter when I found your tutorial which has been a lot of help. I'm nearly finished with the flash part, then I just need to tackle the EEPROM stuff. Smile
 
 View user's profile Send private message  
Reply with quote Back to top
westfw
PostPosted: Oct 23, 2007 - 01:52 AM
Wannabe


Joined: Jun 19, 2002
Posts: 92
Location: SF Bay area

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?

I've got problems similar to everyone else; menus:

Code:
typedef const struct menu_item_ {
    unsigned char menu_key;
    menu_action_t menu_action;   /* function or menu pointer */
} menu_item_t;

const menu_item_t foo[] PROGMEM = {
  {'A', nextmenuA},
  {'B', nextmenuB},
  {0, "menu help string"}
};


And then code, for example, to draw a prompt (on a non-progmem implementation) that looks like:

Code:
menu_item_t *menu, *lastitem;
    drawmenu:
   lastitem = menu;
   while ((lastitem->menu_key & 0x7F) != 0)
       lastitem++;  /* Find menu terminator to get type of draw */
   if (lastitem->menu_action != 0) {
       char *p = (char *) lastitem->menu_action;
       while (*p)
      printf("%c", *p++);
   } else {   
       while (menu->menu_key != 0) {
      printf("%c, ", menu->menu_key & 0x7F);
      menu++;
       }
   }
   printf("\r\n");
   return;            /* Done! */

and the code is looking really ugly as I try to insert pgm_read calls in the appropriate places...
 
 View user's profile Send private message  
Reply with quote Back to top
westfw
PostPosted: Dec 14, 2007 - 10:25 AM
Wannabe


Joined: Jun 19, 2002
Posts: 92
Location: SF Bay area

So how come the definition of PSTR defines the string as
Code:
((const PROGMEM char *)(s))

instead of using the typedefs for prog_char:
Code:
((const prog_char *)(s))

It seems like the latter would allow C++ code to run different methods for progmem strings rather than ram strings (which would be a good thing.)
 
 View user's profile Send private message  
Reply with quote Back to top
reSpawn
PostPosted: Dec 20, 2007 - 11:27 PM
Wannabe


Joined: Jun 10, 2007
Posts: 62
Location: Romania, Oradea

Thanks Dean! Your tutorials helped me a lot.
 
 View user's profile Send private message  
Reply with quote Back to top
vthinsel
PostPosted: Jul 17, 2008 - 04:20 PM
Rookie


Joined: Apr 16, 2008
Posts: 43


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.

I'm using an atmega128, and the summary is:
Program: 23934 bytes (18.3% Full)
(.text + .data + .bootloader)

Data: 642 bytes (15.7% Full)
(.data + .bss + .noinit)

Once more, thanks to avrfreaks folks !

Vincent.
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Jul 17, 2008 - 04:30 PM
Moderator


Joined: Jan 23, 2004
Posts: 7028
Location: Melbourne, Victoria, Australia

There are two limits:

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 Evil

_________________

 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
vthinsel
PostPosted: Jul 17, 2008 - 05:15 PM
Rookie


Joined: Apr 16, 2008
Posts: 43


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 ?) ?

Thanks.
Vincent.
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Jul 17, 2008 - 06:03 PM
Moderator


Joined: Jan 23, 2004
Posts: 7028
Location: Melbourne, Victoria, Australia

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.

Code:
char StringLocatedOver64KB[] = "Test";

int main (void)
{
   char a = pgm_read_byte_far(0x10000 | (uint16_t)&StringLocatedOver64KB);
}


You'd need to write your own "far" versions of the other library routines which deal with FLASH memory, such as memcmp_P(), using the far accessor routines.


Alternatively, use Carlos' macro to get the far address of a variable in FLASH space instead:

Code:
#define GET_FAR_ADDRESS(var)                          \
({                                                    \
    uint_farptr_t tmp;                                \
                                                      \
    __asm__ __volatile__(                             \
                                                      \
            "ldi    %A0, lo8(%1)"           "\n\t"    \
            "ldi    %B0, hi8(%1)"           "\n\t"    \
            "ldi    %C0, hh8(%1)"           "\n\t"    \
            "clr    %D0"                    "\n\t"    \
        :                                             \
            "=d" (tmp)                                \
        :                                             \
            "p"  (&(var))                             \
    );                                                \
    tmp;                                              \
})

int main (void)
{
   char a = pgm_read_byte_far(GET_FAR_ADDRESS(StringLocatedOver64KB);
}


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 Evil

_________________

 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
Baldrian
PostPosted: Jul 30, 2008 - 05:06 PM
Hangaround


Joined: Jul 10, 2008
Posts: 150
Location: Ruhrpott, Germany

Nice tutorial, but I'm still totally screwed.
I read also the avr-libc FAQ http://www.nongnu.org/avr-libc/user-man ... _rom_array but I'm still not getting how to make an array of structs into flash.

I want to have a struct of strings for a menu.
like
struct {
char z[2][20]
} mystruct

And I want to make an array of this structs for different languages.
mystruct myarray[n_languages]

So that i can access the strings by something like
this example:
array[French].z[0]
or
array[French].z[1]

And now I want to have my 2.5k of strings in flash using Progmem Laughing
How to do that?

_________________
http://xkcd.com/221/
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Jul 30, 2008 - 05:28 PM
Moderator


Joined: Jan 23, 2004
Posts: 7028
Location: Melbourne, Victoria, Australia

Easy, just add the PROGMEM attribute to the structure itself:

Code:
struct {
char z[2][20]
} mystruct PROGMEM;


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 Evil

_________________

 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits