2.2.1 General Information

One of the more technical features in microcontrollers is the reset register(s) or the Reset controller (for AVR devices). They contain a bit field that indicates the last source of reset for the microcontroller.

One method to consider is the debugger. Before continuing, there are a few things to note about the debugger. Some peripherals will not operate correctly with the debugger active. The most vulnerable peripherals will be the timers and serial peripherals (SPI, I2C, CAN, UART, etc.). On AVR devices, many of the peripherals must be explicitly enabled to run in debug. In some cases, entering sleep while debugging may affect the debugger’s performance and operation as well.

The benefit of the debugger is that the device registers and Random-Access Memory (RAM) can be directly viewed and edited while the program is stepped line by line. This method is one of the simplest ways to troubleshoot complex issues that are difficult or time-consuming to replicate.

Another way to print the values is to output the bits in parallel, then use a logic analyzer to read the value. This is the simplest (and likely fastest) I/O-based method; however, it consumes a lot of I/O in the process.

An alternative output for the values is to create a software defined serial bus. The simplest method is a software-defined serial transfer, where three I/Os are used – one to indicate activity, one to produce a data clock, and one to contain the data. All of the I/O in use are manually clocked in software, removing any hardware influences or overhead.

void softwareSerialPrint(uint8_t value)
{
    //Signal a message
    DBG_EN_SetHigh();
    
    //Bit mask (inital condition = MSB)
    uint8_t mask = 0x80;
    uint8_t temp = mask & value;
    
    //Print the bits
    for (uint8_t i = 0; i < 8; ++i)
    {
        //Clear the clock
        DBG_CLK_SetLow();
        
        //Output the MSB
        if (temp == 0)
            DBG_DATA_SetLow();
        else
            DBG_DATA_SetHigh();
        
        //Shift the data mask
        mask = mask >> 1;
        
        //Pulse the Clock (Data valid on rising edge)
        DBG_CLK_SetHigh();
        
        //Do this calculation here to improve clock duty cycle.
        temp = mask & value;            
    }
    
    //Cleanup
    DBG_DATA_SetLow();
    DBG_CLK_SetLow();   //If clock is idle high, remove this line.
    DBG_EN_SetLow();
}

The hardware peripherals on the microcontroller can also be used to print the data to UART or SPI. However, there is an additional software overhead to set up these peripherals, and they may be impacted by some issues. But, if “Redirect STDIO to UART” is enabled in the UART Driver(1) from MCC, helpful human-readable logging messages can be printed to MPLAB Data Visualizer or another serial terminal.

Note: Printf uses a lot of memory when enabled.