Forums

AVR Harvard architecture -- worst of both worlds?

Started by Everett M. Greene September 8, 2007
And we won't even get into Little-Endian vs. Big-Endian...

An "interesting" situation arises when dealing with constants in programs.
One would like to put these in ROM but with a Harvard architecture, one
can't access the locations as directly (if at all) as one can if the values
are in RAM.  Thus, one has to have either special functions to call to copy
the constants to RAM when needed or copy them to RAM at program initialization.
The latter runs the risk of the RAM location getting overwritten and the
constant not being as constant as one wishes.  The former adds a layer of
complexity and additional execution time to the programming that one would
just as soon avoid.

The AVR just adds to the problem by having word-oriented addressing for the
ROM space and byte-oriented addressing for the RAM space.  This makes life
especially "interesting" for linkers which have to be able to distinguish
between ROM and RAM addresses to perform the proper offset calculations.
On Fri, 7 Sep 2007 20:12:01 PST, mojaveg@mojaveg.lsan.mdsg-pacwest.com
(Everett M. Greene) wrote:

>And we won't even get into Little-Endian vs. Big-Endian...
Thank Bog!
>An "interesting" situation arises when dealing with constants in programs. >One would like to put these in ROM but with a Harvard architecture, one >can't access the locations as directly (if at all) as one can if the values >are in RAM. Thus, one has to have either special functions to call to copy >the constants to RAM when needed or copy them to RAM at program initialization.
I don't understand how it would even be possible to copy the constants to RAM if they can't be accessed "at all" when they are in the flash ROM. Good trick. But of course, all that's necessary is to use the "special function" [sic] which is really just another opcode (LPM) to fetch a constant from ROM into a machine register vice using LD to fetch a value from RAM. What's the big deal? Seriously.
>The latter runs the risk of the RAM location getting overwritten and the >constant not being as constant as one wishes. The former adds a layer of >complexity and additional execution time to the programming that one would >just as soon avoid.
Or just fetch directly from ROM when needed?
>The AVR just adds to the problem by having word-oriented addressing for the >ROM space and byte-oriented addressing for the RAM space. This makes life >especially "interesting" for linkers which have to be able to distinguish >between ROM and RAM addresses to perform the proper offset calculations.
Well, okay, but distinguishing between and managing the various code/data/bss/text/... segments is what linkers *do*.
> >The AVR just adds to the problem by having word-oriented addressing for the > >ROM space and byte-oriented addressing for the RAM space. This makes life > >especially "interesting" for linkers which have to be able to distinguish > >between ROM and RAM addresses to perform the proper offset calculations. > > Well, okay, but distinguishing between and managing the various > code/data/bss/text/... segments is what linkers *do*.
Indeed linkers do link various sections - this is what they do. But if one sections address increment is worth one byte and anothers - two bytes, things become a bit messy. I had to deal with that when I included a DSP which had a word based address space (16 bits per address); what I generally did was add a switch to the linker, once it saw one such - 16 bits per address - section it switches to this mode. There was more to it than that, it still had to be able to use ASCT symbols from either size etc., so the issue is not non-existant. Having said that, it was not a huge issue either, I don't remember having to wrestle it for too long (must have taken me < a week, 5-6 years back). Dimiter ------------------------------------------------------ Dimiter Popoff Transgalactic Instruments http://www.tgi-sci.com ------------------------------------------------------ On Sep 8, 5:15 pm, Rich Webb <bbew...@mapson.nozirev.ten> wrote:
> On Fri, 7 Sep 2007 20:12:01 PST, moja...@mojaveg.lsan.mdsg-pacwest.com > > (Everett M. Greene) wrote: > >And we won't even get into Little-Endian vs. Big-Endian... > > Thank Bog! > > >An "interesting" situation arises when dealing with constants in programs. > >One would like to put these in ROM but with a Harvard architecture, one > >can't access the locations as directly (if at all) as one can if the values > >are in RAM. Thus, one has to have either special functions to call to copy > >the constants to RAM when needed or copy them to RAM at program initialization. > > I don't understand how it would even be possible to copy the constants > to RAM if they can't be accessed "at all" when they are in the flash > ROM. Good trick. > > But of course, all that's necessary is to use the "special function" > [sic] which is really just another opcode (LPM) to fetch a constant > from ROM into a machine register vice using LD to fetch a value from > RAM. What's the big deal? Seriously. > > >The latter runs the risk of the RAM location getting overwritten and the > >constant not being as constant as one wishes. The former adds a layer of > >complexity and additional execution time to the programming that one would > >just as soon avoid. > > Or just fetch directly from ROM when needed? > > >The AVR just adds to the problem by having word-oriented addressing for the > >ROM space and byte-oriented addressing for the RAM space. This makes life > >especially "interesting" for linkers which have to be able to distinguish > >between ROM and RAM addresses to perform the proper offset calculations. > > Well, okay, but distinguishing between and managing the various > code/data/bss/text/... segments is what linkers *do*.
"Rich Webb" <bbew.ar@mapson.nozirev.ten> wrote in message
news:2m95e3l7iuov2kte6sg48qe7g0o2t8sget@4ax.com...
> > But of course, all that's necessary is to use the "special function" > [sic] which is really just another opcode (LPM) to fetch a constant > from ROM into a machine register vice using LD to fetch a value from > RAM. What's the big deal? Seriously. >
The big deal is the lack of the universal *. You have to explicitly use the different kinds of pointers depending on where is the object. Those pointers can't be casted. It also creates a major mess when you have to use several levels of indirection; when the different levels are located in the different classes of memory. For that reason, the IAR EC++ for AVR tends to keep the constant static objects in RAM rather then in ROM. Vladimir Vassilevsky DSP and Mixed Signal Consultant www.abvolt.com
"Vladimir Vassilevsky" <antispam_bogus@hotmail.com> writes:

