passing a pointer from a struct loc in PRGMEM, to a fucntion

Go To Last Post
28 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
menu.h

// Forward structure declarations
struct          MENU_Item_Collection_ struct;
typedef struct  MENU_Item_Collection_ struct		MENU_Item_Collection_t;

struct MENU_Item_Collection_ struct 
{
    U8          menu_mask;	
    U8          menu_enter;	
    U8          menu_exit;
    U8          item_group;
    U8          item_group_index;
    U8          item_type;
    PGM_VOID_P  item_p;
};

void update_screen (MENU_Item_Collection_t const * menu_items);
//----------- end menu.h --------------//


menu.c

void update_screen (MENU_Item_Collection_t const * menu_items)
{
	U8	item_group = 0;
	item_group  = pgm_read_byte(menu_items ->item_group);
    ...
    ...
}
//----------- end menu.c --------------//



setup.c

#include menu.h

const MENU_Item_Collection_t PROGMEM menu_items_pgm[] = 
{
     {0xFF,0x01,0x00,0x01,0x00,0x01,&menu_1}
    ,{0xFF,0x00,0x00,0x01,0x01,0x03,&menu_2}
    ,{0xBF,0x00,0x00,0x01,0x02,0x03,&menu_3}
    ,{0x9F,0x00,0x00,0x01,0x03,0x03,&menu_4}
    ,{...}
    ,{...}
}

Some_function (void)
{
	update_screen (&menu_items_pgm[2]);
	...
	...
}
//----------- end setup.c --------------//

Whatever I try to get the pointer to my structure, I get the wrong values in the 'update_screen' function. If I use a different cast than const *, I get an error from the compiler, or else, I can’t reference to the different elements in the structure.

