We have written the following embedded systems basics and embedded C programming tips keeping in view the general C programmer making the transition to embedded programming. Please use the form below this page if you would like to add your own tips or comment on something we have said.
If possible, choose a widely used processor with a strong online support forum
When you are doing embedded programming you are going into uncharted territory with only the datasheet of the processor as your guide. Almost all processor implementations have bugs and the datasheets are buggy or incomplete. Also you will make mistakes in your understanding of the processor. If the processor is widely used chances are that someone else would have encountered the same issue and discussed it in the forums.
Use a software emulator for initial development and logic tests
Can be used even before the hardware is ready. External hardware can be modeled and added to it. Many software simulators run at near native speeds. Since the simulator runs on a general purpose computer there are no limits on the number of breakpoints and watch parameters that you can put
Test on actual hardware as soon as possible
Actual hardware is reality and you will in almost all cases have to modify your code that you developed to have it work on actual hardware. Try and run the software on the first prototype hardware that you can lay your hands on. This may be hacked up with jumper wires running all over and may change considerably before the the final unit is ready. However it will provide you invaluable feedback.
Try and have the fastest build, run, test, debug cycle
You will be modifying, compiling and downloading your code many, many times before you are done. Being able to do this fast will help you many times over.
Do not upgrade your toolchain in middle of the project unless there is a compelling reason to
Compiler upgrades may generate different assembly code which may impact your software in unforseen ways. A small upgrade to one portion of your toolchain may cause other parts to not work together causing many hours of down time while you re assemble your toolchain.
Preserve your toolchain after the project, virtual machines may help.
A successful embedded project will be with you for a long time. It will go out in the field and right when you are sipping coffee at lunch one day there will come a call about this small change that has to be done. So once you are done with the project, make a small box of everything about the project,. It is important to preserve the tool chain. The compiler that you will have available 2 or 5 years down the road will not be the same as the compiler you have available now.
Virtual machines are great in this respect. We try and do each project on a separate virtual machine. Once we are done we preserve the entire virtual machine. We have find VMWare and VirtualBox to be great in this respect.
Understand the processor and the hardware, Keep updated schematics of the board handy
If you are doing embedded programming you will have to understand the hardware. You will have to know the architecture of the processor and the schematics of the board. If you are coming from a pure software ground, you will have to read up on this. The good news is that this is not that hard. Just know that there is no way you are going to become a successful embedded programmer without understanding the hardware. Insist on getting schematics with each hardware that you are trying to program. In case any changes are made to the hardware, ensure that the schematics that you have are updated.
Try to have a serial port on the board or some visual indicator
These old fashioned tools are remarkably effective in debugging embedded system
Write a monitor routine
If you do manage to get a serial port, write a monitor routine that allows you to inspect the variables and execute commands. A monitor routine will save you a lot of time. As time goes on you will find yourself porting this monitor routine from one project to another.
Get the best debugging environment you can afford
In circuit emulators (ICE) are best but they are expensive and rarer to find. JTAG provides an alternative. However JTAG implementations are limited in the number of breakpoints you can place and the ability to examine code traces.
Ensure that all variables modified in interrupts are defined as volatile
Elementary, but I have been bitten by this more than once.
Watch RAM space carefully
Many embedded systems are severely constrained in the amount of RAM they have. If you find yourself running out of RAM you can store constant strings and other variables in flash. The mechanism for this varies from C compiler. Check these carefully.
Watch out for Priority Inversion
If you have multiple tasks with differing priority levels it is important to ensure that priority inversion does not happen.Priority inversion is when a low priority task acquires a resource required by a higher priority task. The execution of the high priority task will block till the low priority task has released the resource. The low priority task has effectively taken priority over the high priority task, thus inverting the priority task. Now if a middle priority task comes along it will take priority over both the high priority and the low priority task. There are ways around this issue .
Try to have the source of all the code the processor
Something or the other will go wrong and without the source of everything it will take you much longer to locate the problems.
Write C in a modular fashion
You will most likely be using C to program. You can write C in a modular fashion with each module dedicated to a particular function, exposing only the interface in a header file. This approach is remarkably effective.
What has not been tested, doe not work!
Ensure that the code and the hardware is tested in all coniditions. Try to automate the testing as far as possible.
Do Not Have Infinite Loops
Do not have infinite loops that depend on some condition to terminate. A hardware or software bug may cause the condition to never happen and your software will appear as locked. Always have a way of getting out of any infinite loop.
Implement a Watchdog
Even if your code never crashes or never goes to never, never land in tests. A watch dog will restart your system if something goes wrong with the coding. Embedded systems operate for days and in unpredictable conditions. One can never account for everything that will happen.
Do you need more help to solve your problem? Would you like to ask the author a question about your specific problem? Do you have a great idea about this?
We will post an answer within 2 business days. If you need more immediate assistance or you would like to discuss your issue privately, please use our contact us form or call us at 1-888-215-8557. We love solving technical issues and there is no charge if we solve your problem over email or over a short phone call.