IAR C-compiler for AVR: Array of pointers to strings in flash

Hi group!

Looking for help from someone with experience with IAR´s C-compiler for AVR (ATmega16/32)

I want to declare an array with pointers to constant text. And both of the should be in flash-memory, like this.

__flash char * __flash textTab[] = { "Text1", "Text2", "Text3", "Text4", "Text5", "Text6", "Text7", "Text8", "Text9", };

The array is easy to make in flash but the strings i cant manage. I managed to accomplish it by doing like this:

__flash char textText1[] = "Text1"; __flash char textText2[] = "Text2"; __flash char textText3[] = "Text3"; __flash char textText4[] = "Text4"; __flash char textText5[] = "Text5"; __flash char textText6[] = "Text6"; __flash char textText7[] = "Text7"; __flash char textText8[] = "Text8"; __flash char textText9[] = "Text9";

__flash unsigned char __flash *textTable[] = { textText1, textText2, textText3, textText4, textText5, textText6, textText7, textText8, textText9, };

But this is not sufficient bacause we need a LOT more texts.

Anyone got any idea?

//Erik

Reply to
Erik Cato
Loading thread data ...

AFAIK this is the only way. IAR does it this way, ICCAVR too.

Meindert

Reply to
Meindert Sprang

snipped-for-privacy@japro.se (Erik Cato) wrote in news: snipped-for-privacy@posting.google.com:

Doesn't const help here? I may have the second const in the wrong position.

const char * const textTab[] = { "foo", "bar", "baz" };

--
- Mark ->
--
Reply to
Mark A. Odell

You forgot to say how this approach failed.

This may just be a bug in that compiler's C extension keyword __flash, particularly in how it's parsed, or you may be missing something on how it's supposed to be used.

If you've seen the trouble people have in getting the usage of standard keyword "const" right in such multi-level pointer situations, you'll realize that getting this __flash thingy to parse exactly right may be tricky. You may have to expend a couple of parens, or a typedef, like this:

typedef __flash const char flashstring[];

__flash *flashstring = { /* ... */ };

--
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
Reply to
Hans-Bernhard Broeker

If you only define the array itself as const, and not the strings, only the array with pointers will be in rom or flash. The pointers are pointers to ram locations, where the strings are copied to from rom by the startup code.

Meindert

Reply to
Meindert Sprang

[snipped code placing char arrays explicitly in flash memory]

If you want to place string literals in flash memory, supply the command-line option --string_literals_in_flash to the compiler. But beware: it might not really solve your problem.

What are you going to do with all the strings? If you are going to write them out, you will have to recompile (parts of) the library to get a printf() version accepting pointers into flash memory.

Best wishes, Mats Kindahl

--
IAR Systems in Uppsala, Sweden.

Any opinions expressed are my own and not those of my company.

Spam prevention: contact me at mNaOtSkPiAnM@acm.org or
mNaOtSs.kPindAahMl@iar.se, removing the *NO SPAM* from the address.
Reply to
Mats Kindahl

There's a bug in the declaration, it should write:

char __flash * __flash textTab[] = ....

or __flash char __flash * textTab[] = ...

(I know, this is really confusing.)

The reason is that writing a memory attribute first on the line associates this memory attribute to every variable being declared (for pre-ANSI backward compatability reasons). The warning message emitted is something about "char const *" not being convertible to "char __flash *" (not very surprising, they are in completely different address spaces).

The problem is a result of the fact that, according to the ANSI standard, generic pointers have to be able to point to string literals and generic pointers cannot point to flash memory.

Best wishes, Mats Kindahl

--
IAR Systems in Uppsala, Sweden.

Any opinions expressed are my own and not those of my company.

Spam prevention: contact me at mNaOtSkPiAnM@acm.org or
mNaOtSs.kPindAahMl@iar.se, removing the *NO SPAM* from the address.
Reply to
Mats Kindahl

Thanks for the answer although it was incorrect!

I lookad at some tech. notes at iar.com and found out that you can this with the command line option --string_literals_in_flash

//Erik

Reply to
Erik Cato

Let's first note that ANSI/ISO C specs obviously say nothing about flash memory.

Now, if the compiler does implement an extension like this __flash, but does not also implement generic pointers in a way that they *can* point at it, that's IMHO at least a serious misfeature of the compiler. It's not strictly a bug for the only reason that this whole issue is outside the domain of the standard, i.e. the implementor can technically do whatever they please about it.

Such a situation effectively means that "pointers to flash" are not actually "pointers" (as defined by the language) at all. Just about every usage of such pointers could go fatally wrong, then, for lots of crazy, hard-to-find reasons.

The language specs go to quite some length to make sure that generic pointers can be implemented including a "memory class specifier", if the target platform needs that. Not making use of that flexibility is somewhat wasteful.

--
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
Reply to
Hans-Bernhard Broeker

Let me guess, you have never written a compiler for the embedded market for use by embedded engineers? :-)

With all due respect, having the flexibility by the standard is nice. However, implementing a generic pointer requires the pointer to be larger than 16 bits, and runtime check to see what type of a pointer it is, thus blowing up resulting code's FLASH and RAM requirements and make things run slower.

-- // richard

formatting link

Reply to
Richard F. Man

Neither char __flash * __flash textTab[] = .... or __flash char __flash * textTab[] = ... did work but with the commandline option --string_literals_in_flash it did.

We are writing special functions for displaying text so there is no need for printf.

//Erik

Reply to
Erik Cato

Correct; that's why it's not very practical (or nice) to place all string literals in flash memory by default (but, as I mentioned, you can pass the --string_literals_in_flash to the compiler to get this behaviour).

