AVR Debugger


 

History

    The fact is, 10 years ago this project could have been completed. It will be a useful tool to help you debug code. The challenge was to make a debugger that does not require any MCU resources to be used from the MCU, allowing the debugger to run integrated with the code being debugged. The Debugger only use 1 I/O pin, and is connected to a serial port from the host PC. Using a VT100 terminal to capture the output from the Debug tool, all of the debug information can be captured. By adding a simple command along with the debug firmware, you can send out debug statements like debugXY(x,y, "test").  The Debugger will adapt to any speed from 1Mhz to 20Mhz without configuration from the user.
 

 

Features Ver : 1.0

puce No resource need in the MCU you are debugging
puce No configuration to do
puce Run with MCU from 1Mhz to 20Mhz
puce Use VT100 terminal emulator as debugging window
puce Self powered by the serial port of your PC
puce Simple to build
puce Convert any I/O in a verbose debugger
puce Reset button

 

System Requirements

puce Terminal software
puce Debugging circuit with the HEX file of the debugger
puce PC free serial port

 

History

V1.0 First Release!

 

Picture

 

 

Schematic, PCB, Code, Hex File

Schematic

PCB

Hex File

 

\Code in the debugger ATMega162

//*****************************************************************************
// AVR Debuger
// Version 1.0 Fev 2007
//
// Sylvain Bissonnette
//*****************************************************************************
// Editor : UltraEdit32
//*****************************************************************************
//
//                         R E T U R N   S T A C K   1 6
//
//*****************************************************************************
//                      I N C L U D E
//*****************************************************************************
#include <iom162v.h>
#include <macros.h>
#include <shortnametype.h>

//*****************************************************************************
//                      D E F I N E
//*****************************************************************************
#define XTAL                        8000000
#define FALSE                       0
#define TRUE                        1
#define DEBUG_DDR           DDRD
#define DEBUG_PORT            PORTD
#define DEBUG_BIT             0x08

#define DEBUG_UCSRA              UCSR0A
#define DEBUG_UCSRB              UCSR0B
#define DEBUG_UCSRC              UCSR0C
#define DEBUG_UDR                UDR0
#define DEBUG_UBRRH              UBRR0H
#define DEBUG_UBRRL              UBRR0L

#define TERM_UCSRA               UCSR1A
#define TERM_UCSRB               UCSR1B
#define TERM_UCSRC               UCSR1C
#define TERM_UDR                 UDR1
#define TERM_UBRRH               UBRR1H
#define TERM_UBRRL               UBRR1L
#define TERM_SPEED               19200
#define TERM_TXBUFFER            80

#define LED_OK                   0x01
#define LED_ERROR                0x02
#define LED_GOOD                 0x04
#define LED_DDR                     DDRA
#define LED_PORT                 PORTA

//*****************************************************************************
//                  P R O T O T Y P E
//*****************************************************************************
void main(void);
void Delay(void);

// Term
void TermInit(void);
void TermTxChar(char ch);
void TermTxFlush(void);
void TermTxInt(void);
void TermConstXY(ushort x, ushort y, const char *Ptr);
void TermXY(ushort x, ushort y, char *Ptr);
void TermConstString(const char *ptr);
void TermString(char *ptr);

// Debuger
void DebugInit(void);
void Debuger_RxInt(void);

//*****************************************************************************
//                    G L O B A L   V A R I A B L E
//*****************************************************************************
// Term
char TermTxBuffer[TERM_TXBUFFER];
char *TermTxFill;
char *TermTxFree;
uint TermTxBufferChar;

char Text[512];

//*****************************************************************************
//                            M A I N
//*****************************************************************************
void main()
{
   ushort i;

   SEI();
   TermInit();

   TermConstXY(24,03,"    A    V       V   R R R            \0");
   TermConstXY(24,04,"   A A    V     V    R    R           \0");
   TermConstXY(24,05,"  A   A    V   V     R R R            \0");
   TermConstXY(24,06," A A A A    V V      R    R           \0");
   TermConstXY(24,07,"A       A    V       R     R          \0");

  TermConstXY(6,10,"D D D   E E E E  B B B   U     U   G G G    G G G   E E E E  R R R  \0");
  TermConstXY(6,11,"D    D  E        B    B  U     U  G        G        E        R    R \0");
  TermConstXY(6,12,"D    D  E E E    B   B   U     U  G  G G   G  G G   E E E    R R R  \0");
  TermConstXY(6,13,"D    D  E        B    B  U     U  G     G  G     G  E        R    R \0");
  TermConstXY(6,14,"D D D   E E E E  B B B    U U U    G G G    G G G   E E E E  R     R\0");

   TermConstXY(35,20,"V : 1 . 0\0");

   TermConstXY(23,21,"S y l v a i n   B i s s o n n e t t e\0");

   for (i=0;i<68;i++)
   {
      TermConstXY(6+i,17,"*\0");
      Delay();
      TermConstXY(6+i-1,17," \0");
      Delay();
   }

   TermConstXY(0,0," \0");
   DebugInit();
   while(1);
}

