April 25, 2006

Unit Testing Embedded System Registers, Part 2

After figuring out how to unit test hardware registers for single reads and writes, we encounter code that makes multiple writes to a register. For example, here is some code that runs on 68HC12 microprocessor:


void set_pulse_speed(unsigned int ps)
{ 
  SPI0DR = (unsigned char)(ps >> 8); // Pump speed high byte
  while( (SPI0SR & 0x80) == 0 ) {};
  c = SPI0DR; // dummy read to reset the SPI interrupt flag
  
  SPI0DR = (unsigned char)ps; // Pump speed low byte
  while( (SPI0SR & 0x80) == 0 ) {};
  c = SPI0DR; // dummy read to reset the SPI interrupt flag

  select_SPI_device(SPI_NONE);
}

Since the code writes to the register SPI0DR two times, we cannot test the code by reading the last value written to SPI0DR. We obviously have to remember the "history" of all writes. This code saves consecutive writes, by defining the register as an array buffer:

// mock_registers.h
extern unsigned char REG_write[16];
extern int           REG_write_idx;
#define              reset_REG_write_idx()    (REG_write_idx = 0)
#define              REG        REG_write[++REG_write_idx]

// my_code.c
//      Accessing REG more than once within a function
    REG = 7;    // resolves to:  REG_write[0] = 7;
    REG =55;    // resolves to:  REG_write[1] = 55;

// unit_test_my_code.c
    reset_REG_write_idx();               // Reset array counter
    
    my_code();                           // ... REG = 7; REG = 55; ...
    
    test_char_equal(  5, REG_write[0] ); // Verify that correct values are set
    test_char_equal( 77, REG_write[1] );

This code works great for a few tests. But when running hundreds of tests, some tests might access REG more than 16 times (the length of REG_write[16]). Thus I use this safer code that uses a circular buffer:

// mock_registers.h
extern unsigned char REG_write[16];
extern int           REG_write_idx;
#define              reset_REG_write_idx()    (REG_write_idx = 0)

#define              REG    if( ++REG_write_idx>=16 ) REG_write_idx=0;  \
                            REG_write[REG_write_idx]

     REG = 7;      // resolves to:
                   //    if( ++REG_write_idx>=16 ) REG_write_idx=0;
                   //    REG_write[REG_write_idx] = 7;

Testing functions that perform multiple reads from a register can be done in the same manner. Posted by laza at April 25, 2006 06:10 PM | TrackBack

Comments
Post a comment









Remember personal info?