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
japroach
PostPosted: Jul 20, 2006 - 10:27 PM
Wannabe


Joined: May 28, 2006
Posts: 50
Location: vancouver

Great tutorial, very well written.

One question:
Quote:
Because of this fact, we can now make use of it to read out our table data. If we wanted to grab the fourth element of the array, the following extract would complete this purpose:

Code:
pgm_read_word(&LCD_SegTable[4])

Wouldn't this be the fifth element of the array?
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Jul 20, 2006 - 11:55 PM
Moderator


Joined: Jan 23, 2004
Posts: 9817
Location: Trondheim, Norway

Now I know why Smokey's book had so much erratta! If I can't even get a couple of pages right, I shudder to think of what a full book would contain!

You are of course correct. I was using conventional numbering rather than the (true!) zero-indexed way of counting. Fixed.

- Dean Twisted Evil

_________________
Atmel Studio 6.1 is now released, grab it here.
Report AS6/ASF bugs here.
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
GlingON
PostPosted: Oct 13, 2006 - 02:27 AM
Newbie


Joined: Aug 27, 2006
Posts: 11


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

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.
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Oct 13, 2006 - 07:00 AM
Moderator


Joined: Jan 23, 2004
Posts: 9817
Location: Trondheim, Norway

GlingON,

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 Evil

_________________
Atmel Studio 6.1 is now released, grab it here.
Report AS6/ASF bugs here.
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
GlingON
PostPosted: Oct 13, 2006 - 11:07 AM
Newbie


Joined: Aug 27, 2006
Posts: 11


Yeah, it was the .pdf. I was looking at that since it's nicer to look at than the forums. Sorry, I should have specified more clearly.

That said I'm still seeing the error in the post and in the .pdf. Let me point it out. It is near the end of part 1.

Code:

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++));
 
 View user's profile Send private message  
Reply with quote Back to top
RancidWannaRiot
PostPosted: Oct 17, 2006 - 07:20 AM
Wannabe


Joined: May 13, 2005
Posts: 50


Why did you say that

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


only works once??

The documentation say's absolutly nothing about that..

and i managed to use PSTR() a millions times with printf_P()

i used it many times like so..

Code:
printf_P(PSTR("Hello world"));
printf_P(PSTR("How are you doing"));


litterally about 100 times, with no issues..

what exactly did you mean by you can only use it once?

I was using a basic hitachi interface LCD (4x20)
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Oct 17, 2006 - 07:25 AM
Moderator


Joined: Jan 23, 2004
Posts: 9817
Location: Trondheim, Norway

Sorry, I meant that individual string can only then be used once. If you make the string a global declaration:

Code:
uint8_t SomeString PROGMEM = "Some String";


Then you can use it multiple times throughout your program:

Code:
// In some function
printf_P(SomeString);

// In some other function
printf_P(SomeString);


When using PSTR, that string is only available in the instance where it is used - it's unavailable to other statements in your program. You'd have to make duplicates of the string:

Code:
// In some function
printf_P(PSTR("Some String"));

// In some other function
printf_P(PSTR("Some String"));


And waste flash (unless the appropriate GCC optimiser flags are set).

Sorry for the confusion.

- Dean Twisted Evil

_________________
Atmel Studio 6.1 is now released, grab it here.
Report AS6/ASF bugs here.
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
RancidWannaRiot
PostPosted: Oct 17, 2006 - 04:33 PM
Wannabe


Joined: May 13, 2005
Posts: 50


abcminiuser wrote:
Sorry, I meant that individual string can only then be used once. If you make the string a global declaration:

Code:
uint8_t SomeString PROGMEM = "Some String";


Then you can use it multiple times throughout your program:

Code:
// In some function
printf_P(SomeString);

// In some other function
printf_P(SomeString);


When using PSTR, that string is only available in the instance where it is used - it's unavailable to other statements in your program. You'd have to make duplicates of the string:

Code:
// In some function
printf_P(PSTR("Some String"));

// In some other function
printf_P(PSTR("Some String"));


And waste flash (unless the appropriate GCC optimiser flags are set).

Sorry for the confusion.

- Dean Twisted Evil


aahh i see i see.. thanks
 
 View user's profile Send private message  
Reply with quote Back to top
Bingo600
PostPosted: Dec 07, 2006 - 01:40 PM
Raving lunatic


Joined: Apr 25, 2004
Posts: 3808
Location: Denmark

I think this thread might be of value here

PROGMEM using structs and arrays
http://www.avrfreaks.net/index.php?name ... mp;t=31622

/Bingo
 
 View user's profile Send private message  