/******************************************************************************

Name:          void Delay(void)

Description:  Delay

Input:         none

Output:        none

Misc:

******************************************************************************/
void Delay(void)
{
   uint i,j;

   for (i=0;i<30000;i++);
}

/******************************************************************************

Name:          void DebugInit(void)

Description:   Setup the serial port

Input:         none

Output:        none

Misc:

******************************************************************************/
void DebugInit(void)
{
   DEBUG_UCSRB = (1<<RXEN0) + (1<<TXEN0) + (1<<RXCIE0);
   DEBUG_UCSRC = (1<<URSEL0) + (1<<UCSZ01) + (1<<UCSZ00) + (1<<UPM01);
   DEBUG_UBRRH = 0;
   DEBUG_UBRRL = 0;
}

/******************************************************************************

Name:          void Debuger_RxInt(void)

Description:   Interrupt from RX of the Debuger Port

Input:         none

Output:        none

Misc:

******************************************************************************/
#pragma interrupt_handler Debuger_RxInt:iv_USART0_RXC
void Debuger_RxInt(void)
{
   char Ch;
   static ushort Lock = TRUE;
   static ushort LockCounter;


   if ((DEBUG_UCSRA & (1<<FE0)) || (DEBUG_UCSRA & (1<<DOR0)) || (DEBUG_UCSRA & (1<<UPE0)))
   {
      Ch = DEBUG_UDR;
      DEBUG_UBRRL++;
   }
   else
   {
      Ch = DEBUG_UDR;
      if (Ch < 0x7f) TermTxChar(Ch);
   }
}

/******************************************************************************

Name:          void TermInit(void)

Description:   Setup the serial port

Input:         none

Output:        none

Misc:

******************************************************************************/
void TermInit(void)
{
   char Buffer[10];

   TermTxFlush();

   TERM_UBRRH = ((XTAL / (16 * TERM_SPEED)) - 1)>>8;
   TERM_UBRRL = (XTAL / (16 * TERM_SPEED)) - 1;

   TERM_UCSRA = 0x00;
   TERM_UCSRB = (1<<TXEN0) + (1<<UDRIE0);
   TERM_UCSRC = (1<<URSEL0) + (1<<UCSZ11) + (1<<UCSZ10);

   TermConstXY(0,0,"\0");
}

/******************************************************************************

Name:         void TermConstXY(ushort x, ushort y, const char *Ptr)

Description:  

Input:        ushort x -> X position to print on the termnal
                     ushort y -> Y position to print on the termnal
                     const char *Ptr-> Pointer of string to be print on the terminal

Output:       none

Misc:        

******************************************************************************/
void TermConstXY(ushort x, ushort y, const char *Ptr)
{
   char Buffer[10];

   if ((x == 0) && (y == 0))
   {
      Buffer[0] = 0x1b;
      Buffer[1] = '[';
      Buffer[2] = '2';
      Buffer[3] = 'J';
      Buffer[4] = 0x00;
      TermString(&Buffer[0]);

      Buffer[0] = 0x1b;
      Buffer[1] = '[';
      Buffer[2] = '1';
      Buffer[3] = ';';
      Buffer[4] = '1';
      Buffer[5] = 'H';
      Buffer[6] = 0x00;
      TermString(&Buffer[0]);
   }
   else
   {
      Buffer[0] = 0x1b;
      Buffer[1] = '[';
      Buffer[2] = (y/10)+48;
      Buffer[3] = (y%10)+48;
      Buffer[4] = ';';
      Buffer[5] = (x/10)+48;
      Buffer[6] = (x%10)+48;
      Buffer[7] = 'f';
      Buffer[8] = 0x00;
      TermString(&Buffer[0]);
      TermConstString(Ptr);
   }
}

