GDB 7.7 introduced range stepping, in combination with the vCont remote
protocol extension. This patch series includes support for these features
and implements them for JTAG ICE mkII devices only, as we only have
documentation for those.
Debugging, especially for single steps and function calls is greatly
increased by this, comparable to AVRStudio on Windows.
>From 66d13dbd0bd2b1cc0b54dd6f9b5b658e55398267 Mon Sep 17 00:00:00 2001
From: Martin Hofmann <[email protected]>
Date: Fri, 14 Mar 2014 16:29:34 +0100
Subject: [PATCH 1/4] Implement setBreakOnChangeOfFlow

To properly implement range stepping later on, the debugger must be
notified of unexpected branches during execution. This parameter may
only be set on mkII devices, as those are the only ones that possibly
can support range stepping.

Leaving the "break on change of flow" flag enabled does not influence
other debug commands like continue: The JTAG ICE does report a break to
GDB, but GDB itself continues, as long as the breakpoint has not been
reached.
---
 avarice/src/jtag.h      | 8 ++++++++
 avarice/src/jtag1.h     | 2 ++
 avarice/src/jtag2.h     | 3 +++
 avarice/src/jtag2run.cc | 6 ++++++
 avarice/src/jtag3.h     | 3 +++
 avarice/src/jtag3run.cc | 7 +++++++
 avarice/src/jtagrun.cc  | 7 +++++++
 7 files changed, 36 insertions(+)

diff --git a/avarice/src/jtag.h b/avarice/src/jtag.h
index 4846ee8..72978d4 100644
--- a/avarice/src/jtag.h
+++ b/avarice/src/jtag.h
@@ -822,6 +822,14 @@ class jtag
 
   unsigned int get_page_size(BFDmemoryType memtype);
 
+  /* Set 'break on change of flow' flag, if supported.
+   *
+   * If the JTAG device supports range stepping, the break on change of flow
+   * flag must be set in the JTAG ICE so that GDB gets notified on jumps and can
+   * automatically step over function calls.
+   */
+  virtual void setBreakOnChangeOfFlow(bool yesno) = 0;
+
   public:
   jtag(void);
   jtag(const char *dev, char *name, emulator type = EMULATOR_JTAGICE);
diff --git a/avarice/src/jtag1.h b/avarice/src/jtag1.h
index 1c91b5d..fa4e9ec 100644
--- a/avarice/src/jtag1.h
+++ b/avarice/src/jtag1.h
@@ -123,6 +123,8 @@ class jtag1: public jtag
         /* no Xmega handling in JTAG ICE mkI */
         return DATA_SPACE_ADDR_OFFSET;
     }
+  protected:
+    virtual void setBreakOnChangeOfFlow(bool yesno);
 
   private:
     virtual void changeBitRate(int newBitRate);
diff --git a/avarice/src/jtag2.h b/avarice/src/jtag2.h
index f763594..fdcf2de 100644
--- a/avarice/src/jtag2.h
+++ b/avarice/src/jtag2.h
@@ -98,6 +98,9 @@ class jtag2: public jtag
         return is_xmega? REGISTER_SPACE_ADDR_OFFSET: DATA_SPACE_ADDR_OFFSET;
     }
 
+  protected:
+    virtual void setBreakOnChangeOfFlow(bool yesno);
+
   private:
     virtual void changeBitRate(int newBitRate);
     virtual void setDeviceDescriptor(jtag_device_def_type *dev);
diff --git a/avarice/src/jtag2run.cc b/avarice/src/jtag2run.cc
index 2dd2617..0408c50 100644
--- a/avarice/src/jtag2run.cc
+++ b/avarice/src/jtag2run.cc
@@ -409,3 +409,9 @@ bool jtag2::jtagContinue(void)
     return eventLoop();
 }
 
+void jtag2::setBreakOnChangeOfFlow(bool yesno)
+{
+    uchar command[1] = { CMND_SET_PARAMETER };
+
+    this->setJtagParameter(PAR_BREAK_ON_CHANGE_FLOW, command, yesno);
+}
diff --git a/avarice/src/jtag3.h b/avarice/src/jtag3.h
index ac61a40..7abb99e 100644
--- a/avarice/src/jtag3.h
+++ b/avarice/src/jtag3.h
@@ -251,6 +251,9 @@ class jtag3: public jtag
         return is_xmega? REGISTER_SPACE_ADDR_OFFSET: DATA_SPACE_ADDR_OFFSET;
     }
 
+  protected:
+    virtual void setBreakOnChangeOfFlow(bool yesno);
+
   private:
     virtual void changeBitRate(int newBitRate);
     virtual bool synchroniseAt(int bitrate);
