views:

777

answers:

9

I am an embedded SW Engineer, with less than 3 yrs of experience. I aim to "sharpen the saw" continuously. I was wondering if there was anything specific to low level programming that C/C++ coders should be proficient with.

What comes to my mind is familiarity with the hardware's architecture and instruction set. Knowing how to fiddle with bits is also important, resource management and performance have been part of my job, is there anything else?

EDIT: I work with an in-house customized RTOS, not embedded Linux.

+8  A: 

I'd study the electronics of the actual chips. Learn how they work internally (such as architecture), interface with peripherals, electrical and timing characteristics, etc.

Basically, read the data sheet start to finish a few times and dig into anything you've not seen/used before.

By the way, what chips do you work with?

samoz
Agreed. Learn about the electrical/electronic engineering aspects of computers!
Noldorin
I work with the ARM9 for controller and C55 for DSP, also helped write drivers for various types of RF, AD/DA and Power Amp ICs.
+3  A: 

Having great familiarity with pointers, the checks these languages don't do much (like buffer overflow and stuff like that), digital electronics. Operational systems internals might also help.

Get to know how stuff is represented internally, specially ready-made data structures (supposing you won't build your own one).

Above all, practice a lot. Doing it brings much more to you than just reading about it ;)

Samuel Carrijo
+4  A: 

If you haven't yet I think every Software Engineer should read The Pragmatic Programmer and Code Complete. I know these are not specific to low level programming, but have a large wealth of knowledge in them that applies to all sub disciplines.

Brian
I have these books and read them. I think they are both great.
*Practices of an Agile Developer* is sort of the sequel to *The Pragmatic Programmer* and is also a very good book.
Imagist
+10  A: 

Specific concepts like,

  1. Endianness (this link is to an old but good linuxjournal article)
  2. Effective use of multithreading architectures (the Embedded site is good in general)
  3. Debugging embedded and multithreaded systems
  4. Understand, Learn and Follow good programming techniques (the link is very old and the point very generic and subjective, but think about it)
  5. Other things (this IBM page on embedded linux sums up most of the other points I want to make)
  6. One more thing -- never underestimate testing! or, planning test cases!!

Use the reference links I give as concepts,
please followup further for deeper knowledge.

nik
Yes TATFT. If you don't know what it means, look it up, and live by it!
Brian
@Brian, You bet! I kicked myself for missing that one out.
nik
I just learned what TATFT stood for and laughed out loud in my cubicle, I totally agree, actually we always TATFT in my team and frown upon those groups that don't.
this assumes the user is using an rtos or other embedded operating system which is not an assumption I would make, certainly not embedded linux which is an oxymoron. These are good high-level things to worry about but not low-level
dwelch
The question mentions embedded software engineering and perceived importance of hardware architecture and ISA. I had that in mind while enumerating points.
nik
@dwelch, I read your points and agree with them. If you look at the points in my answer (and maybe skim over the articles a bit), you will probably agree that this high-level approach towards low-level engineering will make your mind ready to write the kind of points you list.
nik
+6  A: 

Similar to what Brian said, learn how to create unit tests and automated builds.

These skills are are good for all levels of software engineers to be proficient in. They will help improve the quality of your code while also making it easier to refactor and improve the code base.

Vinnie
Good but not unique to embedded systems.
Craig McQueen
+1  A: 
  • bit operations
  • processor architectures (caches, etc)
  • wcet analysis
  • scheduling

Edit: What I forgot to mention is model based development. Today, the control algorithms are often implemented as some kind of automaton from which C code is generated afterwards. Commercial available tools are for example MATLAB/Simulink, ASCET or SCADE.

swegi
I didn't know about what wcet stood for, I googled it and found <a href="http://www.mrtc.mdh.se/projects/wcet/">this page.</a> I just learned something new, thanks!.
+1  A: 

Get yourself a copy of the MISRA-C book. It was originally written by members of the automotive industry, and attempts to make software written in C more robust by applying a number (quite a large number!) of rules and guidelines.

