Hi all
I have experience with Assembler programming on embedded system, and now going to learn some C embedded programming.
Can anyone recommend some good books?
Thanks
Je-Rock
Hi all
I have experience with Assembler programming on embedded system, and now going to learn some C embedded programming.
Can anyone recommend some good books?
Thanks
Je-Rock
Kernighan & Ritchie 2nd edition. The End.
Differences: - Avoid the heap. Embedded and heap are tricky bed-partners. - File I/O is usually irrelevant. Not always; usually. - putchar, printf, getchar (etc) are provided by user-supplied routines, often using serial comms. - Hardware I/O will again be user-supplied. (Avoid bit-fields; use masks.) - You'll have more control over physical placement in memory, and you'll need to understand the compiler-specific directives that place things. - As always, use module scope as a means of decoupling, and avoid global variables where possible. - Otherwise, C is C.
Must dash. Someone is playing "Freebird" in my kitchen.
Steve
In article , Steve at fivetrees writes
I think I'd make that clearer for the less experienced reader by saying "avoid C bit-fields", not to be confused with bit types in some C compilers that allow generation of code that uses the underlying bit addressing instructions offered by some architectures - something which is highly recommended for efficiency.
If I am not mistaken, K&R2 doesn't cover C99 which has lots of good stuff (var-sized arrays, designated initializers, to name a couple). Is there a decent C99 text? Please, share.
- Ark
c99 is irrelevant for embedded work. There are not any compilers that implement c99. That includes compilers who do use a C99 compliant front end.
Embedded compilers work around C95. K&R 2nd Ed is what most people used before there was anything better. In the intervening 15+ years since it was published the language has moved on there are many better books.
For embedded you will probably need a book that is chip specific as the compilers for most embedded work have many extensions that are requir4ed to make good use of the hardware.
-- \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ \/\/\/\/\ Chris Hills Staffs England /\/\/\/\/
Sorry, I must remember to remove all the C99 stuff from my code, since my compilers apparently don't support it. I can't imagine how I've managed to persuade a range of embedded compilers to accept things like // comments, or mixing declarations with statements and other such C99 features. And I'll have to cut out all my "static inline" functions and go back to good old macros.
Back here in reality, a lot of embedded compilers support most of the useful enhancements of C99. There are few (if any) that could claim complete C99 support, but in practise many C99 features are not needed in embedded systems.
But Chris is right that you need to read details for your specific compiler. There are always target-specific features (such as for hardware access, data in flash, interrupt routines, and inline assembly), and different compiler vendors have different general-purpose extensions (gcc, for instance, has a number of very useful extensions - using them makes the code non-portable, but perhaps smaller, faster, or easier to write).
Grow up.
There are VERY few ( I think 4) compilers that are C99 compliant. The rest work around C95 That is C95 with C99 few bits added. The // is one of the few things they all support. Though I have come across some differences on how they handle the line ends with defines and macros.
However depending on which compiler you have some support some bits of C99 others don't.
Those two well defined terms "most" and "useful" :-)
I think 4 do.
So they are not implemented and back to my original point that was you are better off looking at C95 and your compiler documentation for the extensions.
Yes... and C95 NOT C99.
-- \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ \/\/\/\/\ Chris Hills Staffs England /\/\/\/\/
An almost universally overlooked issue which alone calls for some C99: In the embedded world, we all use static const data structures, arrays in particular. This saves runtime initialization (speed and footprint) and RAM (footprint and, arguably, robustness). So, say foo[] in foo.c contains the good stuff and the useful indices into it are published in foo.h. The trouble is, there is no guarantee whatsoever that those indices remain correct in the course of maintenance (additions and deletions): nothing in the build will break. Instead of C
Huh?
I don't get it. If the indices are defined (once) in foo.h, foo.c *surely* depends on foo.h.
If they're defined twice, all bets are off. (Indeed, I'd fire the programmer, and find somone to write good code.)
Am I missing something?
Steve
Yes you are. In C
Why?
-Le Chaud Lapin-
Not if you do it the simple, naive way, right. But it's quite possible to get the C89 preprocessor to fix this problem for you, by a slight detour. So no need for C99 or yet another preprocessor:
foo_init.h: EXP(GOOD) EXP(BAD) EXP(INDIFFERENT)
proprecess this one with a definition of EXP that is
#define EXP(foo) INDEX_##foo
and let the result of this preprocessor run become part of foo.h:
enum { # include "processed_foo_init.h" };
or even do it in place:
#define EXP(foo) INDEX_##foo enum { #include "foo_init.h" };
In foo.c, #include foo_init.h again, but this time like this:
#define EXP(foo) foo const foo_t foo[] = { #include "foo_init.h" };
And that's before you consider that, if you're going to address the elements of that data structure by what is effectively a *name*, rather than by an actual computed number, then an array may not be the right data structure to begin with, and a struct would be in order.
-- Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de) Even if all the snow were burnt, ashes would remain.
Because it depends on the compiler how the elements of a bit field are aligned in memory.
I think it's sad that even 30 years after its invention C does not have a usable implementation of bit exact placement of variables. Compare Ada:
for SPI_Config use record CPOL at 0 range 0..0; CPHA at 0 range 1..1; CLKDIV at 0 range 5..10; end record;
...
SPI_Config := (CPOL => 1, CPHA => 0, CLKDIV => 4);
SPI_Config.CLKDIV := 4;
Their is a downloadable embedded C book on our website
"First Steps with Embedded Systems"
Walter Banks Byte Craft Limited
Je-Rock wrote:
Dear Banks,
Thanks very much for the book.
--shankar
Dear Banks,
Thanks very much for the book.
--shankar
Nor does it allow you to lay out other types of fields within structures. When I complain about that the proponents of C usually berate me for trying to do low level stuff in C. They seem to think it's a high-level application development language rather than a device-driver and hardware-bashing language. I think they're deluded. It's understandible that a language like Python wouldn't support user-specified bitfields or structures.
"C: it sucks at both high-level _and_ low-level stuff"
-- Grant Edwards grante Yow! By MEER biz doo at SCHOIN...
Parsing from the end: arrays were just an example: Structures have the same initialization problem if the (some) members have same types. Defining the same macro name differently is a cure much worse than the disease. All regulated industries prohibit this outright AFAIK. Same goes for file inclusion inside a statement. The mere fact that it is technically possible does not mean it's a good idea, like, say, letting a fart out on a job interview. Cf. Safer C and lots of other sources. All I was saying is C99 is not insignificant to be brushed off.
Regards, Ark
Hello Chris. You say you know of 4 C99 compilers..... lets list them here for the C. A. E. members. Imagecraft has a new C99 preprocessor for their family of compilers... AVR, HC12, ARM, MSP430. GCC has many C99 things like and 64 bit longs. Anyone add to the list?
... snip ...
Maybe I don't see the problem, but it sounds to me as if the definition of INDEX_GOOD doesn't belong in any .h file, but with the definition of foo[], right in the c source file. If other modules need access to those particular indexed entries, then they should do so via a function, again in the .c file, and that function can be propagated via the .h file.
static int foo[FOOSIZE]; enum foodex {FOOBAD, FOOGOOD, FOOINDIFFERENT};
int *foobad(void) {return &foo[FOOBAD]} etc.
Now all the .h file needs is prototypes for foobad and friends. The users can use:
if (*foobad(void)) .... or *foobad(void) = something;
and you can absorb the void etc in
#define BADFOO *foobad(void)
although I would recommend not doing so.
-- "If you want to post a followup via groups.google.com, don't use the broken "Reply" link at the bottom of the article. Click on
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.