EmbeddedRelated.com
Forums

mixing C and assembly

Started by Lax April 22, 2008
Lax wrote:
> Are there any situations where programming an embedded processor > "requires" at least some assembly code?
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.
> How about for AVR, MSP430, 68HC11, 8051(Atmel)? > Can these 4 microcontrollers be programmed fully in C without touching > assembly (even interrupts and etc.)?
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.
Walter Banks wrote:
> > Vladimir Vassilevsky wrote: > >> 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, > > 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 > http://www.bytecraft.com > walter@bytecraft.com > > > > > >
Do not forget the startup code
Lax wrote:
> 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.)?
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.
In message <fulm9l$r16$02$1@news.t-online.com>, Hans-Bernhard Br&#4294967295;ker 
<HBBroeker@t-online.de> writes
>Lax wrote: >> Are there any situations where programming an embedded processor >> "requires" at least some assembly code? > >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. > >> How about for AVR, MSP430, 68HC11, 8051(Atmel)? >> Can these 4 microcontrollers be programmed fully in C without touching >> assembly (even interrupts and etc.)? > >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.
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 /\/\/\/\/ \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
Chris H wrote:
> In message <fulm9l$r16$02$1@news.t-online.com>, Hans-Bernhard Br&#4294967295;ker > <HBBroeker@t-online.de> writes >> Lax wrote: >>> Are there any situations where programming an embedded processor >>> "requires" at least some assembly code? >> >> 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. >> >>> How about for AVR, MSP430, 68HC11, 8051(Atmel)? >>> Can these 4 microcontrollers be programmed fully in C without touching >>> assembly (even interrupts and etc.)? >> >> 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. > > > 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 >
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.
> 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!
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).
> > 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. >
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.
> 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. >
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.

Neil wrote:

> Walter Banks wrote: > > > > Vladimir Vassilevsky wrote: > > > >> 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. > > > > > 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. > > > > > Do not forget the startup code
Our startup code is in C. w..

Chris H wrote:

> 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.
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 http://www.bytecraft.com walter@bytecraft.com

David Brown wrote:

> 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.
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 http://www.bytecraft.com walter@bytecraft.com
Walter Banks wrote:
> > David Brown wrote: > >> 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. > > 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. >
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
In article <480F2B12.69B62031@bytecraft.com>, walter@bytecraft.com 
says...
> > > Chris H wrote: > > > 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. > > 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, >
Just out of curiosity, how do you set the initial value of the stack pointer in C? Mark Borgerson