mixing C and assembly

Are there any situations where programming an embedded processor "requires" at least some assembly code?

How about for AVR, MSP430, 68HC11, 8051(Atmel)? Can these 4 microcontrollers be programmed fully in C without touching assembly (even interrupts and etc.)?

Reply to
Lax
Loading thread data ...

At least for AVR one can write pretty much everything using gcc and avr-libc. However, while writing "cli();" in your C program is not technically "touching assembly", it is not much different from including the cli instruction as inline assembly. It is more convenient, but still very much target dependent.

--
Pertti
Reply to
Pertti Kellomäki

Lax pisze:

IMO, generally it is possible, but sometimes C compiler doesn't optimalize code such good as you want. In this case you can write it in assembly language or change your approach to the problem.

--
Piotr Piwko
http://www.embedded-engineering.pl/
Reply to
Piotr

You have to resort to assembly in the two special cases:

  1. The system level work like switching the contexts of the tasks, C startup code, etc.
  2. The parts of code where the performance is very critical.

Other then that, everything can be done in C.

Vladimir Vassilevsky DSP and Mixed Signal Design Consultant

formatting link

Reply to
Vladimir Vassilevsky

I think that it should be possible, although as it has been said, compiler may not optimize your code properly, and you may have some lost o performance. You may try the asm directive of C as a solution to avoi writing a whole file in assembly code.

Good Luck!

Reply to
hectorhg

Usually.

Yes.

Sometimes. It depends on the toolchain and on the job to be done. Most toolchains provide C extensions to do things like interrupts and access special hardware features. If those extensions are sufficient for what you need to do, then you don't need to write assembly code. If they aren't, then you do.

--
Grant Edwards                   grante             Yow! ... or were you
                                  at               driving the PONTIAC that
                               visi.com            HONKED at me in MIAMI last
                                                   Tuesday?
Reply to
Grant Edwards

In every case where I've worked an embedded processor directly, I've had to at least initialize the environment so it could run C. Basically, setup the stack, clear RAM and jump to _main.

In cases where there's an OS on it already, and that has an applications hook, then it could have been done with only C. In some cases, however, it's been expedient to use some assembler.

I have no experience with the first two. For the last two, without an OS, yes. With an OS, for the 68HC11 I did for expediency, but could have avoided it, but for the 8051 I had to do some assembly. Perhaps selection of a different OS or development package would have made it possible to avoid assembler.

- Bill

Reply to
Bill Leary

There are always assembly involved somewhere, but you don't have to write them. Why are you re-inventing run-time libraries?

Yes for AVR, you can interrupt, sleep, powerdown and change clock speeds in C. The only assembly I have used is to load flash codes into data space, for which there is no C equivalent.

Reply to
linnix

Vladimir,

In your second point I would qualify it to parts of code requiring exact timing on anything that we have released recently that seems to be the only limitation.

Regards,

-- Walter Banks Byte Craft Limited Tel. (519) 888-6911

formatting link
snipped-for-privacy@bytecraft.com

Reply to
Walter Banks

For processors without an external bus (IOW they have a fixed memory map), many toolchains will provide startup code that does all that. That's certainly true for GCC on the Atmel AVR and TI MSP430: tell the compiler which part you're using, and you don't have to write a lick of startup code.

--
Grant Edwards                   grante             Yow! Did something bad
                                  at               happen or am I in a
                               visi.com            drive-in movie??
Reply to
Grant Edwards

Yes. Somebody, somewhere, some time, will have to write some assembly code. Startup code, low-level support routines for the C compiler, task switching support, ... that kind of thing.

It depends on just about every partner in the process (from chip designer to application customer) whether "somebody" includes you, the embedded software engineer.

That depends entirely on what one still considers to be "in" C, and how the tool makers chose to handle those features of an embedded controller that strictly pure standard C can't handle. E.g., ISRs could be mapped to the signal() mechanism of standard C. But hardly anyone ever actually does that. Instead, there are compiler extensions or assembly wrappers that link C functions to interrupts.

Reply to
Hans-Bernhard Bröker

Do not forget the startup code

Reply to
Neil

MAYBE

For many applications using small CPUs you do not need any ASM. There are situations where you do need it. Your code may vary.

Of the above I have used Keil 8051 C compiler. Many general apps did not need ASM.

Reply to
Neil

I agree... if you go to comp.lang.c you will find that Gcc is NOT C... it is a "C like language" as it is not a full C implementation and has Gcc extensions quite apart from extensions for the target

Also most compilers for embedded targets have many "assembler like" extensions eg where you can put hex directly into registers and peripherals. The "C" function to set up the UART on an 8051 with a Keil compiler looks almost the same as assembler!

As has already been mentioned the start up code has to be in assembler as it sets up the memory for the stack etc however if you use the standard one that comes with the compiler you will never need to see it. It is usually automatically pulled in as an object file.

That said you can program most of these micros in pure C with no extensions (compiler or targets) BUT it is usually very inefficient code and no one is likely to employ you if you do that.