> "Rich Webb" <bbew.ar@mapson.nozirev.ten> wrote in message > news:2m95e3l7iuov2kte6sg48qe7g0o2t8sget@4ax.com... >> >> But of course, all that's necessary is to use the "special function" >> [sic] which is really just another opcode (LPM) to fetch a constant >> from ROM into a machine register vice using LD to fetch a value from >> RAM. What's the big deal? Seriously. >> > > The big deal is the lack of the universal *. You have to explicitly use the > different kinds of pointers depending on where is the object. Those pointers > can't be casted. It also creates a major mess when you have to use several > levels of indirection; when the different levels are located in the > different classes of memory. For that reason, the IAR EC++ for AVR tends to > keep the constant static objects in RAM rather then in ROM.
To expand on this, it means you can't e.g. put all your constant strings in flash and use standard library functions with them. There are special versions of the standard library functions what will accept these "program strings", but these are then incompatible with your strings that *are* in ram. It makes it very awkward to define things like menu tables. In principle I think these issues could all be hidden by the compiler, but unfortunately none of them seem to do this, even the commercial ones as far as I know. This is the main reason I now use ARM for new projects, unless the application is *very* small (in which case there won't be too many strings or complicate constant structures). (All the above refers to C, of course). -- John Devereux
Rich Webb <bbew.ar@mapson.nozirev.ten> writes:
> (Everett M. Greene) wrote: > > >And we won't even get into Little-Endian vs. Big-Endian... > > Thank Bog! > > >An "interesting" situation arises when dealing with constants in programs. > >One would like to put these in ROM but with a Harvard architecture, one > >can't access the locations as directly (if at all) as one can if the values > >are in RAM. Thus, one has to have either special functions to call to copy > >the constants to RAM when needed or copy them to RAM at program initialization. > > I don't understand how it would even be possible to copy the constants > to RAM if they can't be accessed "at all" when they are in the flash > ROM. Good trick.
I've worked with at least one CPU in the past that had no access to the code space at all.
> But of course, all that's necessary is to use the "special function" > [sic] which is really just another opcode (LPM) to fetch a constant > from ROM into a machine register vice using LD to fetch a value from > RAM. What's the big deal? Seriously.
You left out the steps of having to load the ROM address into the Z register, execute the LPM instruction, and then move the fetched value to where you want it if you want it somewhere other than R0. You have to move the value if you're dealing with a multi-byte entity.
> >The latter runs the risk of the RAM location getting overwritten and the > >constant not being as constant as one wishes. The former adds a layer of > >complexity and additional execution time to the programming that one would > >just as soon avoid. > > Or just fetch directly from ROM when needed?
And how do you pass by reference?
> >The AVR just adds to the problem by having word-oriented addressing for the > >ROM space and byte-oriented addressing for the RAM space. This makes life > >especially "interesting" for linkers which have to be able to distinguish > >between ROM and RAM addresses to perform the proper offset calculations. > > Well, okay, but distinguishing between and managing the various > code/data/bss/text/... segments is what linkers *do*.
With quite some difficulty.
Everett M. Greene wrote:

