I just started at a small company and there is a hot-needle-built software for micro controllers written in C which we are now starting to clean up to make it maintainable again.

Of course this goes in parallel to normal production and since our final product testing is quite extensive, the software in general works quite well.

However, there are a few things that bother me like things that only work with -Os and break with any other optimisation level in that the watchdog (counting up a certain sequence, which looks good before it resets) resets the MCU kind of randomly. So I thought about using a sanitizer like the UBSan from the LLVM project to inspect things further. But I find myself unable to find a tool that might help here.

Am I missing something or is it just in the nature of embedded systems that runtime-checker like UBSan cannot be used?

What I tried so far was stepping through instruction by instruction to see where it breaks ... but well, the part where the watchdog reset acurs, jumps around, meaning it happens in any corner of the code.

I also enabled many warning switches of the compiler and ran cppcheck and in the process fixed over a hundred warnings about possibly undefined variables and dead code but the watchdog issue remains.

Are there other ways to inspect random resets more effectively?

  • This question doesn't seem like it's not sufficiently specified to be reasonably answerable here. What does "things that only work with -Os" mean specifically? Are you experiencing crashes on other optimization levels? Have you tried compiling the code to assembly and examining the output of the compiler, comparing the -Os output to that of other optimization levels? Have you otherwise been able to isolate the code that is failing on some optimization levels? Do you have reasonable suspicion that UB is occurring? Commented Oct 30, 2019 at 21:04
  • That's part of the problem. The code is tightly coupled at the moment. It's not possible to test parts of the code in isolation. Lots of globals and all that. ... We will work on that probably throug the whole of 2020 but for now we are tackling urgent issues. I will try to edit my question to be more specific. However, I do not look for a solution for a specific problem, but for a more general advice on how to debug code specific to undefined behavior that does run on a micro controller. ... Maybe a stupid question for experienced embedded devs?
    – user233741
    Commented Oct 30, 2019 at 21:15
  • Perhaps consider running the source code through a static code analyzer first, like this one: cppcheck.sourceforge.net Commented Oct 30, 2019 at 21:19
  • @RobertHarvey: Thanks for the hint and sorry for not mentioning this initially in my question. I ran cppcheck and fixed most of the problems it found. "most" because some come from generated code and need to be fixed elsewhere.
    – user233741
    Commented Oct 30, 2019 at 21:25
  • 3
    Ok, then your best options is probably to make use of classic techniques for debugging without a debugger: like adding lots of logging (maybe by instrumenting the code with logging each function call), checking/asserting preconditions, postconditions and invariants. Note your "watchdog issues" are not necessarily a cause of UB, a classic bug can also bring your program into an endless loop.
    – Doc Brown
    Commented Oct 30, 2019 at 21:48

1 Answer 1


This does not answer the question but indicates a problem with using code generated by CubeMX so I will post it here for reference. From http://blog.atollic.com/best-practices-faq-truestudio-stm32cubemx

The debugger "jumps around randomly" or "breakpoints don't work" or "Execution stuck at a certain code line"

These are all symptoms of the same underlying problem. STM32CubeMX generates a build configuration named Debug which has the optimization setting set to -Os (optimize for size). When applying any optimization level above -O0 or -Og the debugger will be unable to disassemble and map a certain instruction 1-to-1 to a C code line. Since source code no longer matches Assembly instructions. This will throw the debugger off totally. Stepping may not work, breakpoints may not work and it may seem as if execution is stuck at some random code line when it actually is in the while(1)-loop in main().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.