I can't see your reasoning behind this: how could using pointers to flash (or any other specific memory) go fatally wrong in "just about every usage"? There's nothing magic or strange about flash memory, it's just in another address space.

You can have pointers to flash memory: the problem is about having

*one* (i.e., generic) pointer that can point to flash memory *and* to "static" *and* to "auto" memory at the "same" time.

Consider:

char const __flash my_string[] = "Hello World!";

int main() { static char const static_string[] = "This is a string in static memory"; char const auto_string[] = "This is a string in auto memory";

char const* ptr = my_string; puts(ptr); ptr = static_string; puts(ptr); ptr = auto_string; puts(ptr); }

The pointer 'ptr' cannot point to all three memories. Of course it is possible to "tag" the generic pointer with extra information about the memory, effectively extending the address space, but that is impractical and wastes loads of memory for no obvious benefit (except, perhaps, academical benefits).

...and tagging every pointer in a program with the memory class is definitely wasteful; esp. since there is no problems at all having pointers to flash memory as long as you *treat* them as pointers to flash memory.

Best wishes, Mats Kindahl

--
IAR Systems in Uppsala, Sweden.

Any opinions expressed are my own and not those of my company.

Spam prevention: contact me at mNaOtSkPiAnM@acm.org or
mNaOtSs.kPindAahMl@iar.se, removing the *NO SPAM* from the address.
Reply to
Mats Kindahl

[snip]

Sorry, I was unclear. What I meant was that the original declaration did not declare the right kind of array. You have to change the declaration *and* add the command line switch.

Then you will have no problems (in this regard, at least).

You do know that you can reuse the printf() implementation if you need more advanced printing? It can also be configured to exclude some support that is not needed (for example, printing floating-point numbers).

Best wishes, Mats Kindahl

--
IAR Systems in Uppsala, Sweden.

Any opinions expressed are my own and not those of my company.

Spam prevention: contact me at mNaOtSkPiAnM@acm.org or
mNaOtSs.kPindAahMl@iar.se, removing the *NO SPAM* from the address.
Reply to
Mats Kindahl

Give me the compilers Mats and Richard design any day. I don't want to halve my profit margin on a $30 product because I need a bigger processor to accomodate abstract compiler aesthetics. That would drive me back to assembler. Give me more time and space utilisation optimisations (Richard...give me cases on byte expression and jump table based cases).

Cheers, Alf

--
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.576 / Virus Database: 365 - Release Date: 30/01/2004
Reply to
Unbeliever

--- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system

formatting link
Version: 6.0.576 / Virus Database: 365 - Release Date: 30/01/2004

Reply to
Unbeliever
[snip]

I got slapped on the fingers by the maintainer of the AVR compiler: I had got things completely wrong.

This is not an issue about generic pointers. You can declare a generic pointer using the __generic attribute, and a generic pointer can point to any memory, including flash memory.

This has to do with an issue about the *default* data memory pointer (for the particular memory model in this case) is unable to point to flash memory.

Sorry about all the confusing comments.

Enough said about this, Mats Kindahl

--
IAR Systems in Uppsala, Sweden.

Any opinions expressed are my own and not those of my company.

Spam prevention: contact me at mNaOtSkPiAnM@acm.org or
mNaOtSs.kPindAahMl@iar.se, removing the *NO SPAM* from the address.
Reply to
Mats Kindahl

Erik Cato schrieb:

Hello,

const char *const video_mode[8] =3D { "Live-Videobild" , "alle 4 Proben 1:2 verkleinert" , "alle 4 Proben 1/4 Bildhoehe" , "Vollbild Probe 1" , "Vollbild Probe 2" , "Vollbild Probe 3" , "Vollbild Probe 4" };

did work with Keil C166 for the 80c166. Both the pointers and the strings itself reside in Flash memory.

Sorry for the german words in the example, but this I had tested and read= y.

Bye

Reply to
Uwe Hercksen

Written one: no. Used one, though, and I actually do think I understand enough of the underlying issues to be allowed to speak up here.

It only makes slower if and where it gets used, of course. The issue I'm debating here is not whether pointers specialized to a single memory should exist --- on these architectures, they rather obviously have to.

I'm debating whether a "generic" pointer type deserves being called that if there are some addressable objects out there it can't point to. And whether the default pointer type, i.e. the one whose behaviour _is_ covered by the C standard, should be such a truly generic one, or one that is tied to one of the memory classes. My view is that the answers to these are "no" and "yes", in that order.

And BTW, I have indeed seen at least one compiler that did a better job, IMHO, in this area than the ones being discussed here: Keil C51, where a pointer without a memory class specifier is a generic pointer, and it truly is generic. The code size increase can be kept quite reasonable at the expense of some helper functions in the runtime lib, and the speed loss is for the programmer to decide about --- he has to decide whether he needs the gain in flexibility badly enough to justify it or not.

--
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
Reply to
Hans-Bernhard Broeker

No, I didn´t know this. How? Can you point me to where i can find more info in this issue.

//Erik

Reply to
Erik Cato

... snip ...

Ignoring specific hardware, the general approach of segmentation can pay off here. Consider a machine with 16 bit entities. For pointers, we could designate 3 of those bits to specify one of eight segment registers, each of which in turn specifies a storage area and base location therein. The remaining 13 bits in the pointer can specify an offset of up to 8191.

--
Chuck F (cbfalconer@yahoo.com) (cbfalconer@worldnet.att.net)
   Available for consulting/temporary embedded and systems.
     USE worldnet address!
Reply to
CBFalconer

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.