views:

2299

answers:

15

Related to:

If you are writing code for a microcontroller is there a real difference if you write in assembly or C or some other high level language? If you wrote C code, how would you compile it?

Thanks

+2  A: 

Assembly can in many cases be faster; when you're on a desktop, the compilers tend to be optimized to the point that hand assembly is rarely a necessity, but in the uC world, it often is. Also, if you need to write interrupt handling routines and things like that, you often can't do it in C.

As for compilation, google around for a C compiler for your target.

Cody Brocious
Compilers designed for embedded micros (eg IAR) tend to have all the trick you'll need for writing interrupt handlers.
Roddy
+17  A: 

Most microcontroller manufacturers provide some sort of cross-compiler where you can compile the code on your PC and then transfer it over to the microcontroller.

Why C?
An advantage of C is that your code will be easier to port to other microcontrollers in the future. The history of computing has shown that code typically outlasts hardware implementations.
A second advantage is control structures (if, for, while) that make code more readable and maintainable.

Why Assembly Language?
You can hand craft optimizations.

Verdict
As is often the case with this sort of question, the trade-offs are very dependent on the specific use.
Be aware that it is often possible to mix the two by making assembly calls within C code, so you can find a balance that is right for your project.

Specific to the PIC hardware
It seems that you don't have the option of GCC with most PIC hardware. On the other hand, as a commenter noted, the Microchip C30 compiler for the 16-bit PIC24 and dsPIC33 is gcc.
PIC is also not yet supported by SDCC.
New Info: according to a comment, SDCC has workable support for PIC.
There are some other open source options, but I don't have experience with them.

John Mulder
and you can use assembly within C if you want
Joe Philllips
That is what I was trying to say in the last sentence. I'll make it more explicit.
John Mulder
The Microchip C30 compiler for the 16-bit PIC24 and dsPIC33 is gcc.
Doug Currie
it's gcc but they don't include the C++ part :(
Jason S
+1 for mentioning SDCC
Jason S
SDCC port to PIC is available: "Work is in progress on supporting the Microchip PIC16 and PIC18 series. " It actually works well right now in the current build. Even though it's not considered "complete" people are using it for commercial products.
Adam Davis
?! PIC16 seems so old-school and crippled by lack of C-friendly features; last I checked the price differences between more modern PIC families was rather small. I wonder why they chose to aim at PIC16 (and maybe PIC18 for that matter) instead of PIC24, PIC30, etc.
Jason S
Oops, my bad -- a quick check on Mouser shows the lowest cost parts are all in the PIC16, PIC10, PIC12 families.
Jason S
+4  A: 

Best option is probably to code in C, and then for the very few instances where you need to hand optimize and can do a better job than the compiler, you should code the assembly into your c files.

Kibbee
+3  A: 

One issue I ran into with writing assembly for a microcontroller is the need to be very careful how your code was laid out. Having a jump table cross memory boundaries, and causing your code to jump to really weird places is rather disturbing. Coding in C, the compiler covers that base for you.

Harper Shelby
+4  A: 

I would definitely go with C. It is faster and it creates more reliable software. Assembly has very little to offer and in scarce occasions. Have in mind that in C:

  • You would be able to easily port code from existing platforms, even from PCs.
  • You can develop in a high level language without compromising execution speed or code size. Provided that a quality compiler is available (there are many choices for PIC18), these would be most probably be better with C than hand crafted assembly.
  • It is much easier to debug, test and maintain the code. C produces more reliable code.

Another thing that specifically has to do with PIC18. You won't have to deal with the non-intuitive PIC architecture and things like memory BANKs.

kgiannakakis
So, how would you compile your C code for the PIC 18? Any more info on this?
cbrulak
The better, but also more expensive compiler is the one from IAR. Other good choices are the Hitech compiler and Microchip's one, which is getting better.
kgiannakakis
+3  A: 

I've had good experience with IAR C compilers for 8051's in the past.

My recent approach has always been this:-

Write it in C with a good optimizing compiler, and ONLY THEN if there's a problem with size or speed, consider rewriting certain parts in assembler.

However, since taking this approach I've never needed to write a single line of assembler...

Roddy
+18  A: 

Several comments:

1) Absolutely not assembly unless performance or optimization constraints warrant it. The following metrics go through the roof with assembly:

  • time to code it
  • time to debug it
  • time to test it
  • time to document it
  • time to figure out (1 year later) what it was you were doing when you coded it
  • chances of making a mistake

