Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automated testing of bare metal C code (microprocessor firmware): simulating changes in hardware registers

I want to write automated tests for some very low level C code on a PC that I will port to the microprocessor. I understand that there will be differences (implementation-specific behaviours such as size of int), which I will have to live with.

I need ideas on how to simulate changes of volatile variables (which map to special function registers in the microcontroller). E.g. in the code below, the value of the register flag TX_BUFF_FULL can repeatedly change during the course of the execution of the code, when space in the transmit buffer becomes available or is used up:

void send_str(char * str){
    // for each non-null character
    for (char i = 0; str[i]; i++){
        // wait for space in TX hardware buffer
        while(TX_BUFF_FULL);
        // put character into hardware FIFO
        TX_REGISTER = str[i];
    }
}

TX_BUFF_FULL and TX_REGISTER are volatile variables mapped to the address of special function registers for the UART.

Ideally I will write the source so that it can be compiled without changes for both the automated tests on a PC and running on the microcontroller, which probably needs preprocessor directives.

For example, a directive that uses this line when compiled for the microcontroller:

while(TX_BUFF_FULL);

but uses this when compiled for testing on the PC:

while(test_tx_buff_full());

where the test_tx_buff_full() function would be a part of the test suite that emulates changes in the state of the registers. I can't think of a different way of achieving the result.

Is this a reasonable way? What would be a neat way of implementing the preprocessor directives to achieve this? Is there a neater way? Thanks

Edit: From this question, this question and this question, some other ideas are:

  • using preprocessor macros that produce inline code to replace reading of registers
  • using a programmable hardware test bench that can bootload and perform unit and integration tests, bypassing the need for a simulator
like image 811
CL22 Avatar asked Mar 07 '14 11:03

CL22


1 Answers

It seems to me that this could be done using the kind of APIs used to implement breakpoint debugging. On linux, this could be ptrace (in particular, the PTRACE_POKEDATA operation could be used to deliver the new volatile value, and PTRACE_SINGLESTEP would allow for precisely timing its delivery). I'm certain that analogs exist on Windows and BSD, but I am less familiar with those platforms.

like image 138
laindir Avatar answered Nov 09 '22 15:11

laindir