diff --git a/avarice/src/jtag3run.cc b/avarice/src/jtag3run.cc
index 2ae8b83..2f89d2c 100644
--- a/avarice/src/jtag3run.cc
+++ b/avarice/src/jtag3run.cc
@@ -403,3 +403,10 @@ bool jtag3::jtagContinue(void)
   return eventLoop();
 }
 
+/*
+ * The following method is only supported on mkII devices so far.
+ */
+void jtag3::setBreakOnChangeOfFlow(bool yesno)
+{
+    throw "not implemented";
+}
diff --git a/avarice/src/jtagrun.cc b/avarice/src/jtagrun.cc
index eea4bc3..85e31e6 100644
--- a/avarice/src/jtagrun.cc
+++ b/avarice/src/jtagrun.cc
@@ -218,3 +218,10 @@ bool jtag1::jtagContinue(void)
     }
 }
 
+/*
+ * The following method is only supported on mkII devices so far.
+ */
+void jtag1::setBreakOnChangeOfFlow(bool yesno)
+{
+    throw "not implemented";
+}
-- 
1.9.0

>From 36ce2ef7591467701efad506aecc32551164cfe4 Mon Sep 17 00:00:00 2001
From: Martin Hofmann <[email protected]>
Date: Fri, 14 Mar 2014 16:38:37 +0100
Subject: [PATCH 2/4] Implement run to address method for mkII

mkII devices support a command that allows the JTAG ICE to run until a
certain program counter is reached, without explicitly setting
breakpoints. This patch implements a method for this command.
---
 avarice/src/jtag.h      |  6 ++++++
 avarice/src/jtag1.h     |  3 +++
 avarice/src/jtag2.h     |  2 ++
 avarice/src/jtag2run.cc | 28 ++++++++++++++++++++++++++++
 avarice/src/jtag3.h     |  2 ++
 avarice/src/jtag3run.cc |  7 ++++++-
 avarice/src/jtagrun.cc  |  7 ++++++-
 7 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/avarice/src/jtag.h b/avarice/src/jtag.h
index 72978d4..ef18ddf 100644
--- a/avarice/src/jtag.h
+++ b/avarice/src/jtag.h
@@ -936,6 +936,12 @@ class jtag
       Return true for a breakpoint, false for gdb input. **/
   virtual bool jtagContinue(void) = 0;
 
+  /* Run until the program counter toPC is reached
+   *
+   * Not implemented on all devices, only mkII
+   */
+  virtual bool jtagRunToAddress(unsigned long toPC) = 0;
+
   // R/W memory
   // ----------
 
diff --git a/avarice/src/jtag1.h b/avarice/src/jtag1.h
index fa4e9ec..2112dde 100644
--- a/avarice/src/jtag1.h
+++ b/avarice/src/jtag1.h
@@ -123,6 +123,9 @@ class jtag1: public jtag
         /* no Xmega handling in JTAG ICE mkI */
         return DATA_SPACE_ADDR_OFFSET;
     }
+
+    virtual bool jtagRunToAddress(unsigned long toPC);
+
   protected:
     virtual void setBreakOnChangeOfFlow(bool yesno);
 
diff --git a/avarice/src/jtag2.h b/avarice/src/jtag2.h
index fdcf2de..636692e 100644
--- a/avarice/src/jtag2.h
+++ b/avarice/src/jtag2.h
@@ -98,6 +98,8 @@ class jtag2: public jtag
         return is_xmega? REGISTER_SPACE_ADDR_OFFSET: DATA_SPACE_ADDR_OFFSET;
     }
 
+    virtual bool jtagRunToAddress(unsigned long toPC);
+
   protected:
     virtual void setBreakOnChangeOfFlow(bool yesno);
 
diff --git a/avarice/src/jtag2run.cc b/avarice/src/jtag2run.cc
index 0408c50..d8d1d94 100644
--- a/avarice/src/jtag2run.cc
+++ b/avarice/src/jtag2run.cc
@@ -415,3 +415,31 @@ void jtag2::setBreakOnChangeOfFlow(bool yesno)
 
     this->setJtagParameter(PAR_BREAK_ON_CHANGE_FLOW, command, yesno);
 }
+
+bool jtag2::jtagRunToAddress(unsigned long toPC)
+{
+    uchar *response;
+    int responseSize;
+    uchar command[5] = { CMND_RUN_TO_ADDR };
+
+    this->setBreakOnChangeOfFlow(true);
+
+    u32_to_b4(command + 1, toPC / 2);
+
+    try
+    {
+        doJtagCommand(command, sizeof(command), response, responseSize, true);
+    }
+    catch (jtag_exception& e)
+    {
+        fprintf(stderr, "cannot run to address: %s\n",
+                e.what());
+        throw;
+    }
+
+    delete [] response;
+
+    cached_pc_is_valid = false;
+
+    return eventLoop();
+}
diff --git a/avarice/src/jtag3.h b/avarice/src/jtag3.h
index 7abb99e..c0704f3 100644
--- a/avarice/src/jtag3.h
+++ b/avarice/src/jtag3.h
@@ -251,6 +251,8 @@ class jtag3: public jtag
         return is_xmega? REGISTER_SPACE_ADDR_OFFSET: DATA_SPACE_ADDR_OFFSET;
     }
 