2) My preference would be C++ rather than C for its namespace encapsulation & its facilitation of compile-time object-oriented practices. C has too many opportunities for global variables and namespace collisions. (Real-time Java would be nice but from what I understand its requirements are still pretty high)

Or rather a subset of C++: Exclude exceptions, virtual functions, run-time type identification, also dynamic memory allocation in most cases -- basically anything that's left unspecified at compile time, as it will usually require a lot of extra resources during runtime. That's the "bloat" of C++.

I have used both TI's and IAR's compilers for C++, for the TMS320 and MSP430 microcontrollers (respectively) and with proper optimization settings, they do a fantastic job of reducing the overhead you might expect from C++. (Especially if you help it out by judicious use of the inline keyword)

I have even used templates for some of their compile-time benefits which promote good code reuse: e.g. writing a single source code file to handle 8-bit, 16-bit, and 32-bit CRCs; and compile-time polymorphism to allow you to specify the usual behavior of a class, and then reuse that but override some of its functions. Again, the TI compiler had an extremely low overhead with appropriate optimization settings.

I have been looking for a C++ compiler for the Microchip PICs; the only company I've found that produces one is IAR. ($$$ has been an obstacle but I hope to buy a copy sometime) The Microchip C18/C30 compilers are pretty good but they're C, not C++.

3) A specific caveat about compiler optimization: it can/will make debugging very difficult; often it's impossible to single-step through optimized C/C++ code and your watch windows may show variables that have no correlation with what you think they should contain with unoptimized code. (A good debugger would warn you that a particular variable has been optimized out of existence or into a register rather than a memory location. Many debuggers do not. >:(

Also a good compiler would let you pick/choose optimization at the function level through #pragmas. The ones I've used only let you specify optimization at the file level.

4) Interfacing C code to assembly: This is usually difficult. The easiest way is to make a stub function that has the signature you want e.g. uint16_t foo(uint16_t a, uint32_t b) {return 0; }, where uint16_t = unsigned short, we usually make the # of bits explicit. Then compile it and edit the assembly it produces (just make sure to leave the begin/exit parts of the code) and be careful not to clobber any registers without restoring them after you are done.

Inline assembly usually can have problems unless you are doing something very simple like enabling/disabling interrupts.

The approach I like best is compiler intrinsics / "extended ASM" syntax. Microchip's C compiler is based on the GNU C compiler and it has "extended ASM" which lets you code bits of inline assembly but you can give it lots of hints to tell it which registers/variables you are referencing and it will handle all the saving/restoring of registers to make sure your assembly code "plays nice" with C. TI's compiler for the TMS320 DSP doesn't support these; it does have a limited set of intrinsics which have some use.

I've used assembly to optimize some control loop code that got executed frequently, or to calculate sin(), cos(), and arctan(). But otherwise I'd stay away from assembly and stick with a high-level language.

Jason S
Agreed mostly, but I don't think you need to exclude the use of virtual functions. The runtime overhead is very minimal, and less than the work-arounds you'd probably do instead of using virtual functions (like managing your own function pointers), and more importantly, VFs are less confusing to fellow programmers than whatever scheme you'd roll yourself.IMO, I'd exclude templates before virtual functions. Templates themselves are okay, I've just seen them misused so often I reflexively cringe when I think of them.
KeyserSoze
Bump for IAR compilers suite. I like quantum leaps too. http://www.state-machine.com/index.htm
GregC
+3  A: 

Go for c !