Any ideas what I’m doing wrong (it's probably something stupid)?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Apparently, this is not possible, I need to use a const void* without the struct definition for the argument in my update_screen function, and then copy the structure from flash memory into a variable placed in ram, with the memcpy_P function. Then I can access the different members in the structure.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

you could try using the offsetof() macro

#include 
.
.
.
void update_screen (MENU_Item_Collection_t const * menu_items)

item_group  = pgm_read_byte(menu_items + offsetof(MENU_Item_Collection_t, item_group));

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'll put some comments in the quoted part, so the alignment is not lost

fleemy wrote:

menu.h

// Forward structure declarations
struct          MENU_Item_Collection_ struct;
                                     ^
_____________________________________|
Superfluous space. This is either not your
real code (why not?) or you have it broken
right here 

typedef struct  MENU_Item_Collection_ struct		MENU_Item_Collection_t;
                                     ^
_____________________________________|
Superfluous space. Againg

struct MENU_Item_Collection_ struct 
                            ^
____________________________|
And again superfluous space.


{
    U8          menu_mask;	
    U8          menu_enter;	
    U8          menu_exit;
    U8          item_group;
    U8          item_group_index;
    U8          item_type;
    PGM_VOID_P  item_p;
};

BTW You could do the struct and the typedef in one go, without the need to resort to forward declarations

typedef struct  {
 
} ;

Quote:

void update_screen (MENU_Item_Collection_t const * menu_items);

Either (pay close attention to the order of things)

void update_screen (const MENU_Item_Collection_t *menu_items);

This is what people usually want: The argument is a pointer to a const(ant) MENU_Item_Collection_t.

void update_screen (MENU_Item_Collection_t * const menu_items);

The above is a const(ant) pointer to a (changeable) MENU_Item_Collection_t. This is rarely used.

void update_screen (const MENU_Item_Collection_t * const menu_items);

The above is a const(ant) pointer to a const(ant) MENU_Item_Collection_t. This is rarely used.

Quote:

{
     {0xFF,0x01,0x00,0x01,0x00,0x01,&menu_1}
    ,{0xFF,0x00,0x00,0x01,0x01,0x03,&menu_2}
    ,{0xBF,0x00,0x00,0x01,0x02,0x03,&menu_3}
    ,{0x9F,0x00,0x00,0x01,0x03,0x03,&menu_4}
    ,{...}
    ,{...}
}

Why do beginners always feel they need to become so creative in formatting code? It is not syntactically wrong, but by convention the comma belongs at the end of the line. That's where it belongs for more than 30 years.

Quote:
Whatever I try to get the pointer to my structure, I get the wrong values in the 'update_screen' function.
Get a good textbook on C and read it (and spare me the whining how hard it is to get and read a book).

Quote:
If I use a different cast than const *
That is not a cast. Get a good C textbook and ...

Stealing Proteus doesn't make you an engineer.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
   item_group  = pgm_read_byte(menu_items ->item_group); 

pgm_read_xxx needs an address so this must be

   item_group  = pgm_read_byte(&menu_items->item_group); 

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi glitch, Arnold, frist off thanks for the response!

Those spaces are not in my code, it probable happened when I was copy/pasting.

ArnoldB wrote:
BTW You could do the struct and the typedef in one go, without the need to resort to forward declarations

typedef struct  {
 
} ;

I need those structures in different .c files (different menus), thus I forward them in the menu.h file, otherwise i'll have two of the same typedef’s, right?

ArnoldB wrote:

void update_screen (const MENU_Item_Collection_t *menu_items);

This is what people usually want: The argument is a pointer to a const(ant) MENU_Item_Collection_t.

I tried it this way, didn’t seem to work.

ArnoldB wrote:

{
     {0xFF,0x01,0x00,0x01,0x00,0x01,&menu_1}
    ,{0xFF,0x00,0x00,0x01,0x01,0x03,&menu_2}
    ,{0xBF,0x00,0x00,0x01,0x02,0x03,&menu_3}
    ,{0x9F,0x00,0x00,0x01,0x03,0x03,&menu_4}
    ,{...}
    ,{...}
}

Why do beginners always feel they need to become so creative in formatting code? It is not syntactically wrong, but by convention the comma belongs at the end of the line. That's where it belongs for more than 30 years.

At this time, I’m still adding some features in the menu’s, mostly at the end, I find it easer to copy/past it when formatted this way.

ArnoldB wrote:
[
Quote:
Whatever I try to get the pointer to my structure, I get the wrong values in the 'update_screen' function.
Get a good textbook on C and read it (and spare me the whining how hard it is to get and read a book).

Quote:
If I use a different cast than const *
That is not a cast. Get a good C textbook and ...

Honestly, I know it’s not a (cast), but couldn’t find the correct word. (I speak and write, Dutch, French, English, and a little German, thus after many hours off nestling with the C language, I get a brain fart from time to time)

But you’re right, I need a good textbook on C, the first book I’ve bought was ‘Embedded C Programming and the Atmel AVR’ from Barnett, Cox and O’Cull, but there isn’t much explanation (in-depth) on the C- language.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lajon wrote:

   item_group  = pgm_read_byte(menu_items ->item_group); 

pgm_read_xxx needs an address so this must be

   item_group  = pgm_read_byte(&menu_items->item_group); 

/Lars

That could be my problem, I’ll try it after I got some sleep.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

At this time, I’m still adding some features in the menu’s, mostly at the end, I find it easer to copy/past it when formatted this way.

If this is because you don't want to miss out on the comma, then here's something you maybe didn't know: You are allowed to have a comma after the last element in an array initializer, like so:

const MENU_Item_Collection_t PROGMEM menu_items_pgm[] =
{
     {0xFF,0x01,0x00,0x01,0x00,0x01,&menu_1},
     {0xFF,0x00,0x00,0x01,0x01,0x03,&menu_2},
     {0xBF,0x00,0x00,0x01,0x02,0x03,&menu_3},
     {0x9F,0x00,0x00,0x01,0x03,0x03,&menu_4},
     {...},
     {...},
} 

and AFAIK this is allowed for exactly the situation that you are expanding the array initializer one element at a time.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That's the whole reason, yes Johan.

I’ve noticed also, that some ‘Atmel’ programmers are using the same way of formatting, given their examples code.

I’m not sure anymore, but I think that the compiler gave me an error (or at least a warning), when I added accidently a comma at the end of the array initializer.

I’ve changed the code format since.

I’ll give it a second try.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just to confirm:

#include  


typedef struct {
	int n;
	char c;
	long fred;
} struct_type;

struct_type fred[] = { 
  {3, 'a', 0x12345}, 
  {50, 'z', 0x54321}, // note ','
};

int main(void) {
}

produces:

AVR Memory Usage
----------------
Device: at90usb162

Program:     202 bytes (1.2% Full)
(.text + .data + .bootloader)

Data:         14 bytes (2.7% Full)
(.data + .bss + .noinit)

where the 14 bytes are two lots of initial data for the 7 byte structure.

So the ',' neither caused warning/error nor to generate a third "zero" element.

Cliff

Last Edited: Wed. Aug 6, 2008 - 01:44 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Some compilers complain and some don't.

It is always safest to avoid that last comma, otherwise you will find that it will come back to bite you.

If you really like the pasting bit, you can always put a dummy NULL structure in the last line. Assuming of course that your structure access routines can handle it.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
you can always put a dummy NULL structure in the last line

Yup:

struct_type fred[] = { 
  {3, 'a', 0x12345}, 
  {50, 'z', 0x54321}, 
  { 0 }
};

leads to:

AVR Memory Usage
----------------
Data:         22 bytes (4.3% Full)
(.data + .bss + .noinit)

Not sure why that's 22 and not 21 bytes though?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Edit, ah now I see, the 'fred' provide 21 (0x15) bytes:

 .data          0x00800100       0x15 test.o
                0x00800100                fred

but the .map also shows:

                0x00800116                . = ALIGN (0x2)
 *fill*         0x00800115        0x1 00

(learn something new every day - I didn't realise .data aligned to 2 byte boundaries but as it's copied from code flash perhaps this should have been obvious?)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well you guys are right (who would have doubted that), I added a comma at the last element of an initializer in my code example (40k+), and no complaints from the compiler.

I remember how It happened now, it was during a copy/past of some new elements at the end of the initializer, and forgot to add a comma at the last element above, where I was pasting then new elements, It happened more than once, so I decided to do it the other way around.

Now I’m going to recode the function, what made me start this topic, because I already changed the function with a memcpy_P macro to a ram variable. Too bad that AVR Studio doesn’t have a way of versioning like Visual Safe Source.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lajon wrote:
pgm_read_xxx needs an address so this must be

   item_group = pgm_read_byte(&menu_items->item_group); 

/Lars

That works.

I was confused because the parameter in my function call is already a pointer to a structure.

I also tried this, and thought it would work:

   item_group = pgm_read_byte(*menu_items.item_group); 

But the compiler complains, it can’t find the structure.

Then again, this worked:

   item_group = pgm_read_byte(&(*menu_items).item_group); 

Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'd suggest a good book on C - perhaps K&R - to learn about structure pointers.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I heard already a few times about the 'K&R' book, I think it's time to visit the Amazon site. Any other online book stores that might have good prices?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

K&R will generally hold value quite well. In general, tho, go to www.bestbookbuys.com (which will take you to www.bestwebbuys.com ) and find the book(s) you are looking for by title, author, or ISBN. The search function will then give you a list of available sources. The nice thing is that it will include half.com and Amazon used. At half.com it will run a check on eBay auctions as well (I beleive that they are associated).

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

Is this the book you are on about: -

http://www.amazon.com/Programmin...

I too could do with going over Pointers and correct structure useage :).

Andy

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Is this the book you are on about

Yes. The authors are the inventors of the language.
Straight from the horses mouth, as they say.

Quote:
Amazon used

I'm a book nerd, and buy an awful lot of books on Amazon Marketplace (which I suppose is what is hinted at here). Generally, I'd recommend that place, but for K&R I'd be somewhat wary. Do not buy anything at AM that not has condition "new" or "mint condition" or similar. You don't want a book with highlighting, or a binding that is seeing it's last mediocre days. Last time I browsed through the K&Rs at AM there where none that I should have bought. The second hand prices on K&R is fairly high (supporting Lee's claim on it holding value), and if you can get a new item for just a few bucks more then I'd recommend that instead of AM.

