11 techniques every Cortex-M developer should consider

Posted by Magnus Unemyr on Apr 13, 2015 1:31:27 PM

Are you a skilled Cortex-M developer, perhaps developing great software? Of course you are. No one would admit to being a lousy developer. However, it is useful to sometimes take a step back and see if there are new techniques or skills available that can help you improve. In this blog article, I have collected a number of techniques that can be deployed to help you develop Cortex-M software in a better way, releasing software more timely and of higher quality.

First of all, you obviously need to know C or C++ and possibly a tad bit of assembler as well. This is a must; if you don’t master this, order a book on immediately. You likely need to know your target device and its device driver libraries as well. Your semiconductor vendor will provide information on this. But when what? What are the “secret” techniques used by really skilled embedded developers?


To start with, the Cortex-M processor core contains a lot of advanced debugger capabilities not used by all embedded developers. This is a shame as these powerful debugger solutions may sit there right under the nose, not solving your “million dollar bug” when it can.

#1 Hard fault crash analysis. The CPU may crash due to a hard fault exception caused by a software error, such as division by zero, a pointer error or a stack overrun. Use the built-in Cortex-M hard fault crash analysis capabilities that will tell you what happened, where in the code it was, and why. It can save you so much time!
#2 Real-time event and data tracing. Cortex-M processors have hardware support for Serial Wire Viewer (SWV) real-time event and data tracing, offering capabilities like:
  • Single-channel and multi-channel printf() redirection to a debugger console
  • Software instrumented tracing
  • Real-time variable watch
  • Graphical oscilloscope-styled variable value chart plots
  • Memory and variable access history log
  • Performance analysis using statistical profiling
  • Execution time measurement
  • Interrupt and exception event logging
  • Interrupt and exception statistics
  • Interrupt and exception nesting analysis
  • General event logging

Make sure to learn using the powerful debugger capabilities enabled by SWV!

#3 Record execution history using instruction tracing. For really tough debugging tasks, you may have to buy an ETM trace enabled JTAG probe, such as SEGGER J-Trace. It will record the execution history for you, enabling the possibility to analyze what happened prior to a nasty bug. Instruction tracing may be your only option if stopping on a breakpoint will damage physical equipment, for example in motor control applications.

#4 Real-time variable watch. The Cortex-M core enables debuggers to poll the memory as the target system executes at full speed, enabling debuggers to provide “live” variable watch views, supporting also complex data structures such as structures and arrays. Being able to see variable values changing in real-time as your system runs at full speed really is very useful!

#5 Kernel-aware RTOS debugging.  Are you using an RTOS? Great, but don’t be blind! If you are using an RTOS, you will need an RTOS-aware debugger that shows you the internal state of the RTOS when you stop on a breakpoint; for example by visualizing the state of tasks, semaphores, message queues, timers, etc.

Being an ace on debugging is all-and-well, but why do you introduce bugs in the first place? Skilled developers are using defensive techniques helping them to avoid introducing bugs. Only “cowboy hackers” start to write code without employing strategies for bug prevention.

#6 Use a consistent coding style. Use a consistent coding style, and standardize your blank lines, indentations, location of curly brackets etc. A modern editor should allow you to configure the coding style, and helps you enforce that automatically. This helps code reading and code understanding.

#7 Follow best-practice coding standards. Why invent the wheel or doing things opposite to what hard-learnt industry best-practice tells you? Make sure your source code conforms to the MISRA-C coding standard, or some other formal coding standard. That helps you write code that is less error prone, more portable, and more maintainable. Good IDE’s have built-in MISRA checkers with rich results navigation GUI and coding standard teaching aids.

#8 Measure and manage code complexity. The more complex your C/C++ functions are, the more likely you have bugs in them. Additionally it is more difficult and expensive to maintain the code. Measuring, and managing (=limiting) the structural complexity of your C/C++ functions can massively help reduce the number of bugs, and simplify maintenance too. Code complexity have nothing to do with number of code lines, as it instead measures the number of potential execution paths that can be taken in the function, using a standard measure called cyclomatic value of code complexity (aka McCabe index). Do you feel alone? Hopefully not, as most developers today work in a team, with multiple team members in the same office, or geographically spread over the country or even across continents. But adding more code, and more developers, increase the need for code management, task management, and team management. Make sure you use the right tools for this. Most of them are even free, and so there is no excuse to be a rebellion “cowboy hacker” anymore!

#9 Manage your code in a version control system. Really. Do this. Period. It still surprises me to hear that there are professional developers working on commercial projects, without proper code management using version control systems. In my mind, this is a serious neglect even if you are a single developer working alone on your own. For a multi-developer team, this is just a must. In particular since the tools needed for this are free, and provides so much benefits in terms of traceability, change tracking, revertability, as well as possibilities for working in parallel using feature and release branches etc. If you don’t use version control systems already, stop reading this article right now and download the free Subversion (SVN) or Git version control system immediately.

#10 Manage your bugs and feature requests in an issue tracking system. While not fully as important as using a version control system, it almost is. Download for example the free Bugzilla or Trac issue management database systems, and record all bugs, feature requests and work tasks in a well-organized database, allowing you to track work tasks like bug reports and feature requests, and tag them for different versions/releases, etc. Scanning through the open items in the issue management database in the weekly team meeting is an excellent way to organize the work-week and weekly team-meetings as well.

#11 Source code reviews. Performing peer reviews or source code reviews is arguable the cheapest way to improve software quality the most, fastest. It is often not done as it is considered a bit boring, and integrated tool support have previously been lacking. But if you are serious about improving your software quality, you ought to perform source code reviews regularly. At least for the critical parts of your software product.

Most of the techniques listed above are either free or likely already supported in the tools you already use; and so in many cases it is just to learn a new skill. Even if you do not start to use all of these techniques right now, using some of them will likely improve your development situation quite a bit.

For more information on debugging Arm Cortex-M devices read this blog post:

How to use the most powerful debug techniques on Arm Cortex-M devices

You can also get a good overview of Serial Wire Viewer real-time tracing on Cortex-M cores by reading this white paper on the subject:

Read our SWV event and data tracing whitepaper!

Get an overview of Arm Cortex-M development and debugging in this whitepaper:

 Read our ARM development whitepaper!

Topics: ARM Cortex, Software quality, Debugging, Embedded Software Development