--
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills  Staffs  England     /\/\/\/\/
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
Reply to
Chris H

gcc supports at least as high a proportion of C99 as the great majority of commercial compilers, and I don't know off-hand of any pre-C99 language issues. Just like all commercial compilers I am familiar with (I've used a few over the years), gcc has extensions which can be enabled or disabled. Some of these extensions are target-specific (such as for interrupt handling), others are target-independent (such as allowing certain C++ constructs in C, and vice-versa).

Since gcc has barely been mentioned in this thread, you must have good reason for bringing it up - surely it was not merely for gratuitous and unsubstantiated bashing (and surely it was not trolling for my reply, to re-establish our relationship after too many recent agreements :-)

Since you hang out gcc for not being "a full C implementation", and for having "extensions quite apart from extensions for the target", can you give me some examples of other available compilers that *are* "full C implementations" (along with an explanation of exactly what you mean by that phrase), which have *no* compiler extensions, and which are targeted at embedded systems?

Beyond the obsessive gcc-bashing, I pretty much agree with your post.

Embedded toolchains are pretty much useless unless you can get low-level access beyond what can be written in standard C with standard libraries, so there are normally either extensions to the compiler, or extra library functions (often just wrappers around embedded assembly).

Although the compiler and its libraries will often handle this sort of thing, it is sometimes useful to write it yourself. Sometimes you want to use different memory layouts from the standard ones, and sometimes you need board-specific low-level code at the start. For example, I have a card with external sdram - I needed to initialise the sdram before copying the program over from flash to sdram and running it there. I also have two separate sets of .bss and .data - one in the sdram, and one in fast internal ram. So I had a specific startup routine to handle that copying.

Depending on your tools, however, this sort of thing can often be written in C - even though your real C environment is not yet ready (for example, initialised data are not yet initialised, and for C++ your global objects are not yet constructed). I find that my assembly can often be reduced to two or three op-codes at the very start (if the toolchains standard startup code is not suitable), along with some embedded assembly macros or function wrappers for things like interrupt control, or accessing cpu-space registers on some targets.

You usually need to use your compiler's target extensions (for interrupts, if nothing else), unless you have a ready-made OS layer that handles that sort of thing for you.

For "general" C programming, it is rare that you can write significantly smaller or faster code using assembly than a good compiler will generate. This is especially true for big processors where manually tracking things like register allocations, pipelining, and instruction overlap will drive you up the wall - the compiler does this quickly and easily, and thus will generate better code than all but the most dedicated assembly programmers. Similarly, for very small and limited cpus, modern compilers can optimise things like bank switching and data placement better than a human can while still writing legible and maintainable code.

Compilers often have other extensions which *can* make a big difference, however. Extensions giving hints to the compiler ("inline" is often available as an extension when compiling for older C standards) can make the generated code smaller and/or faster. Extensions for source code, such as unnamed structs and unions, or flexible array types, can lead to clearer and neater source code. Obviously you must be aware of when such extensions make your code non-portable between targets and/or compilers - it's a tradeoff you have to evaluate.

The one place where compiler assembly-like extensions and/or real assembly can make a big difference is for dsp programming. Compilers are getting better at turning C loops into optimal dsp code, but in many cases you have to write something horrendous involving all sorts of compiler/target-specific pseudo-functions to end up with optimal assembly - writing in pure assembly is often clearer and neater.

Reply to
David Brown

Our startup code is in C.

w..

Reply to
Walter Banks

There is no requirement for the start up code to be in asm. A lot of compilers come with asm sample startup but the code could have been written in C in the same compiler. The same extensions that support embedded systems make this possible

Regards,

-- Walter Banks Byte Craft Limited Tel. (519) 888-6911

formatting link
snipped-for-privacy@bytecraft.com

Reply to
Walter Banks

In the area of DSP the single biggest change has been IEC/ISO 18037 which made it a lot easier to express DSP algorithms in C without using obscure syntax. The C source quickly became a lot easier to port between architectures. The biggest difference was clear way to simply express the data structure of the target processor. At the instruction level the compiler was responsible for mapping the C on the processors mac instructions.

Porting went from needing to rewrite the asm code for each target to changing declarations describing the data struct with a minor amount of tweaking.

There are other things in this C extension as well that normalized the definitions of fract and accum data types which cleaned up a way to represent data for DSP applications.

Regards,

-- Walter Banks Byte Craft Limited Tel. (519) 888-6911

formatting link
snipped-for-privacy@bytecraft.com

Reply to
Walter Banks

Once support fract/accum/sat becomes common in C compilers, then it will certainly make it easier to write legible, portable code working with scaled fractional integers. I seriously doubt that it will entirely remove the need for extensions and intrinsics to get optimal code from powerful DSPs, but it will certainly be a solid step in the right direction and will let you write close to optimal code for everything but the tightest of inner loops.

mvh.,

David

Reply to
David Brown

Just out of curiosity, how do you set the initial value of the stack pointer in C?

Mark Borgerson

Reply to
Mark Borgerson

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.