The named address spaces are quite new (as they are new to the C
standards). You can use them as alternatives to the "progmem" macros
and attributes - when you specify exactly which flash bank you are
using, they are approximately as efficient (depending on exact
optimisation details). You can also use a more general pointer that
covers all of flash and ram - but you pay for the flexibility in code
time and space.
Although I haven't used them myself (I haven't used the AVR for a new
project for quite a while, and I don't change tools for existing
projects), I think they are a nice idea. They are about as good a
solution as it is possible to get when using an 8-bit architecture to
address up to 512 KB flash.
>
>> Imagecraft had a different idea (at least when I used their AVR
>> compiler, which was a long time ago) - they made "const" mean "flash".
>
> I thought that was standard behaviour for embedded, e.g. I thought the
> gcc toolchains put constants into a read-only segment that the link
> script puts in flash.
gcc (in cooperation with the linker and linker scripts) will put /some/
types of consts into flash, depending on the architecture. But in C it
is valid to write code like this:
extern size_t strlen(const char* s);
size_t foo(void) {
char a[] = "Hello, world!";
return strlen(a);
}
I.e., you can cast a pointer to a non-const into a pointer-to-const.
This means that the implementation of "strlen" here cannot assume
anything special about the placement of "s" - it could be in flash, and
it could be in ram. For most architectures, assembly instructions for
pointer-to-ram and pointer-to-flash operations are the same, so there is
no problem. But on the AVR (and PIC, 8051, COP8, and many other small
micros), the operations are different. To be consistent, the
compiler/library implementer must choose either "fat" pointers with
their extra overheads, or assume that all normal pointers are to ram.
Thus on the AVR, "const" data must be allocated to ram - there is no
other way to be efficient and consistent.
The compiler will then give you some other method of declaring that a
particular piece of data is explicitly put in flash - such as "progmem"
and friends, or "__flash" named address spaces. And you use similar
compiler extensions to access said data. This is usually worth the
effort for strings, tables, etc., but not for small constants.
For targets that have a single unified address space (arm, msp430, most
32-bit processors), it is usually easy for the compiler to allocate
const data to read-only memory.
>
>> That let you write most C code in a natural way, and const data got put
>> in flash. But it meant that converting a non-const pointer to a const
>> pointer would cause disaster, which was a bad idea.
>
> I admit I under-use "const".
You should learn to love it. Values that don't change should be made
const - it lets the compiler do more checking for errors, and sometimes
also leads to better optimisation. Where possible, use "static const".
In particular, prefer "static const int maxValue = 100;" over "#define
maxValue 100" - as long as your compiler is optimising, it will generate
as good code and will have better static error checking. (You can't
replace /all/ macros this way - but do it when you can.) And any
function that takes a pointer to data but does not change that data
should const-qualify the pointer - it helps spot mistakes and can lead
to better object code.
>>>
>>> CM3 is so much nicer now for most things.
>>
>> Indeed.
>>
>> The msp430 is probably the smallest cpu the is /really/ C friendly.
>
> Yes never tried it but would look into it if needed something really
> small/low power. Everyone had nice things to say about it. I seem to
> recall it did not have a proper gcc port when I would have been in a
> position to use it last, so I went with ARM.
>
The msp430 has had a usable gcc port for many years, but it was arguably
not "proper" - it was outside the main gcc tree, and for a while it was
a long way behind mainline gcc. But thanks mainly to the efforts of
Peter Bigot, it has been solid - I have used it for many years. And now
TI has paid Redhat to make msp430 gcc a full member of the mainline gcc,
and to provide a complete toolchain and library package. This new
version is now available in beta, with integration in CCS.
Still, it must be said that the msp430 is only really C-friendly with
the devices up to 64K total memory (flash + ram + peripherals) - data
access beyond 64K means using 20-bit registers and that means messy
compiler-specific stuff. (You can access normal code over more than 64K
- it is only when you use pointers that addresses above 64K get ugly.)