> And how do you pass by reference?
The same way C compilers for RAM-constricted Harvard architectures have done it since day one: have the C compiler add a special flag to generic pointers that indicates whether they point at RAM or ROM, and use it accordingly. Memory class-specific pointers (i.e. the 'code' keyword) then offer a significant speedup over those, but the rules of C pretty much require one of the following for generic pointers to const data on a Harvard: 1) an "intelligent" pointer implementation (the CPU may help here, by keeping code and data in numerically separate address ranges) 2) copying const data from code to data space at boot-up (losing the physical immutability) 3) mapping const from code into data space by memory access hardware (MMU, address decoding logics)
Everett M. Greene wrote:
> I've worked with at least one CPU in the past that had no access to > the code space at all.
You might want to rephrase that statement! :) A CPU with "no access to the code space at all" cannot even fetch opcodes, and is thus going to be very easy to work with, as it is a paper-weight. -jg
Vladimir Vassilevsky wrote:
> "Rich Webb" <bbew.ar@mapson.nozirev.ten> wrote in message > news:2m95e3l7iuov2kte6sg48qe7g0o2t8sget@4ax.com... > >>But of course, all that's necessary is to use the "special function" >>[sic] which is really just another opcode (LPM) to fetch a constant >>from ROM into a machine register vice using LD to fetch a value from >>RAM. What's the big deal? Seriously. >> > > > The big deal is the lack of the universal *. You have to explicitly use the > different kinds of pointers depending on where is the object. Those pointers > can't be casted. It also creates a major mess when you have to use several > levels of indirection; when the different levels are located in the > different classes of memory. For that reason, the IAR EC++ for AVR tends to > keep the constant static objects in RAM rather then in ROM. >
Vladimir, this is a shortcoming of the C language. I know others that let the programmers treat RAM and ROM and EEPROM the same. Rene -- Ing.Buero R.Tschaggelar - http://www.ibrtses.com & commercial newsgroups - http://www.talkto.net
Rene Tschaggelar <none@none.net> writes:
> Vladimir Vassilevsky wrote:
>> The big deal is the lack of the universal *. You have to explicitly >> use the different kinds of pointers depending on where is the >> object.
...
>> the IAR EC++ for AVR tends to keep the constant static objects in >> RAM rather then in ROM.
> this is a shortcoming of the C language.
No, it's a shortcoming of some implementations of the C language. Nothing in the language requires that RAM and ROM share address space. HI-TECH Software (for example) have been doing C compilers for Harvard architecture machines for a very long time which manage to use 'const X *' as a "universal" pointer, able to refer to RAM or ROM objects with no extra work from the programmer. mlp (Yes, I'm currently employed by HI-TECH, but that's not relevant here - I'm defending the language, not pushing an implementor.)