Debugging tool for mbed enabled microcontrollers, especially for NUCLEO-F303RE and STM32F042F6P6.

debug_register.cpp

Committer:
bieleluk
Date:
2019-05-13
Revision:
12:a8ab6e018422
Parent:
11:90164cad21ed
Child:
13:92533bcf6542

File content as of revision 12:a8ab6e018422:

#include "Debug.h"


// create object of class Debug_register
//------------------------------------------------------------------------------------------------------------------ 
Debug_register::Debug_register(PinName tx_pin, PinName rx_pin, int baudrate) : pc(tx_pin,rx_pin, baudrate) {
    init();
}

// init function
//------------------------------------------------------------------------------------------------------------------ 
void Debug_register::init() {
    pc.printf("\ec"); //clear entire screen
    wait_ms(50); //wait until clearing is done
    pc.printf("-----------------\n\r|\e[1m\e[97;40m\e[93;40mBREAKPOINT AREA\e[22m\e[97;40m|\n\r-----------------\n\r\033[s"); //print breakpoint label
    pc.printf("serial successfully initialised\n\r\e[32;40mto start program press any button\e[97;40m");
    breakpoint_count=0;
    pc.getc(); // wait until user sends any character
    pc.printf("\r\e[2K\e[31;40mprogram is running\e[97;40m\r"); //running program message
    pc.printf("\033[14;0H------------------\n\r|\e[1m\e[93;40mSERIAL PORT AREA\e[22m\e[97;40m|\n\r------------------\n\r\033[s"); //print serial port label
}


// perform one breakpoint and print one register
//------------------------------------------------------------------------------------------------------------------  
void Debug_register::breakpoint(int line_number, uint32_t address){
    
    uint32_t reg; //value of register
    char sign; //received character

    address -= address%4; //if address is not divisible by 4, set address to the closest lower number divisible by 4 

    pc.printf("\e[s");//save actual cursor position
    wait_ms(50);//wait until the position is saved
    
    breakpoint_count++;
 
    while(1){ //endless cycle until Enter is pressed  
        address -= address%4; //if address is not divisible by 4, set address to the closest lower number divisible by 4 
        clear_from_n_up_to_m(13,3); //clear breakpoint area
        
        if (line_number < 0){ //print breakpoint and line number
            pc.printf(" Breakpoint number %d\t unknown line number\n\r",breakpoint_count);
        }else{
            pc.printf("| Breakpoint number %d\tline number %d\n\r",breakpoint_count, line_number);
        }
        
        reg = read_word(address, 0); // read register value from address shifted by offset 0
      
        //print entire breakpoint
        pc.printf("---------------------------------------------------------------------------------------------------------\n\r");    
        pc.printf("| address hex 0x%8x | value hex 0x%8x | address decimal %10u | value decimal %10u |\n\r", address, reg, address, reg);
        pc.printf("---------------------------------------------------------------------------------------------------------\n\r");
        pc.printf("|bit_num|31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|\n\r");
        pc.printf("---------------------------------------------------------------------------------------------------------\n\r|bit_val|");
        // print register value in binary form
        for (int i = 0; i < 32; i++){
            pc.printf("%2d|",reg >> (31 - i));
            reg -= ((reg >> (31 - i)) << (31 - i));
        }
        pc.printf("\n\r---------------------------------------------------------------------------------------------------------\n\r");
        
        
        pc.printf("\e[32;40mto continue press enter or p, to see higher press i, to see lower press j\n\rto read register press r, to write to register press w\e[97;40m");
        sign = pc.getc();
        if (sign == 13 || sign == 'P' || sign == 'p'){ // if P or enter was pressed, end the breakpoint
            pc.printf("\r\e[2K\e[31;40mprogram is running\e[97;40m\n\r");  
            pc.printf("\e[u"); // return cursor position to serial port area
            break;
        }else if (sign == 'i' || sign == 'I'){ // if i was pressed, show register on higher address
            pc.printf("\e[u");
            address += 0x4; // return cursor position to serial port area
            continue; 
        }else if (sign == 'k' || sign == 'K'){ // if i was pressed, show register on higher address
            pc.printf("\e[u");
            address -= 0x4; // return cursor position to serial port area
            continue; 
        }else if (sign == 'r' || sign == 'R'){ // if r was pressed, insert new address value 
            pc.printf("\r\e[K\e[12;0H\r\e[K\e[32;40m use l or j to xyzzzzzzzzx\e[97;40m");
            //pc.printf("\e[6;46H"); //move cursor to 6th row 46th column
            address = modify_value(address, 17); // insert or modify actual address(starting in 17th column) to read register value from it
            continue;            
        }else if (sign == 'w' || sign == 'W'){ // if r was pressed, insert address value and register value to write register value on that address
            pc.printf("\r\e[K\e[12;0H\r\e[K\e[32;40m use l or j to xxxxxxxxxxx\e[97;40m");
            //pc.printf("\e[6;46H");
            address = modify_value(address, 17); // insert or modify actual address(starting in 17th column) to write register value on that address
            pc.printf("\e[12;0H\r\e[K\e[32;40m use l or j to yyyyyyyx\e[97;40m");  
            //pc.printf("\e[6;96H");
            reg = *((volatile unsigned int *)address); //read register value from address
            reg = modify_value(reg, 40); // insert or modify actual register value(starting in 40th column) to that write register value on address
            *((volatile unsigned int *)address) = reg; // write new register value on the address
            continue;
        }else{
        }
    }
}