/******************************************************************************

Name:         void TermXY(ushort x, ushort y, char *Ptr)

Description:  

Input:        ushort x -> X position to print on the termnal
                     ushort y -> Y position to print on the termnal
                     char *Ptr-> Pointer of string to be print on the terminal

Output:       none

Misc:        

******************************************************************************/
void TermXY(ushort x, ushort y, char *Ptr)
{
   char Buffer[10];

   if ((x == 0) && (y == 0))
   {
      Buffer[0] = 0x1b;
      Buffer[1] = '[';
      Buffer[2] = '2';
      Buffer[3] = 'J';
      Buffer[4] = 0x00;
      TermString(&Buffer[0]);

      Buffer[0] = 0x1b;
      Buffer[1] = '[';
      Buffer[2] = '1';
      Buffer[3] = ';';
      Buffer[4] = '1';
      Buffer[5] = 'H';
      Buffer[6] = 0x00;
      TermString(&Buffer[0]);
   }
   else
   {
      Buffer[0] = 0x1b;
      Buffer[1] = '[';
      Buffer[2] = (y/10)+48;
      Buffer[3] = (y%10)+48;
      Buffer[4] = ';';
      Buffer[5] = (x/10)+48;
      Buffer[6] = (x%10)+48;
      Buffer[7] = 'f';
      Buffer[8] = 0x00;
      TermString(&Buffer[0]);
      TermString(Ptr);
   }
}

/******************************************************************************

Name:          void TermConstString(const char *ptr)

Description:  Send a constant string the serial port

Input:         String Pointer

Output:        none

Misc:

******************************************************************************/
void TermConstString(const char *ptr)
{
   while(*ptr != 0x00)
   {
      TermTxChar(*ptr++);
   }
}

/******************************************************************************

Name:          void TermString(char *ptr)

Description:  Send a string the serial port

Input:         String Pointer

Output:        none

Misc:

******************************************************************************/
void TermString(char *ptr)
{
   while(*ptr != 0x00)
   {
      TermTxChar(*ptr++);
   }
}

/******************************************************************************

Name:          void Term_TxChar(ushort)

Description:  Send a char on the serial port

Input:         char

Output:        none

Misc:

******************************************************************************/
void TermTxChar(char ch)
{
   while(TermTxBufferChar > TERM_TXBUFFER - 2) WDR();

   *TermTxFill++ = ch;
   if (TermTxFill == &TermTxBuffer[TERM_TXBUFFER]) TermTxFill = &TermTxBuffer[0];
   TermTxBufferChar++;
   TERM_UCSRB |= (1<<UDRIE0);
}

/******************************************************************************

Name:         int Term_TxFlush

Description:  This function flush all the Tx buffer

Input:        none

Output:       none

Misc:
******************************************************************************/
void TermTxFlush()
{
  TermTxFill = &TermTxBuffer[0];
  TermTxFree = &TermTxBuffer[0];
  TermTxBufferChar = 0;
}

/******************************************************************************

Name:         void Term_TxInt(void)

Description:  This function is automaticaly when the UDR buffer is empty

Input:        none

Output:       

Misc:
******************************************************************************/
#pragma interrupt_handler Term_TxInt:iv_USART1_UDRE
void Term_TxInt(void)
{
  if (TermTxBufferChar)
  {
    TERM_UDR = *TermTxFree++;
    if (TermTxFree == &TermTxBuffer[TERM_TXBUFFER]) TermTxFree = &TermTxBuffer[0];
    TermTxBufferChar--;
  }
  else TERM_UCSRB &= ~(1<<UDRIE0);   /* TX int empty disable */
}
 

\Code in the target to debug

//*****************************************************************************
// AVR Debuger
// Version 1.0 Fev 2007
//
// Sylvain Bissonnette
//*****************************************************************************
// Editor : UltraEdit32
//*****************************************************************************
//
//                         R E T U R N   S T A C K   1 6
//
//*****************************************************************************
//                      I N C L U D E
//*****************************************************************************
#include <io2313v.h>
#include <macros.h>
#include <shortnametype.h>

//*****************************************************************************
//                      D E F I N E
//*****************************************************************************
#define DEBUG_XTAL                     16000000
#define DEBUG_DDR                DDRD
#define DEBUG_PORT                  PORTD
#define DEBUG_BIT                   0x01