+    virtual bool jtagRunToAddress(unsigned long toPC);
+
   protected:
     virtual void setBreakOnChangeOfFlow(bool yesno);
 
diff --git a/avarice/src/jtag3run.cc b/avarice/src/jtag3run.cc
index 2f89d2c..a3f3a8b 100644
--- a/avarice/src/jtag3run.cc
+++ b/avarice/src/jtag3run.cc
@@ -404,9 +404,14 @@ bool jtag3::jtagContinue(void)
 }
 
 /*
- * The following method is only supported on mkII devices so far.
+ * The following methods are only supported on mkII devices so far.
  */
 void jtag3::setBreakOnChangeOfFlow(bool yesno)
 {
     throw "not implemented";
 }
+
+bool jtag3::jtagRunToAddress(unsigned long toPC)
+{
+    throw "not implemented";
+}
diff --git a/avarice/src/jtagrun.cc b/avarice/src/jtagrun.cc
index 85e31e6..5e7a97d 100644
--- a/avarice/src/jtagrun.cc
+++ b/avarice/src/jtagrun.cc
@@ -219,9 +219,14 @@ bool jtag1::jtagContinue(void)
 }
 
 /*
- * The following method is only supported on mkII devices so far.
+ * The following methods are only supported on mkII devices so far.
  */
 void jtag1::setBreakOnChangeOfFlow(bool yesno)
 {
     throw "not implemented";
 }
+
+bool jtag1::jtagRunToAddress(unsigned long toPC)
+{
+    throw "not implemented";
+}
-- 
1.9.0

>From 9449f62e5a92cb16ddfcb1abc5ea6e894dfe4582 Mon Sep 17 00:00:00 2001
From: Martin Hofmann <[email protected]>
Date: Fri, 14 Mar 2014 16:47:56 +0100
Subject: [PATCH 3/4] Implement flag if device supports range stepping

As only the mkII device seems fit to support range stepping, we need a
flag so we can check in remote.cc (see later patch) if the current
device is capable of using this extension.
---
 avarice/src/jtag.h       | 8 ++++++++
 avarice/src/jtag1.h      | 2 ++
 avarice/src/jtag2.h      | 2 ++
 avarice/src/jtag2misc.cc | 5 ++++-
 avarice/src/jtag3.h      | 2 ++
 avarice/src/jtag3misc.cc | 5 ++++-
 avarice/src/jtagmisc.cc  | 5 ++++-
 7 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/avarice/src/jtag.h b/avarice/src/jtag.h
index ef18ddf..bb2968f 100644
--- a/avarice/src/jtag.h
+++ b/avarice/src/jtag.h
@@ -1031,6 +1031,14 @@ class jtag
   **/
   virtual unsigned int cpuRegisterAreaAddress(void) const = 0;
 
+  /** Determine, if this device supports stepping over multiple assembler cmds
+
+    Returns true if the device supports stepping over multiple commands with
+    the CMND_RUN_TO_ADDR jtag instruction. Returns false otherwise.
+    Necessary, as this functionality is known to be implemented only for the
+    JTAG ICE mkII so far.
+   **/
+  virtual bool deviceSupportsRangeStepping() = 0;
 };
 
 class jtag_exception: public exception
diff --git a/avarice/src/jtag1.h b/avarice/src/jtag1.h
index 2112dde..c8da12c 100644
--- a/avarice/src/jtag1.h
+++ b/avarice/src/jtag1.h
@@ -126,6 +126,8 @@ class jtag1: public jtag
 
     virtual bool jtagRunToAddress(unsigned long toPC);
 
+    virtual bool deviceSupportsRangeStepping();
+
   protected:
     virtual void setBreakOnChangeOfFlow(bool yesno);
 
diff --git a/avarice/src/jtag2.h b/avarice/src/jtag2.h
index 636692e..da37611 100644
--- a/avarice/src/jtag2.h
+++ b/avarice/src/jtag2.h
@@ -100,6 +100,8 @@ class jtag2: public jtag
 
     virtual bool jtagRunToAddress(unsigned long toPC);
 
+    virtual bool deviceSupportsRangeStepping();
+
   protected:
     virtual void setBreakOnChangeOfFlow(bool yesno);
 