I've worked for a large CE manufacturer. The last time I saw assembly was there was around 1996 in some small interrupt services routines for RC5 and RC6 decoding and TV tuning algorithms. After that always used c, and C++ (only used classes, no stl, exceptions or rtti). I have good experiences with the old KEIL compiler for 8051 and with greenhills compiler (MIPS) and the VxWorks toolset (PowerPC based).

As Roddy says, first write in C , and optimize in assembly later (if needed).

RoccoD
A: 

That is the bottom line if you use C you can hand optimize later, I wouldnt use anything other than C or assembler (no C++, etc).

The key is the microcontroller instruction set if you are using a PIC or even an 8051 I would use assembler only. If it is a compiler friendly isa like arm or avr or msp430 then use C to save some typing but you will probably have some routines in assembler for various reasons. Likewise you probably want to avoid a C library, even newlib can be just too bulky, borrow code or ideas from them but dont just link one in. Oh, back to the question, look at what C compilers are available for the target, again arm and avr you wont have any problems. Likely msp is okay as well. Just because Keil or Iar will SELL you a compiler doesnt mean you should buy it or use it, the output of pay for as well as free compilers can be dreadful. You need to be well versed in the asm anyway and examine the output (you probably have to write a disassembler to do this).

Bottom line (another bottom line), there is no global answer (well avoid anyhthing higher than C is a global answer) it always depends on what the platform is what your resources are what your task is what the performance requirements are what the portability requirements are (if it is truly embedded on a microcontroller much of it is by definition not portable) what compilers, debuggers, jtag, etc are availble, even so far as what host operating system are you developing on can be a big factor.

dwelch
+1  A: 

There is one other time when writing in assembly may be necessary: if you need to do some low-level RAM test or similar, which requires absolute control over where data is being stored.

For example, software which confirms to SIL-2 (Safety Integrity Level) and above may require continual checks on RAM, in order to detect any possible data corruption. The area of RAM you're checking can't be changing while it's being checked, and so writing the test in assembler allows you to ensure that this is true, for example by storing any local variables in specific registers or in another area of RAM. This would be difficult, if not impossible, in C.

Startup code which zeroes the RAM and initialises non-zero static variables may also be written in assembler for the same written, though this sort of code is normally provided.

Steve Melnikoff
+1  A: 

If you're writing code that is highly dependent on device-specific peripherals, and the tool chain you're using doesn't provide the necessary intrinsics to utilize them efficiently (like the crappy Freescale DSP563CC compiler), then use assembly.

Besides that, I think the unwritten rules of using assembly vs. a high-level language are more or less the same as those for desktop software development: keep the code clean, maintainable, and optimize hot code with machine language.

switchmode
A: 

It is too bad no one has mentioned Forth or Scheme so far. Both can be appropriate for small environments, and can give impressive productivity gains.

Jeff Allen
+1  A: 

Definitely C, except when

  • program memory is extremely limited. Say after painstaking hand-optimizing your assembler code you manage to fit your program in this 1024 bytes of Flash, with 0 bytes left. In this case no C compiler will be any good.

  • you want to have absolute timing control. If any amount of interrupt latency is too long you'll have to rely on assembler.

stevenvh
+1  A: 

Assembly coding is a thing of the past for PCs, but is very relevant in embedded.

Writing assembly in embedded is different than writing assembly on PCs. PC compilers are "better than humans" at generating optimized instructions. Embedded systems often have weird architectures, and their optimizing compilers are not nearly as mature as a PC optimizing compiler.

Dustin Getz
A: 

Plain C or Pascal, Modula2. But due to compiler availability that means C.

The extra's of C++ and similars are only interesting out of style grounds, since dynamic allocation and program size is usually very limited.

Also a more complicated runtime can be a pain if your apps get tight.

Assembler can be useful too, but only if you sell really gigantic quantities, and a smaller firmware means a smaller, cheaper chip (less flash) and the program's size is overseeable (read: there is some chance that you will get it bugfree in time)

Marco van de Voort