For less popular or less timeless books, AM is the place. If you, for example, could live with a C# book that is "one generation out of date" (ie C#/.Net 2005), then you will probably find it for a bargain-price through AM as NOS ("New Old Stock"). Be meticolos about checking the ratings of the sellers. Buy from one that has old thousands or more books, and has a 95% or higher score.

If you are in for several books then check out special standing offers from eg O'Reilly like "three-for-two".

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the links, I think I'll buy the book new, to bad I didn't order that book along when I've ordered my 'USB Complete' book, would have saved me some shipping costs.

To return on topic, changing the code back to multiple ‘pgm_read_byte()’ instructions, instead of one memcpy_P instruction, bloated my code with another 300 bytes, and no decrease in sram (the memcpy_P, stores the ram portion probably in the stack, right?)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

memcpy_P stores the data where ever the destination pointer you pass it points to. The function does not allocate any space itself. Thus if your pointer is pointing to a reserved chunk of bytes on the stack (automatic variable you're using for storage), then that is where it will be placed.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, I was only using that variable(structure), in that specific function, when using memcpy_P.

So let me guess, not only do I lose some program flash, I do not gain in sram (not counting the stack), but I also lose in performance (not that it matters in this specific menu portion), when using multiple pgm_read_byte() functions...

But still, I’ll keep the multiple pgm_read_byte() functions, not sure why though (stack overflow?, laziness?).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
For less popular or less timeless books, AM is the place.

IMO for US buying, I rarely end up on Amazon after looking over half.com choices.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

IMO for US buying

Yeah. I might be biased towards AM because it has (IMO) advantaged for non-US buyers. YMMV. Sorry.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

fleemy wrote:
Yes, I was only using that variable(structure), in that specific function, when using memcpy_P.

So let me guess, not only do I lose some program flash, I do not gain in sram (not counting the stack), but I also lose in performance (not that it matters in this specific menu portion), when using multiple pgm_read_byte() functions...

But still, I’ll keep the multiple pgm_read_byte() functions, not sure why though (stack overflow?, laziness?).

if all you're doing is copying the entire structure to ram, then there is no advantage to using pgm_read_byte() here. memcpy_P() will be more efficient. But you will not save any RAM, as you still need to store the data in RAM.

What you can do is keep passing around the flash pointer, and use pgm_read_byte() and pgm_read_word() to read the individual members of the structure as you need them. When you do this, you will save RAM, as you don't need to store the entire structure anywhere. Flash usage may increase a bit, as you are making individual reads of the data, instead of using a copy loop to relocate it into RAM.

Also if you are storing the copy on the stack (automatic variable) then you won't see a reduction in ram from the compiler output, but you will be reducing stack usage, thus reducing the risk of overflow.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

Sorry to move the topic again, but is the "'USB Complete" Book any good, as i would like to learn about all things USB, i have the AT90USB board from Atmel, but need to understand USB before diving into the Atmel example code, otherwise i an could to get very confused.

My K&R Book has arrived from amazon, and is the best C book i have ever read. I am slowly working my way through the book using a free C++ Compiler called 'Bloodshed Dev-C++' that can be found at the following link: -

http://www.bloodshed.net/dev/

Quote:
JohanEkdahl : - If you, for example, could live with a C# book

If anybody is learning C#,C++ or VB.Net i found some brilliant video tutorials here: -

http://www.learnvisualstudio.net/

Which i highly recommend.

Sorry for the topic change again, just did not seem like a new topic needed starting.

Andy

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Xplosiv_1 wrote:
Sorry to move the topic again, but is the "'USB Complete" Book any good, as i would like to learn about all things USB, i have the AT90USB board from Atmel, but need to understand USB before diving into the Atmel example code, otherwise i an could to get very confused.

If you want learn more in depth about the USB bus, and need to make a specific device, then yes. The author also describes how to make your own drivers and ‘.inf’ files(PC side). But it’s not specific for the AVR, he has only a few examples for the PIC and FTDI chip (using the D2XX drivers for example).

Xplosiv_1 wrote:
My K&R Book has arrived from amazon, and is the best C book i have ever read. I am slowly working my way through the book using a free C++ Compiler called 'Bloodshed Dev-C++' that can be found at the following link: -

Well, you’re fast, already finished the book!

I’ve ordered mine, but it will take a week or two before I’ll get it in the mailbox, shipping cost are high, if I want the book in 2 or 3 days, cost are almost the price of the book!