//*****************************************************************************
//                  P R O T O T Y P E
//*****************************************************************************
void main(void);
void DebugXY(ushort x, ushort y, char *Ptr);
void Debug(char *Ptr);
void DebugInit();

//*****************************************************************************
//                    G L O B A L   V A R I A B L E
//*****************************************************************************
char Text[30];

//*****************************************************************************
//                            M A I N
//*****************************************************************************
void main()
{
   uint i;

   Text[0] = 'x';
   Text[1] = 'X';
   Text[2] = 'x';
   Text[3] = 'X';
   Text[4] = 'x';
   Text[5] = 'x';
   Text[6] = 'X';
   Text[7] = 'x';
   Text[8] = 'X';
   Text[9] = 'x';
   Text[10] = 0x00;
   DebugInit();

   while(1)
   {
      DebugXY(19,19,&Text[0]);
      for (i=0;i<60000;i++) WDR();
      DebugXY(0,0,&Text[0]);
   }

}

/******************************************************************************

Name:         void DebugXY(ushort x, ushort y, char *Ptr)

Description: 

Input:        ushort x -> X position to print on the termnal
                     ushort y -> Y position to print on the termnal
                     char *Ptr-> Pointer of string to be print on the terminal

Output:       none

Misc:         168 Byte

******************************************************************************/
void DebugXY(ushort x, ushort y, char *Ptr)
{
   char Buffer[10];

   if ((x == 0) && (y == 0))
   {
      Buffer[0] = 0x1b;
      Buffer[1] = '[';
      Buffer[2] = '2';
      Buffer[3] = 'J';
      Buffer[4] = 0x00;
      Debug(&Buffer[0]);

      Buffer[0] = 0x1b;
      Buffer[1] = '[';
      Buffer[2] = '1';
      Buffer[3] = ';';
      Buffer[4] = '1';
      Buffer[5] = 'H';
      Buffer[6] = 0x00;
      Debug(&Buffer[0]);
   }
   else
   {
      Buffer[0] = 0x1b;
      Buffer[1] = '[';
      Buffer[2] = (y/10)+48;
      Buffer[3] = (y%10)+48;
      Buffer[4] = ';';
      Buffer[5] = (x/10)+48;
      Buffer[6] = (x%10)+48;
      Buffer[7] = 'f';
      Buffer[8] = 0x00;
      Debug(&Buffer[0]);
      Debug(Ptr);
   }
}
/******************************************************************************

Name:         void Debug(char *Ptr)

Description:  *char  Char to be print

Input:        char *Ptr

Output:       none

Misc:         150 Byte

******************************************************************************/
void Debug(char *Ptr)
{
   #define MINDELAY   75  

   int i,j,Parity;


   while(*Ptr != 0)
   {
      CLI();
      DEBUG_PORT &= ~DEBUG_BIT;
      for (j=0;j<MINDELAY;j++);           // Start Bit

      Parity = 0;
      for (i=0;i<8;i++)                      // All 8 Bits
      {
         if (*Ptr & (0x01<<i))
         {
            Parity++;
            DEBUG_PORT |= DEBUG_BIT;
            for (j=0;j<MINDELAY;j++);
         }
         else
         {
            DEBUG_PORT &= ~DEBUG_BIT;
            for (j=0;j<MINDELAY;j++);
         }
      }

      if (Parity%2)
      {
            DEBUG_PORT |= DEBUG_BIT;
            for (j=0;j<MINDELAY;j++);
      }
      else
      {
            DEBUG_PORT &= ~DEBUG_BIT;
            for (j=0;j<MINDELAY;j++);
      }

      DEBUG_PORT |= DEBUG_BIT;
      for (j=0;j<MINDELAY*200;j++); // Stop Bit
      SEI();
      Ptr++;
   }
}

/******************************************************************************

Name:         void DebugInit()

Description: 

Input:       

Output:       none

Misc:        

******************************************************************************/
void DebugInit()
{
   uint i;
   char Buffer[2];

   DEBUG_DDR |= DEBUG_BIT;
   DEBUG_PORT |= DEBUG_BIT;

   Buffer[0] = 0x55;
   Buffer[1] = 0x00;
   for (i=0;i<255;i++) Debug(&Buffer[0]);
   DebugXY(0,0,&Text[0]);
}