Unit Testing code that touches the HW registers

 This article guides you on how to unit-test code that reads or writes hardware registers of your SJ development board.

 

// Typical code
int get_ultrasonic_pulse_width(void) {
  // Send a pulse width
  LPC_GPIO1->CLR = (1 << 2);
  delay_us(10);
  LPC_GPIO1->SET = (1 << 2);
  
  const uint32_t previous = time_now();
  while (LPC_GPIO1->PIN & (1 << 3)) {
   ;
  }
  
  return time_delta(previous);
}

Before we solve the problem, let us write better code that is self expressive and does not require comments to understand its intent.

static void send_pulse_to_ultrasonic(void) {
  const uint32_t ultrasonic_pulse_pin = (1 << 2);

  LPC_GPIO1->CLR = ultrasonic_pulse_pin;
  delay_us(10);
  LPC_GPIO1->SET = ultrasonic_pulse_pin;
}

static void wait_for_ultrasonic_pulse_to_bounce_back() {
  while (LPC_GPIO1->PIN & (1 << 3)) {
   ;
  }
}

// Notice the clarity of this function compared to the previous code snippet
int get_ultrasonic_pulse_width(void) {
  send_pulse_to_ultrasonic();
  
  const uint32_t previous = time_now();
  wait_for_ultrasonic_pulse_to_bounce_back();
  return time_delta(previous);
}

And the next level:

// Separate header file to abstract the hardware, such that we can mock out this API
// file: ultrasonic_pins.h
void ultrasonic_pins__set_pulse(bool true_for_logic_high);
bool ultrasonic_pins__get_input_pin_value(void);
#include "ultrasonic_pins.h"

static void send_pulse_to_ultrasonic(void) {
  // This can now move to ultrasonic_pins.c
  // const uint32_t ultrasonic_pulse_pin = (1 << 2);

  ultrasonic_pins__set_pulse(true);
  delay_us(10);
  ultrasonic_pins__set_pulse(false);
}

static void wait_for_ultrasonic_pulse_to_bounce_back() {
  while (ultrasonic_pins__get_input_pin_value()) {
   ;
  }
}

int get_ultrasonic_pulse_width(void) {
  send_pulse_to_ultrasonic();
  
  const uint32_t previous = time_now();
  wait_for_ultrasonic_pulse_to_bounce_back();
  return time_delta(previous);
}

 

Back to top