Main Page


The modem firmware is the second most complicated firmware on the satellite (after the obc firmware) and has the most stringent timing requirements. It is also a critical point of failure as it is the system through which the ground station communicates with the satellite. If a bug is discovered in another system on-orbit and a firmware update is required, the modem must be working in order to deliver the update. Thus, it is critical that all firmware is thoroughly tested and characterized. To achieve this, we are using a paradigm called Test Driven Development (TDD), which essentially means that you write the tests before the code and then refactor the code until it passes the tests.

There are three types of testing we will be performing on the firmware:

  • Unit testing - testing of small functional elements. Ideally, each function should have several tests written for it. These tests are run frequently (after each modification of the firmware, so typically every few minutes during a development cycle).
  • Block-level synchronous integration testing - testing of full system blocks (for example, the Viterbi decoder). Consists of building a mock producer and consumer block and feeding test data through them.
  • System-level asynchronous integration testing - loading two or more system blocks into the scheduler and testing their interoperation and performance.

This document focuses only on unit testing, the most basic and lowest-level of the tests.

Useful Resources

Before you begin, you may wish to read a few chapters of “Test Driven Development in Embedded C” by James W. Grenning. A PDF of this text can be found in the box.

The framework we're using for testing is called Unity. This is its website:


  • XC32 Compiler (Free version is fine)
  • A copy of the modem source code, located in [ Communcations/Software/Active/PIC32Firmware] on the SVN server. ==== Building the Firmware For the Simulator ==== - Open MPLAB X. Choose File → Open Project. Open the “SDRFirmware.X” project. - Make sure that Simulator_Unit_Testing is the current configuration (selectable on the top bar). This configuration will add a compiler flag to disable the FreeRTOS scheduler and run the unit test reports instead. It will also use the PIC32 simulator rather than any actual hardware you may have connected. - Run Debug → Debug Project. The project should build and run in the simulator. A tab marked “UART 2 Output” should appear, which will contain something like: <code> \0xF4v:19:test_adder_add_positive:PASS ———————– 1 Tests 0 Failures 0 Ignored OK </code> ==== Creating a New Test ==== Remember, in the spirit of TDD, you should create a test before you create the implementation. This has a couple of important advantages. You actually verify that the test is installed and works (because it fails), which is important when doing unit testing in C where you have to manually install the tests into a runner program. If the test passes and you haven't done the implementation yet, that's a good sign you've done something wrong (like forgotten to install the test). It also forces you to think about the behavior of the software before you start writing any code. If you write the code before the tests, you might subconsciously reinforce incorrect misconceptions and then miss something when you do go to write the tests. Which tests to write is outside the scope of the tutorial, but I encourage you to read the TDD book suggested above to get a good idea of what to do. To actually write a test, first create an empty, stub implementation of the function you're trying to write, either in a new file or in an existing file. Make sure you also create a header file for it and add its prototype there. Don't implement anything yet! We'll do that once we have tests running and failing. In this example, we're creating a simple function that adds two numbers together. #include “adder.h” int addTwoNumbers(int a, int b) { return 0; } Create two files in the “UnitTests” folder: mymoduleTest.c and mymoduleTest.h (replace “mymodule” with something more fitting“). Here's what they should look like: for adderTest.h /* * File: adderTest.h * Author: Peter * * Created on October 24, 2014, 12:53 PM */ #ifndef ADDERTEST_H #define ADDERTEST_H #ifdef cplusplus extern “C” { #endif void test_adder_add_positive(void); #ifdef cplusplus } #endif #endif /* ADDERTEST_H */ adderTest.c #include ”./UnitTests/unity.h“ #include “adder.h” void setUp(void) { } void tearDown (void) { } void test_adder_add_positive() { TEST_ASSERT_EQUAL_INT(4, addTwoNumbers(2,2)); } Once you've written all the tests you want to write initially, you'll want to install them in the test runner. You can do this by editing testrunner.c in the UnitTests folder: testrunner.c /* * File: testrunner.c * Author: Peter * * Created on October 24, 2014, 11:48 AM */ #include <stdio.h> #include <stdlib.h> #include ”./UnitTests/unity.h“ various tests

#include “adderTest.h”

void runUnitTests(void) {

  /* END TESTS */


After this, you should be able to build and run the project. At this point, the tests should fail, giving output similar to that below:

\0xF4v:13:test_adder_add_positive:FAIL: Expected 4 Was 0
1 Tests 1 Failures 0 Ignored

If not all your tests fail, you've done something wrong. Check that the tests are doing what you want them to and that they're installed, and try again.

Once your tests have failed, you can actually modify the stub implementation so it will pass the tests.

#include “adder.h”

int addTwoNumbers(int a, int b) {

  return a+b;


Once you do this, your tests should pass:

1 Tests 0 Failures 0 Ignored

That's about it. For further details, read the TDD book.

When to commit to the SVN

Commit changes to the SVN frequently. In general, tests may be committed even if they're failing, as long as the test wasn't previously passing. Failing tests simply means that the implementation isn't finished, which is acceptable. You should commit:

  • After writing and installing new test(s) (ie: new tests failing)
  • After a previously failing test passes
  • After successfully refactoring code

You should not commit:

  • If the software does not build (people who upload broken builds will owe the rest of the team a round of Lucky Lager)
  • After a previously passing test fails (ie: breaking a working implementation)
QR Code
QR Code tutorial:unit_testing_in_mplab (generated for current page)