Then, buy PC-Lint (or another static analysis tool) to check your code for MISRA and other rules.

These are particularly relevant to low-level and embedded C, as between them they deal with the causes of a lot of bugs in such software, such as issues relating to pointers, memory leaks, integer promotion (there's a whole chapter on that in the MISRA book), endianness, and undefined behaviour.

Steve Melnikoff
+9  A: 

I see a lot of high-level operating system answers here, but you specifically said low-level.

Some scattered thoughts: Design for test. As you work through a problem only change one thing at a time per test. You need to understand busses and interfaces, spi, i2c, usb, ethernet, etc. Number one interface, today, yesterday, and tomorrow, the uart, serial. The steps involved in programming a flash. Tricks to avoid making the product easily brickable. Bootloaders in general. Bit-banging above said interfaces on various families of parts (different chip vendors have different ideas about io pins, pull ups, direction controls, etc). Board and chip bring up, you certainly never want to boot a many tens of thousands of lines of code program on the first power up (think led on, led off). How to debug a product without using too much test equipment (logical analyzers and scopes), at the same time you have to learn to use a scope for debugging, you are far more valuable if you dont HAVE TO have a tech or engineer in the lab with you. How would you reprogram the unit in the field? What would you do to minimize human error when allowing the user to field upgrade the unit? Remember field downgrades as well. What would you do to discourage hacking (binaries, etc). Efficient use of the flash/rom (dont wear out one bank or section, spread the wear around, or see if the flash is doing it for you). How and when to use a watchdog timer. State machines, very useful with bytestreams (serial and ethernet), design packet structures that stream well and are tailored to a state machine, and that have a header and checksum or other structure that insures you do not interpret partial packets or random data as a good packet.

dwelch
+1, I need more upvotes!
DoxaLogos
Good post. I would add that when building embedded apps, your debugging capabilities are fewer, and design forethought becomes absolutely necessary much more than it is in friendly environments when you are sandboxed and you aren't going to ruin code elsewhere. Additionally, flipping to the wrong bit or dereferencing a dangling pointer has real consequences here, unlike on desktop programming where the worst you get is a program crash. Program defensively, even when you don't see a strong need to.
San Jacinto
yes, program defensively, I like that term.also know when to go against the norm like more global variables and less locals. Dont always assume that .bss and .data have been setup (because you didnt do it), and chose an alternative.Power management, more and more things run off of batteries. It takes less power to store a 1 in a rom than a 0. Save to nv ram when power is removed. Wakeup, handle event, go back to low power mode.
dwelch
If you cant read a schematic, learn. Same goes for datasheets, and same goes for reading of verilog and vhdl. Depending on the project you basically are not going to get a good or accurate programmers reference manual, the schematic plus the scope will show where the signals are and the verilog/vhdl will tell you what your fellow engineers glue logic is doing.
dwelch
This is a good list. I think up-votes would come more readily if you reformatted it to make it more readable. Bullets would be a good place to start -- this is a (unordered) list, after all.
Steve S
+1  A: 

Good question. Some that haven't been mentioned...

Learn your various options for achieving low-level multitasking. From basic round-robin (non-preemptive) schedulers, with timing ticks from a hardware timer, up to a preemptive RTOS. Learn why you might need an RTOS, and why you might not. If you use an RTOS, learn that beginners with a PC background probably tend to want to create too many tasks.

Getting visibility into the internals for debugging can be a challenge. There's no screen typically, so no throwing in "printf" calls wherever you want. An emulator or JTAG interface is ideal--you can set breakpoints and step through your program (as long as halting the micro doesn't make hardware go crazy, like swinging a robot arm around at full speed!). If emulator/JTAG is not available, learn how to use a spare serial port (or maybe even bit-bash a pin to make a serial port) for a debug channel, with some simple memory peek/poke commands.

Craig McQueen