Reply with quote Back to top
Sleekas
PostPosted: Jan 16, 2007 - 10:30 PM
Newbie


Joined: Dec 14, 2006
Posts: 2


Awesome guide! After reading it a few times, I think I have a much better understanding about accessing program data in AVR.

Based on what Lars was saying, should

Code:
pgm_read_word(&LCD_SegTable[4])


be

Code:
pgm_read_word(LCD_SegTable[4])


?
 
 View user's profile Send private message  
Reply with quote Back to top
lfmorrison
PostPosted: Jan 17, 2007 - 01:17 AM
Raving lunatic


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

Sleekas wrote:
Awesome guide! After reading it a few times, I think I have a much better understanding about accessing program data in AVR.

Based on what Lars was saying, should

Code:
pgm_read_word(&LCD_SegTable[4])


be

Code:
pgm_read_word(LCD_SegTable[4])


?

No.
 
 View user's profile Send private message  
Reply with quote Back to top
Sleekas
PostPosted: Jan 17, 2007 - 08:20 PM
Newbie


Joined: Dec 14, 2006
Posts: 2


Oh I see, it's because LCD_SegTable contains ints (not int pointers), while MenuItemPointers contains char pointers.
 
 View user's profile Send private message  
Reply with quote Back to top
d99mhl
PostPosted: Apr 27, 2007 - 08:25 AM
Rookie


Joined: Apr 30, 2004
Posts: 43
Location: Sweden

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.
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Apr 27, 2007 - 08:41 AM
Moderator


Joined: Jan 23, 2004
Posts: 9817
Location: Trondheim, Norway

Cheers d99mhl!

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 Evil

_________________
Atmel Studio 6.1 is now released, grab it here.
Report AS6/ASF bugs here.
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
d99mhl
PostPosted: Apr 27, 2007 - 09:23 AM
Rookie


Joined: Apr 30, 2004
Posts: 43
Location: Sweden

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. Wink
 
 View user's profile Send private message  
Reply with quote Back to top
AllN
PostPosted: Apr 29, 2007 - 04:13 AM
Posting Freak


Joined: Feb 14, 2007
Posts: 1858
Location: San Diego California

Hi Dean
Yet another great Tut! But this one I can’t thank you enough for. As it is saving me I’ll bet a week of research and experiment time.
Thanks again,
John
You’re the greatest!!

_________________
Resistance is futile…… You will be compiled!
 
 View user's profile Send private message  
Reply with quote Back to top
Paul Turner
PostPosted: Apr 29, 2007 - 09:01 PM
Wannabe


Joined: Oct 15, 2004
Posts: 69
Location: Australia

The strncmp_P() call is missing the 'n' parameter.
Prototype in pgmspace.h =
extern int strncmp_P(const char *, PGM_P, size_t) __ATTR_PURE__;
Or just use strcmp_P()
Cheers, Paul

_________________
I have coded for about 2 dozen architectures, and they all have their place.
Don't get too religious about them (but AVR is excellent!)
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Apr 30, 2007 - 08:32 AM
Moderator


Joined: Jan 23, 2004
Posts: 9817
Location: Trondheim, Norway

Thanks AllN, no problem! Glad it helped.

Paul: You're dead right, I didn't catch that on my proof-reading. Fixed.

- Dean Twisted Evil

_________________
Atmel Studio 6.1 is now released, grab it here.
Report AS6/ASF bugs here.
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
UFAnders
PostPosted: Jul 06, 2007 - 06:50 PM
Newbie


Joined: Nov 01, 2006
Posts: 18
Location: San Jose, CA, USA

Very nice tutorial, thanks to you all.

Gentlemen, I have a quick question: As I understand it, all arrays/structs are passed as pointers when used as a function argument. I am using a font set declared as
Code:
 const unsigned char PROGMEM font[128][5]
Why, then, does
Code:
tempChar0 = pgm_read_byte(font[cTemp][0]);
not work but
Code:
tempChar0 = pgm_read_byte(&font[cTemp][0]);
does? It seems to me that pgm_read_byte() would be getting a pointer to a pointer. Am I misunderstanding something?

Thanks!
 
 View user's profile Send private message  
Reply with quote Back to top
AllN
PostPosted: Jul 06, 2007 - 07:07 PM
Posting Freak


Joined: Feb 14, 2007
Posts: 1858
Location: San Diego California

Because &font[cTemp][0] is the address of the unsigned char and is a pointer while the 1st is not.
Only because the author of pgm_read_byte wrote it to receive a pointer not the unsigned char it self?

Edited:
And it's the best practice!

_________________
Resistance is futile…… You will be compiled!
 
 View user's profile Send private message  
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