From the explanation of the Flash library, there's this note about how FLASH_STRING_ARRAY is a little bit special.
[Note also that the String Array is a slightly special case. For technical reasons, as you can see in the example, each member of the array initializer must be wrapped with the PSTR() operator. For this reason, String Arrays cannot be declared at global scope, but must be non-statically defined within in the body of a function. Note also that while the individual strings in a String Array are contained in PROGMEM space, the array itself (again, for technical reasons) is RAM-based, consuming 2 bytes per array element. This limitation does not apply to the other Flash types.]
I have a situation where the same very large chunk of character data is needed to be accessed from multiple functions.
Am I right in thinking I have two options, either:
write a function that is called for all access to the FLASH_STRING_ARRAY, centralising any data access that previously would have occurred in each individual function, and define the FLASH_STRING_ARRAY once locally in that function? Or...
Since the array itself will be RAM based to have a local array in each function that needs to access the data, which points back to the one set of globally defined FLASH_STRINGs (which I presume will all have to be individually defined and named for this to work)?
Or is there a 3rd simpler option?
The static data in question is 6244bytes comprising 104 individual character arrays of differing lengths.
I've used option (1). The function can be declared to return type _FLASH_STRING. Here is an example that stores names of locomotives in a model train control system, and returns one based on the index passed to the function:
// can't have flash string array in global scope, so use a function that defines the array and returns a _FLASH_STRING
// _FLASH_STRING is printable so can use in print statements
_FLASH_STRING locoName(byte staticID)
{
FLASH_STRING_ARRAY(locoNames,PSTR(""),
PSTR("WP F3 801"),
PSTR("WP 4-6-6-4 (Freight)"),
PSTR("CB&Q 0-8-0 543"),
PSTR("WP 4-6-6-4 (Expo Flyer)"),
PSTR("UP GP-7 (Freight)"),
PSTR("UP Alco PA"),
PSTR("SP GS-4 (Daylight)"),
PSTR("UP 2-8-0"),
PSTR("SF GP-38-2"));
return locoNames[staticID];
}
I've used option (1). The function can be declared to return type _FLASH_STRING.
Thanks so much PC! I had option 1 as unnecessarily complex, but of course this is far more elegant. That's what happens when you stare at a problem for too long
I'd have thought in this example though, wouldn't the array declaration cause these strings to be stored in PROGMEM each time its called? Or is Arduino clever enough to "unstore" them from flash somehow like the RAM variables that get created and destroyed each time a function is called?
Either way, my thoughts are now to try this with the FLASH_STRINGs defined with names s000 to s103 with global scope, and have the local array made up of them, and return the FLASH_STRING as you have there.
Thanks so much guys. Forging ahead again now, Geoff
strykeroz:
Either way, my thoughts are now to try this with the FLASH_STRINGs defined with names s000 to s103 with global scope, and have the local array made up of them, and return the FLASH_STRING as you have there.
Following some testing today I get a compiler error that the Initializer fails to determine size of '__c' when I try to pass FLASH_STRING variables to the FLASH_STRING_ARRAY declaration. I can't see any examples of doing it this way either, so suspect I was well wrong with that idea. Back to doing it the tried and proven Professor-Chaos-method for me