Difference b/w Embedded C and General C

Go To Last Post
18 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Anybody please tel me what is the key difference between desktop C and Embedded C?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Absolutely NONE whatsoever. C is C is C.

Sure a desktop app might be invoked with argc and argv being passed in from a command line and at the very end it may return (usually an int) from main() and the OS would interpret this as an ERRORLEVEL but what happens in the middle and what you write in C is exactly the same.

The joy of C is that it is subject to an ANSI standard and, on the whole, all C compilers adhere to that standard so they all can be relied on to work in exactly the same way whether you are writing a stock control database on a PC or an LED flashing program on an AVR

(true you are probably less likely to find yourself using "|= (1<<mask)" and "&= ~(1<<mask)" to control individual bits in a PC app than you are in an embedded program - but bit level stuff and direct IO, ISRs etc are sometimes used on the PC too - that is, when you can get past the operating system going out of its way to stop you doing this kind of thing!)

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

While I agree with what Cliff said, there is one very slight difference in the way an embedded program operates (as opposed to how it's written). A program written for a desktop PC eventually terminates and returns to the operating system, whether it's Windows, Linux or whatever. Embedded systems are usually much smaller and rarely have an OS to return to. Thus they are written such that they loop forever and never terminate.

Dave

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dave,

But I said that didn't I? A PC program returns from main() eventually and usually returns an errorlevel to the OS to let it know how things went.

(while an embedded program must never return from main() because FAQ#2 says so! ;) )

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Language wise there is absolutely no difference, as Cliff already stated. There is a difference when you get to the 'standard' libraries. Some functions are not available, simply due to the fact that they can't be implemented without an underlying OS (some time functions for example), and others simply because they are too resource intensive for the resource limited embedded world. Overall support will vary depending on what platform you are targeting. On smaller systems like the AVR the library is more limited, than on larger systems. Though on Larger systems you may also be more likely to run an underlying OS as well.

As for the comment on 'structure', I don't see that as a real point, since a programs structure is all about the task at hand. A PC app could just as easily run in an endless loop, just as an embedded app typically does. Or your embedded app could exit main just like an app on a PC, the difference is in what happens after that. On a PC your return goes to the OS, in an embedded environment, where there is no OS, there is nothing to return to. As a result, in an embedded environment what happens after you exit main will vary depending on how the compiler writer decided to handle that condition. So usually an App runs in it's own endless loop. Also consider that an embedded application typically runs on it's own and is typically dedicated to performing a single real world task, as such there is no reason to ever return from the application.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
But I said that didn't I?

Ack! You're right - I read the reply but missed the FAQ lines at the bottom. On the other hand, I can barely read them on my monitor (1600x1200) - they almost look like an included graphic that has lost some resolution in the process.

Dave

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No I said the same in the text of the post too - but I guess it doesn't matter. I'm sure OP has got the point by now! ;)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The real difference is in how it is used. In general C you often model a real world situation. In embedded applications you are more often actually interacting with the real world (timers, ADCs, etc within the chip itself, as well as external hardware). This means that you have to have a somewhat different mind set when programming embedded applications and have at least a fair bit of familiarity with basic electronics. It also means that the compiler has to provide access to that real world hardware which you need to be aware of.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There are several big differences:

1.
µC compilers have an additional syntax to define interrupt handlers.
This is importand to react very fast on hardware events.
Thus some times a µC may work faster as a PC, even if it runs with only some MHz in opposition of many GHz of a PC.

2.
µC have often different memory spaces (EEPROM, code, data), so some µC compilers have special syntax for defining the memory segment or generic pointer to hide the segment structure and access all segments with the same syntax.

3.
µC need often to deal with single IO lines or hardware control bits, so some compilers have a special syntax to access and define bit variables.

Unfortunately all these extensions are not covered by the C standard and thus fully compiler dependent.

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One of the differences hinted at by danni has to do with memory.

In "desktop C", the program executes out of the same memory space as data. In embedded C, that is usually not the case. particularly at the 8 and 16 bit levels where it is (almost) never the case.

This diffeence appears mostly in the compiler and is generally invisible to the programmer. It only surfaces when you have to designate various memory spaces.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And you need to "think in assembler and write it in C" with micros, ie forget the way you use C in PC's. Of course you also have your friendly printf command that will fill some chips several times over, on it's own, unless properly adjusted to suit a micro.
Some of the gems I have learned here :)

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
In "desktop C", the program executes out of the same memory space as data. In embedded C, that is usually not the case. particularly at the 8 and 16 bit levels where it is (almost) never the case.

