Dereferencing a flash array of pointers.

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

I have the following:

const tField* PROGMEM Page[] = {&Field1, &Field2, NULL};

where each element in the array is a structure in flash. What is the safest way to load these addresses from flash? At the moment I'm doing the following:

void DisplayPage(const tField** PROGMEM ppField)
{
    const tField* pField;
    pField = pgm_read_word(ppField);
    while(pField != NULL)
    {
        DisplayField(pField);
        ppField++;
        pField = pgm_read_word(ppField);
    }
}

void main(void)
{
    DisplayPage(Page);

    while(1) ;
}

The problem being that this method assumes the pointers are all 16-bits in length. Do I need to write my own macro to load the addresses from flash depending on the amount of flash the part has?

Gavin

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

I’ve done this as follows:

Define some strings and an array of those strings:

   const char ERROR_YOUFOOBARED[] PROGMEM = "You fouled up beyond repair.\r\0";
   const char ERROR_SNAFUED[] PROGMEM = "Situation normal, all fouled up.\r\0";
   const char ERROR_STOPTHEMADNESS[] PROGMEM = "Stop the madness!\r\0";   
   const char ERROR_WHERE[] PROGMEM = "Where did you learn to program?\r\0";
   const char ERROR_RTFM[] PROGMEM = "Read the freaking manual!\r\0";

   const char *ERROR_TBL[]    = { ERROR_YOUFOOBARED, ERROR_SNAFUED,   
      ERROR_STOPTHEMADNESS, ERROR_WHERE, ERROR_RTFM };

Send one of the strings to the PC with:

   sendFString(ERROR_TBL[num]);

Using this function:

// Send a string located in Flash ROM
void sendFString(const char *pFlashStr)
{
    uint8_t i;

   // The 'for' logic terminates if the byte is '\0' or if i = 60.
   // '\0' is 'null' and terminates C strings
   // The 60 prevents too much overrun if we get a bad pointer
   // and it limits the string size
   for (i = 0; pgm_read_byte(&pFlashStr[i]) && i < 60; i++)
   {
      sendChar(pgm_read_byte(&pFlashStr[i]));
   }
}

But with indents. Does this help?

Good Luck

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

Hi SmilyMicros

It's similar to what I'm doing except I have an array of pointers. I start at the first pointer in the array, check that it points to something other than null and then pass the address of that pointer to a function. I continue through the array until I hit the null at the end.

The name of the array when passed to a function becomes a pointer to an array of pointers. To dereference the pointer to pointers, I first copy the word (16-bits) that it's pointing to into ram and then check that to make sure it's not null before passing it along.

The problem with this solution is that I assume that my pointers are all 16-bits. I guess one solution is to ensure that I always place all my contants is flash below 0x10000 (byte address) which is 64k.

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

Any time I see two asterisks ** in C, I tend to freeze up. I'll try to find time tomorrow to look at the code you posted and play with it on my Butterfly, but hopefully a real guru will come across this and answer you question sooner.

Good Luck

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

vulcan wrote:

The problem with this solution is that I assume that my pointers are all 16-bits. I guess one solution is to ensure that I always place all my contants is flash below 0x10000 (byte address) which is 64k.

Technically this isn't a problem. For the current toolset, all data pointers are 16-bit only. When using an atmega128, AVR GCC will automatically place all data constants store in flash in the lower 64K.

So your method looks fine to me and it shouldn't be a problem.