diff --git a/avarice/src/jtag2misc.cc b/avarice/src/jtag2misc.cc
index 2c8eca0..c59d3a8 100644
--- a/avarice/src/jtag2misc.cc
+++ b/avarice/src/jtag2misc.cc
@@ -94,4 +94,7 @@ void jtag2::getJtagParameter(uchar item, uchar *&resp, int &respSize)
         throw jtag_exception("unexpected response to get paramater command");
 }
 
-
+bool jtag2::deviceSupportsRangeStepping()
+{
+	return true;
+}
diff --git a/avarice/src/jtag3.h b/avarice/src/jtag3.h
index c0704f3..6a7e187 100644
--- a/avarice/src/jtag3.h
+++ b/avarice/src/jtag3.h
@@ -253,6 +253,8 @@ class jtag3: public jtag
 
     virtual bool jtagRunToAddress(unsigned long toPC);
 
+    virtual bool deviceSupportsRangeStepping();
+
   protected:
     virtual void setBreakOnChangeOfFlow(bool yesno);
 
diff --git a/avarice/src/jtag3misc.cc b/avarice/src/jtag3misc.cc
index 732d9ee..2e53e8a 100644
--- a/avarice/src/jtag3misc.cc
+++ b/avarice/src/jtag3misc.cc
@@ -99,4 +99,7 @@ void jtag3::getJtagParameter(uchar scope, uchar section, uchar item, int length,
   }
 }
 
-
+bool jtag3::deviceSupportsRangeStepping()
+{
+	return false;
+}
diff --git a/avarice/src/jtagmisc.cc b/avarice/src/jtagmisc.cc
index e2566ce..88253b2 100644
--- a/avarice/src/jtagmisc.cc
+++ b/avarice/src/jtagmisc.cc
@@ -69,4 +69,7 @@ uchar jtag1::getJtagParameter(uchar item)
     return result;
 }
 
-
+bool jtag1::deviceSupportsRangeStepping()
+{
+	return false;
+}
-- 
1.9.0

>From 53261f6bfa96810fb7c93cbe09cac9b704d7f7b1 Mon Sep 17 00:00:00 2001
From: Martin Hofmann <[email protected]>
Date: Fri, 14 Mar 2014 16:52:04 +0100
Subject: [PATCH 4/4] Implement range stepping (GDB 7.7+)

The range stepping extension allows GDB to tell AVaRICE to automatically
run instructions in a specific range. This patch greatly increases
performance when debugging using JTAG ICE mkII devices: Previously, GDB
would single step over each assembler instruction. Now, instructions are
run automatically, function calls etc. are handled by GDB without user
interaction.
---
 avarice/src/remote.cc | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/avarice/src/remote.cc b/avarice/src/remote.cc
index 529b376..71ccd07 100644
--- a/avarice/src/remote.cc
+++ b/avarice/src/remote.cc
@@ -1231,7 +1231,60 @@ void talkToGdb(void)
 	    delete [] flashbuf;
 	    ok();
 	}
-	break;
+        else if (strncmp(ptr, "Cont", 4) == 0)
+        {
+            ptr += 4;
+
+            // range stepping relies on device specific instructions
+            if (theJtagICE->deviceSupportsRangeStepping())
+            {
+                if(*ptr == '?')
+                {
+                    // yes, we support the vCont extension
+                    snprintf(remcomOutBuffer, sizeof(remcomOutBuffer),
+                             "vCont;c;C;s;S;t;r");
+                }
+                else if (*ptr == ';')
+                {
+                    // command
+                    ptr++;
+                    switch(*ptr)
+                    {
+                        case 'c':
+                            repStatus(theJtagICE->jtagContinue());
+                            break;
+                        case 'C':
+                            repStatus(theJtagICE->jtagContinue());
+                            break;
+                        case 's':
+                            repStatus(singleStep());
+                            break;
+                        case 'S':
+                            repStatus(singleStep());
+                            break;
+                        case 't':
+                            // the t stop command is only relevant in
+                            // non-stop mode, which we don't support
+                            // can safely be ignored
+                            break;
+                        case 'r':
+                            ptr++;
+                            hexToInt(&ptr, &addr);
+                            ptr++;
+                            hexToInt(&ptr, &addr);
+                            repStatus(theJtagICE->jtagRunToAddress(addr));
+                            break;
+                        default:
+                            debugOut("vCont command not known %c\n", *ptr);
+                    }
+                }
+            }
+            else
+            {
+                // no, send empty reply
+            }
+        }
+        break;
 
     case 'Z':
 	adding = true;
-- 
1.9.0

------------------------------------------------------------------------------
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and their
applications. Written by three acclaimed leaders in the field,
this first edition is now available. Download your free book today!
http://p.sf.net/sfu/13534_NeoTech
_______________________________________________
avarice-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/avarice-user

Reply via email to