But that's only really true of the kind of unusal and "odd" Harvard architecture of the AVR. Most embedded micros programmed in C have the same Von Neumann architecture as desktop PC processors and are programmed in the same "one memory space" way. True at some of the address space you may have flash and at other parts SRAM/DRAM and others memory mapped IO. But it's still a single memory space model.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm with Cliff. C knows nothing about the underlying hardware, when you guys speak of the differences between general, or desktop or embedded C, you are talking about hardware not about the language. The C is the same no matter the memory architecture or construction. C is C on a Harvard device using SRAM or a Von Neumann device using mechanical relays. There is no difference in French spoken on the street or in a ships engine room, what is said will likely be very different, but the language is exactly the same. It is the use of the language that differs, not the language itself.

Smiley

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Absolutely NONE whatsoever. C is C is C.

Sure a desktop app might be invoked with argc and argv being passed in from a command line and at the very end it may return (usually an int) from main() and the OS would interpret this as an ERRORLEVEL but what happens in the middle and what you write in C is exactly the same.
Cliff

ok, what is the use of this ERRORLEVEL to the OS?
could you please explain this little bit more...
and also glif told that"

As for the comment on 'structure', I don't see that as a real point, since a programs structure is all about the task at hand. A PC app could just as easily run in an endless loop, just as an embedded app typically does. Or your embedded app could exit main just like an app on a PC, the difference is in what happens after that. On a PC your return goes to the OS, in an embedded environment, where there is no OS, there is nothing to return to"

if i am using RTOS in my embedded application then will embedded application return from main() func?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

On a PC a C program might do:

int main (int argc, char * argv[]) {
  if (argc==2) {
    printf("prog argument = %s\r\n", argv[1]);
  }

  return 5;
}

MS-DOS or Windows or Linux or CP/M or whatever the operating system is will read a command line such as:

C:\>myprog hello

and will then enter the main() of this program setting argc to be the number of parameters on the command line and each "word" split into an array of string pointers called argv[]. I can check whether there was a parameter passed in by checking the argc number and print it out using the argv[] array. (argv[0] will be "myprog" in fact). When I run this I'll see:

C:\>myprog hello
prog argument = hello
C:\>

What's more this program not only takes INPUT values handed to it by hte operating system from the command line but it can OUTPUT a value back to the operating system. When it ended with "return 5" it's saying "here MS-DOS/Windows/Linux/... I have stopped running and the output of the program is "5".

In MS-DOS/Windows this value then gets automatically loaded into an environment variable called ERRORLEVEL that you can then check in a batch file (or even at the command line) so I could:

C:\>myprog hello
prog argument = hello

C:\>echo.%errorlevel%
5

C:\>if errorlevel 8 echo yes

C:\>if errorlevel 5 echo yes
yes

C:\>

You often find errorlevel used in the form 0=program worked 1=program failed. For example if you even use:

C:\>avr-gcc working.c
C:\>echo.%errorlevel%
0
C:\>avr-gcc notworking.c
C:\>echo.%errorlevel% 1

So operating system programs have inputs (from the operating system) and they eventually complete running and have outputs (to the operating system) when they hit the final "return" (or just the closing brace } of main in which case 0 will be returned if no specfici value has been given in an "return" statement).

Now, over in the embedded world things are quite different. When you apply power to your AVR it jumps to location 0 and starts to execute from there. The C program you've written will have arranged for that to be a jump straight into some C "pre-amble" where the C compiler will set things into a known state (in fact most of this will be on the start of that OS launched program above too). It will then enter your code at main() but as there's no "operating system" and no way the user could have invoked the program from a command line such as "myprog hello" there is no way there could be argc or argv[] values to be passed into the C program. Equally, because it has not been launched by an operating system it does not have anywhere to return to. If you made the stupid mistake of letting it execute a "return" statement in main() or get as far as the closing brace of main() then where could it go to - nothing launched it (entry was by a jump from 0) so where can it return to? To be helpful a lot of C compilers for embedded catch this mistake and provide a tight "while(1)" loop just beyond main() so if you return it won't just pop a return address off the stack and go on through memory executing rogue code that is really just any old rubbish left in the flash. But instead it'll begin executing a tight one opcode loop ("rjmp .-2") for the rest of time.

