| Author |
Message |
|
|
Posted: Jul 20, 2006 - 10:27 PM |
|

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? |
|
|
| |
|
|
|
|
|
Posted: Jul 20, 2006 - 11:55 PM |
|


Joined: Jan 23, 2004
Posts: 9830
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  |
_________________ Atmel Studio 6.1 is now released, grab it here.
Report AS6/ASF bugs here.
|
| |
|
|
|
|
|
Posted: Oct 13, 2006 - 02:27 AM |
|

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.
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. |
|
|
| |
|
|
|
|
|
Posted: Oct 13, 2006 - 07:00 AM |
|


Joined: Jan 23, 2004
Posts: 9830
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  |
_________________ Atmel Studio 6.1 is now released, grab it here.
Report AS6/ASF bugs here.
|
| |
|
|
|
|
|
Posted: Oct 13, 2006 - 11:07 AM |
|

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++));
|
|
|
| |
|
|
|
|
|
Posted: Oct 17, 2006 - 07:20 AM |
|

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) |
|
|
| |
|
|
|
|
|
Posted: Oct 17, 2006 - 07:25 AM |
|


Joined: Jan 23, 2004
Posts: 9830
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  |
_________________ Atmel Studio 6.1 is now released, grab it here.
Report AS6/ASF bugs here.
|
| |
|
|
|
|
|
Posted: Oct 17, 2006 - 04:33 PM |
|

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
aahh i see i see.. thanks |
|
|
| |
|
|
|
|
|
Posted: Dec 07, 2006 - 01:40 PM |
|


Joined: Apr 25, 2004
Posts: 3809
Location: Denmark
|
|
|
|
|
|
|
Posted: Jan 16, 2007 - 10:30 PM |
|

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])
? |
|
|
| |
|
|
|
|
|
Posted: Jan 17, 2007 - 01:17 AM |
|

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. |
|
|
| |
|
|
|
|
|
Posted: Jan 17, 2007 - 08:20 PM |
|

Joined: Dec 14, 2006
Posts: 2
|
|
| Oh I see, it's because LCD_SegTable contains ints (not int pointers), while MenuItemPointers contains char pointers. |
|
|
| |
|
|
|
|
|
Posted: Apr 27, 2007 - 08:25 AM |
|


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. |
|
|
| |
|
|
|
|
|
Posted: Apr 27, 2007 - 08:41 AM |
|


Joined: Jan 23, 2004
Posts: 9830
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  |
_________________ Atmel Studio 6.1 is now released, grab it here.
Report AS6/ASF bugs here.
|
| |
|
|
|
|
|
Posted: Apr 27, 2007 - 09:23 AM |
|


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.  |
|
|
| |
|
|
|
|
|
Posted: Apr 29, 2007 - 04:13 AM |
|


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!
|
| |
|
|
|
|
|
Posted: Apr 29, 2007 - 09:01 PM |
|


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!)
|
| |
|
|
|
|
|
Posted: Apr 30, 2007 - 08:32 AM |
|


Joined: Jan 23, 2004
Posts: 9830
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  |
_________________ Atmel Studio 6.1 is now released, grab it here.
Report AS6/ASF bugs here.
|
| |
|
|
|
|
|
Posted: Jul 06, 2007 - 06:50 PM |
|

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! |
|
|
| |
|
|
|
|
|
Posted: Jul 06, 2007 - 07:07 PM |
|


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