Reader small image

You're reading from  Hands-On Embedded Programming with C++17

Product typeBook
Published inJan 2019
Reading LevelIntermediate
PublisherPackt
ISBN-139781788629300
Edition1st Edition
Languages
Tools
Right arrow
Author (1)
Maya Posch
Maya Posch
author image
Maya Posch

Maya Posch is a senior C++ developer with more than 15 years of experience. Discovering the joys of programming early on, and later the joys of electronics, she has always expressed a profound interest in technology, a passion that she gladly shares with others. Describing herself as a C developer who happens to like C++ and Ada, she likes to seek the limits of what can be done with the minimum of code and hardware to accomplish everything that is cool, new, and exciting. She also enjoys FPGA development, AI, and robotics research, in addition to creative writing, music, and drawing.
Read more about Maya Posch

Right arrow

Chapter 7. Testing Resource-Restricted Platforms

Developing for MCUs and similar resource-restricted platforms is pretty much exclusively done on regular PCs, except for testing and debugging. The question is when one should be testing on the physical device and when one should be looking at alternative means of testing and debugging code in order to speed up development and debugging efforts.

In this chapter we will cover the following topics:

  • Understanding the resource needs of specific code
  • Effectively using Linux-based tools to test cross-platform code
  • Using remote debugging
  • Using cross-compilers
  • Creating a platform-independent build system

Reducing wear


Often, during development, there comes that point where one is fixing an issue in a system and have to go through the same tweak-compile-deploy-test cycle, over and over. Here are the main problems that are introduced with this approach:

  • It's not fun: It's frustrating to have to constantly wait for results without a clear idea of whether it will actually be fixed this time.
  • It's not productive: You spend a lot of time waiting for results you wouldn't need if you could just analyze the problem better.
  • It wears down the hardware: After removing and reinserting the same connectors dozens of times, writing and overwriting the same sections of the ROM chip countless times, and power cycling the system hundreds of times, the hardware's lifespan is reduced significantly, along with one's own patience, and new errors are introduced.
  • Fiddling with test hardware isn't fun: The best-case scenario for any embedded setup is to be able to take the development board, plug in all the peripherals...

Planning out a design


In Chapter4, Resource-Restricted Embedded Systems,we looked at how to pick an appropriate microcontroller for an embedded platform. While designing the firmware for the MCU, it's essential that we consider not only the resource requirements of specific codes, but also the ease of debugging.

An important advantage of using C++ is the abstractions it offers, including the ability to subdivide the code into logical classes, namespaces, and other abstractions that allow us to easily reuse, test, and debug the code. This is a crucial aspect in any design, and an aspect that needs to be implemented fully before one can proceed with actually implementing the design.

Depending on the design, it can be either very easy or frustratingly hard to debug any issue, or anything in between. If there's a clean separation between all the functionality, without leaky APIs or similar problems that could leak internal, private data, creating different versions of fundamental classes for things...

Platform-independent build systems


Ideally, the project and build system we choose could be used to build the target platform on any desktop platform. Usually, the main consideration here is the availability of the same toolchain and programmer for each development platform. Fortunately, for AVR- and ARM-based MCU platforms, the same GCC-based toolchain is available, so that we do not have to take different toolchains with different naming conventions, flags and settings into account.

The remaining challenge is simply to invoke the toolchain, and subsequently the programmer utility, in a way that doesn't require any knowledge of the underlying OS.

In Chapter 6, Testing OS-Based Applications, we looked at a multitarget build system, which could produce binaries for a wide variety of targets with minimal effort for each new target. For an MCU target, there would only be the following two targets:

  • The physical MCU target
  • The local OS target

Here, the first target is obviously fixed, as we picked...

Using cross-compilers


Every compiler toolchain consists of a side (frontend) that takes in the source code and a side that outputs the binary format for the target platform (backend). There's no reason why the backend couldn't work on any other platform than the one it's targeting. In the end, one merely transforms text files into sequences of bytes.

Cross-compiling in this fashion is an essential feature with MCU-oriented development, as compiling directly on those MCUs would be highly inefficient. There is, however, nothing magical about this process. In the case of GCC-based and GCC-compatible toolchains, one would still be interacting with the same interfaces on the toolchain, just with the tools usually prefixed with the target platform name to distinguish them from other toolchains for different targets. Essentially, instead of g++ one would use arm-none-eabi-g++

The resulting binaries would be in the format appropriate for that target platform.

Local and on-chip debugging


In Chapter 6Testing OS-Based Applications, we looked at debugging applications using Valgrind and similar tools, as well as GDB and kin. With the OS-based integration tests for MCU-based projects, such as those demonstrated in the Example – ESP8266 integration test section, we can use the exact same techniques, profiling and debugging the code without concerning ourselves just yet with the fact that the same code will be running on a much slower and more limited platform during final integration testing on real hardware.

The real challenge comes during that final integration stage, when the firmware—which we have been debugging on our fast desktop system using Valgrind and other highly capable tools—is now running on a paltry 16 MHz ATmega MCU without the ability to quickly launch the code with a Valgrind tool or within a GDB session.

As one will inevitably encounter bugs and issues during this stage, we need to be prepared to deal with this situation. Often,...

Example – ESP8266 integration test


In this example project, we will look at creating an implementation of the Arduino-like APIs of the Sming framework, which we first looked at it in Chapter 5, Example - Soil Humidity Monitor with Wi-Fi. The goal of this is to provide a native framework implementation for desktop operating systems (OSes), allowing the firmware to be compiled to an executable and run locally.

In addition, we want to have simulated sensors and actuators that the firmware can connect to in order to read out environmental data and send data to actuators as part of the BMaC project, which we had a glimpse of in Chapter 5Example - Soil Humidity Monitor with WiFi, and which we will look at in more detail in Chapter 9, Example - Building Monitoring and Control. For this, we also need to have a central service that keeps track of such information. This way, we can also have multiple firmware processes running, to simulate entire rooms full of devices.

The reason for this scope of...

Summary


In this chapter, we looked at how to effectively develop for MCU-based targets in a way that allows us to test them without expensive and long-winded development cycles. We learned how to implement an integration environment that allows us to debug MCU-based applications from the comfort of a desktop OS and the tools it provides.

The reader should now be able to develop integration tests for MCU-based projects and effectively use OS-based tools to profile and debug them before doing final integration work on real hardware. The reader should also be able to perform on-chip debugging, and have a feel for the relative cost of specific software implementations.

In the next chapter, we'll develop a simple infotainment system, based on an SBC platform.

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Hands-On Embedded Programming with C++17
Published in: Jan 2019Publisher: PacktISBN-13: 9781788629300
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Maya Posch

Maya Posch is a senior C++ developer with more than 15 years of experience. Discovering the joys of programming early on, and later the joys of electronics, she has always expressed a profound interest in technology, a passion that she gladly shares with others. Describing herself as a C developer who happens to like C++ and Ada, she likes to seek the limits of what can be done with the minimum of code and hardware to accomplish everything that is cool, new, and exciting. She also enjoys FPGA development, AI, and robotics research, in addition to creative writing, music, and drawing.
Read more about Maya Posch