This is why all embedded programs usually have an infinite loop of some sort at the end of main() (often doing the "main work" of the application for ever more or at least until power is removed).

Now by a strange quirk (because the C standard says that main() should always return an int value) the prototype for main() in avr-gcc is actually:

int main(void)

The 'void' is saying that tere'll never be any argc/argv input to the program but the int is saying "if it ever leaves it should return an integer value". As above, if you don't explicitly generate a "return 0" (but which should NEVER be executed) the compiler will generate code to do it for you anyway.

Oh and if you have an RTOS on a micro like an AVR then the core of the RTOS itself is no different to the main() I just described. Nothing will be passed in when it starts and it will NEVER stop running until power is removed (so it's main() is effectively an embedded program). HOWEVER what an RTOS does for you is effectively let you then run a number of "small C programs" side by side (aka "tasks") and each of these will effectively have their own main() (usually called the "task function"). Now these "sub programs" could have values passed into them by the RTOS (after all it IS an operating system like CP/M, MS-DOS, Linux etc) so it may well fill in some argc and argv values as entry passes into any of those task functions and equally, while most tasks in an embedded system are usually written (like a main embedded program) to never stop running it is quite possible that the task can complete and return from the task function, maybe even returning a value to the RTOS that called it to say how things went.

At the end of the say (apart from limited resources) there'd be nothing to stop you writing/running an operating system like MS-DOS or Linux on an AVR and it could have a "C:\>" style command prompt and allow you to "launch programs" and then see the result of them through a returned error level. IN fact if you think back to CP/M it was the precurosr to MS-DOS on the 8086 and was run on Intel 8080 and Zilog Z80 processors and often in as little as a few K of flash or RAM. So it's quite "do able" on an AVR (though the Harvard architecture is bound to "get in the way" a bit!)

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

prabu wrote:

if i am using RTOS in my embedded application then will embedded application return from main() func?

Yes, absolutely. But in order to do that you will have to build your own compiler, or at least modify the root environment that your compiler uses, so it knows how to accept parameters from, and return to your OS.

As it stands now, your compiler believes that the program it is compiling will be the only thing running, and there is nothing to return to. So the compiler adds it's own startup, and stop code. (this being the GCC forum, GCC enters into an endless loop if you were to exit) you will need to change that behaviour. Also the C startup will need to be modified, as right now it expects that it has complete ownership of the uC, you will need to do this setup now in your OS, and the C startup modified to accept the "frame" that it has been handed by the OS to operate in.

It is far more complex than adding a simple "ret" at the end of your program.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One of the assumptions here is that the OP was talking about "embedded" as it applies to an AVR 8-bit processor.

"Embedded" can be as complicated as a PC (in fact, in some cases it is a "PC"!). A couple of years ago I was involved in an embedded project (a Personal Media Player/Recorder) that was running uCLinux on an ARM7. From an OS point of view, there was literally no difference from running on Linux on a PC. I had to be careful about how processes were run because there wasn't a memory manager (ARM7 doesn't have that), so no "virtual" memory or keeping tasks separate from one another by virtual space. In a sense, not much different from the old MacOS, pre-X days.

"Embedded" has come to mean anything other than a "general" processor (whatever that means). In an embedded environment, your system resources are different that in the general environment. (Different does not necessarily mean less -- sometimes embedded processors can have some pretty fancy resources at their disposal!) You must be more aware of those resources and how to use them.

I agree with Smiley -- C is C. It's how you use it that matters.

Stu

Engineering seems to boil down to: Cheap. Fast. Good. Choose two. Sometimes choose only one.

Newbie? Be sure to read the thread Newbie? Start here!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Stu,

Well I know what you mean. This is "one of mine":

and it's running a dual core TI OMPA5910 (150MHz ARM9 and 150MHz DSP) and on the ARM side it's running a full copy of Linux 2.4.18 with most of the UI being done as a user application (launched from a bash script in fact) with the hardware stuff done as kernel drivers (some in the kernel, some modprobe/insmod'd by the startup scripts)

But it's a pretty fair bet that anyone posting on this board (unless they got lost and were looking for the AVR32 section) are programming CPUs that cannot run a "real" operating system like this. In fact for anything below a 128 I would be very suspicious of anyone who thought they needed to use an RTOS of any sort on an AVR8

Cliff