Forums

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

Started by Erik Cato February 3, 2004
Mats Kindahl <mats.kindahl@nowhere.net> wrote in message news:<u3c9sno66.fsf@mail.iar.se>...
> erik.cato@japro.se (Erik Cato) writes: > > > Hi group! > > > > Looking for help from someone with experience with IAR&#2013266100;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", > > }; > > [snipped code placing char arrays explicitly in flash memory] > > > But this is not sufficient bacause we need a LOT more texts. > > 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
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
Hans-Bernhard Broeker <broeker@physik.rwth-aachen.de> writes:

> Mats Kindahl <mats.kindahl@nowhere.net> wrote: > > > 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. > > Let's first note that ANSI/ISO C specs obviously say nothing about > flash memory.
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).
> 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.
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).
> 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.
...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.
erik.cato@japro.se (Erik Cato) writes:

> Mats Kindahl <mats.kindahl@nowhere.net> wrote in message news:<u3c9sno66.fsf@mail.iar.se>... >> erik.cato@japro.se (Erik Cato) writes: >> >>> Hi group! >>> >>> Looking for help from someone with experience with IAR&#2013266100;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", >>> }; >> >> [snipped code placing char arrays explicitly in flash memory] >> >>> But this is not sufficient bacause we need a LOT more texts. >> >> 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.
[snip]
> Neither > char __flash * __flash textTab[] = .... > or > __flash char __flash * textTab[] = ... > did work but with the commandline option --string_literals_in_flash > it did.
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.
> We are writing special functions for displaying text so there is no > need for printf.
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.
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





---
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


Mats Kindahl <mats.kindahl@nowhere.net> writes:

[snip]

> 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.
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.

Erik Cato schrieb:
> Hi group! >=20 > Looking for help from someone with experience with IAR=B4s C-compiler > for AVR (ATmega16/32) >=20 > I want to declare an array with pointers to constant text. And both of > the should be in flash-memory, like this. >=20 > __flash char * __flash textTab[] =3D > { > "Text1", > "Text2", > "Text3", > "Text4", > "Text5",
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
Richard F. Man <richard@imagecraft.com> wrote:

> Hans-Bernhard Broeker wrote:
> > .... > > 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. > >
> Let me guess, you have never written a compiler for the embedded market for > use by embedded engineers? :-)
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.
> 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.
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.
Mats Kindahl <mats.kindahl@nowhere.net> wrote in message 

> >> 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.
> > We are writing special functions for displaying text so there is no > > need for printf.
> 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
No, I didn&#2013266100;t know this. How? Can you point me to where i can find more info in this issue. //Erik
Hans-Bernhard Broeker wrote:
>
... snip ...
> > 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.
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. <http://cbfalconer.home.att.net> USE worldnet address!