// print formatted string to debug serial port
//------------------------------------------------------------------------------------------------------------------ 
int Debug_register::printf(const char* format, ...){
    
    int ret = pc.printf(format);
    return ret;
}

// read formatted string from debug serial port
//------------------------------------------------------------------------------------------------------------------ 
int Debug_register::scanf(const char* format, ...){
    
    int ret = pc.scanf(format);
    return ret;
}

// print character to debug serial port
//------------------------------------------------------------------------------------------------------------------ 
int Debug_register::putc(int character){
    return pc.putc(character);
}

// read character from debug serial port
//------------------------------------------------------------------------------------------------------------------ 
int Debug_register::getc(){
    return pc.getc();
}

// check whether there is any character to read
//------------------------------------------------------------------------------------------------------------------ 
bool Debug_register::readable(){
    return pc.readable();
}

// check whether it is possible to write a sign to debug serial port
//------------------------------------------------------------------------------------------------------------------ 
bool Debug_register::writable(){
    return pc.writable();
}

// clear screen from m line up to n line
//------------------------------------------------------------------------------------------------------------------
void Debug_register::clear_from_n_up_to_m(int m, int n){
    pc.printf("\033[%d;0H",m);
    wait(0.1);
    while (m > n){ 
        m--;
        pc.printf("\033[K\033[%d;0H",m);
    }
    pc.printf("\n\r");

}

uint32_t Debug_register::modify_value(uint32_t value, int horizontal){
    
    uint32_t tmp = value;
    char val_str[8];
    int horizontal_min = horizontal;
    char sign; 

ONCE_AGAIN:
    pc.printf("\e[6;%dH", horizontal);
    for (int i = 0; i < 8; i++){
        if ((tmp >> (28 - 4*i)) > 9){
            val_str[i] = ((tmp >> (28 - 4*i)) + 87);
        }else{
            val_str[i] = ((tmp >> (28 - 4*i)) + 48);
        }
        pc.putc(val_str[i]);
        tmp -= ((tmp >> (28 - 4*i)) << (28 - 4*i)) ;
    }
    pc.printf("\e[6;%dH", horizontal);

    

    
    while(1){
        sign = pc.getc();
        if (sign == 13){
            value = (uint32_t)strtol(val_str, NULL, 16);
            break;
        }else if(sign == 'l' || sign == 'L'){
            horizontal = min(horizontal+1,horizontal_min+7);
            pc.printf("\e[6;%dH",horizontal );
            continue;
        }else if(sign == 'j' || sign == 'J'){
            horizontal = max(horizontal-1,horizontal_min);
            pc.printf("\e[6;%dH", horizontal);
            continue;
        }else if ( ((sign >= 48 && sign <= 57) || (sign >= 65 && sign <= 70) || (sign >= 97 && sign <= 102)) && horizontal <= horizontal_min + 7 ){
            if (sign >= 65 && sign <= 70){
                val_str[horizontal - horizontal_min] = sign+32;
                pc.putc(sign+32);
            }else{
                val_str[horizontal - horizontal_min] = sign;
                pc.putc(sign);
            }
            if (horizontal == (horizontal_min+7)){
                pc.putc('\b');
            }else{
                horizontal++;
            }
            continue;
        }else if(sign == 27){
            horizontal = horizontal_min;
            tmp = value;
            goto ONCE_AGAIN;
        }
    }
    return value;
}