How to define one-way linked structure in FLASH?

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

Hi,
Is it possible to define a one-way linked structure in FLASH?
Something like this:

struct test
{
	prog_char *stringptr;
	test *next;
};

So one element has a pointer to the next element:

test t1, t2;
char *s1[] PROGMEM ="test";
char *s2[] PROGMEM ="test1";


t1.stringptr=s1;
t2.stringptr=s2;
t1.next=&t2;
t2.next=NULL;

It's important that the list must be created during compilation, not later.
TIA.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
char *s1[] PROGMEM ="test";
char *s2[] PROGMEM ="test1"; 

I don't think that you really want the '*' here.

Quote:
It’s important that the list must be created during compilation, not later.
You simply need to create it in "reverse order":

test t2 PROGMEM = { s2, NULL };
test t1 PROGMEM = { s1, &t2 };

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
typedef struct test
{
   prog_char *stringptr;
   struct test *next;
} test_t;

char s1[] PROGMEM ="test";
char s2[] PROGMEM ="test1";

test_t PROGMEM t2 = {s2, NULL};
test_t PROGMEM t1 = {s1, &t2};

I think you will probably find it considerably easier to just use a an array of char*.

prog_char *stringlist[] PROGMEM = (s1, s2, NULL);

Note that I have taken liberties to substantially amend your types. And the first method involves writing the list backwards. You can probably wite it forwards if t1, t2 ... are declared as extern beforehand.

Both methods are untested.

David.

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

Thanks very much to both of you.
David, I cannot use an array of char*, because my real structure is far more complex, it stores a couple of fields. But the initialization of list you both proposed is perfect, either forward or backward initialization is acceptable for me.

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

I somehow thought that you may have complex structs.

However you can still use an array, and the initialisers are just layed out in a table. You either end with a sentinel value like NULL or the # of array elements.

Bear in mind that linked lists are designed to be dynamic. And arrays are designed to be of fixed size. Anything that is stored in FLASH is inherently not dynamic.

David.

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

Thanks for detailed explanation. My list actually can be either a constant static list with fixed number of items, or dynamic, stored in SRAM. I want to use the list for initialization of C++ class which will handle both situations. One constructor will initialize the class with struct stored in FLASH, and another one will create a struct dynamically in SRAM. Members of the class will take care about handling both situations.
I would like to use it to create menus, item list for generic GUI objects like menu, combo boxes, drop down lists etc. Now my classes can handle constants stored either in FLASH or SRAM, but the pointers have been stored in SRAM. Now I can store the whole struct in FLASH. So thanks again for your help.

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

Arrays still might be syntactically more convenient.

enum { FRED, GREG, HANK };

// alas, PSTR only works inside a function
prog_char pstr_fred[]="fred";
prog_char pstr_greg[]="greg";
prog_char pstr_hank[]="hank";

struct Struc {
    struct Struc * const ptr;
    prog_char * const str;
} const array[] PROGMEM ={
    [FRED]={array+FRED+1, pstr_fred},
    [GREG]={array+GREG+1, pstr_greg},
    [HANK]={0,            pstr_hank}
} ;

The array can be reordered mostly by just reordering FRED..HANK.
As is, the end condition still requires special handling.
If desired, that could be avoided with a macro.
The reordering property could make diffs smaller and easier to interpret.

Moderation in all things. -- ancient proverb