Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Tree: 472bf3cf7a
Fetching contributors…

Cannot retrieve contributors at this time

267 lines (228 sloc) 9.429 kB
/*
* avarice - The "avarice" program.
* Copyright (C) 2005,2006,2007 Joerg Wunsch
* Copyright (C) 2007, Colin O'Flynn
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License Version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
* This file extends the generic "jtag" class for the mkII protocol.
*
* $Id: jtag2.h,v 1.16 2008/09/29 20:52:20 joerg_wunsch Exp $
*/
#ifndef JTAG2_H
#define JTAG2_H
#include <vector>
#include "jtag.h"
#include "breakpoint.hh"
/*
* JTAG ICE mkII breakpoints are quite tricky.
*
* There are four possible breakpoint slots in JTAG. The first one is
* always reserved for single-stepping, and cannot be accessed
* directly. The second slot (ID #1) can be freely used as a code
* breakpoint (only). The third and fourth slot can either be used as
* a code breakpoint, as an independent (byte-wide) data breakpoint
* (i.e. a watchpoint in GDB terms), or together as a data breakpoint
* consisting of an address and a mask. The latter does not match
* directly to GDB watchpoints (of a certain lenght > 1) but imposes
* the additional requirement that the base address be aligned
* properly wrt. the mask.
*
* The single-step breakpoint can indirectly be used by filling the
* respective high-level language information into the event memory,
* and issuing a high-level "step over" single-step. As GDB does not
* install the breakpoints for "stepi"-style single-steps (which would
* require the very same JTAG breakpoint register), this ought to
* work.
*
* Finally, there are software breakpoints where the respective
* instruction will be replaced by a BREAK instruction in flash ROM by
* means of an SPM call. Some devices do not allow for this (as they
* are said to be broken), and in general as this method contributes
* to flash wear, we rather do not uninstall and reinstall these
* breakpoints each time GDB asks for it, but instead "cache" them
* locally, and only delete and add them as they actually change.
*
* To add to the mess, GDB's remote protocol isn't very smart about
* telling us whether the next list of breakpoints + resume are
* actually meant to be a high-level language (HLL) single-step
* command. Thus, always assume the last breakpoint that comes in to
* be a single-step breakpoint, and replace the "resume" operation by
* a "step" one in that case. At least, GDB issues the breakpoint
* list in the order of breakpoint numbers, so any possible HLL
* single-step breakoint must be the last one in the list.
*
* Finally, GDB has explicit commands for setting hardware-assisted
* breakpoints, but the default "break" command uses a software
* breakpoint. We try to replace as many software breakpoints as
* possible by hardware breakpoints though, for the sake of
* efficiency, yet would want to respect the user's choice for setting
* a hardware breakpoint ("hbreak" or "thbreak")...
*
* XXX This is not done yet.
*/
enum {
// We distinguish the total possible breakpoints and those for each type
// (code or data) - see above
MAX_BREAKPOINTS2_CODE = 4,
MAX_BREAKPOINTS2_DATA = 2,
MAX_BREAKPOINTS2 = 4,
// various slot #s
BREAKPOINT2_FIRST_DATA = 2,
BREAKPOINT2_DATA_MASK = 3,
MAX_TOTAL_BREAKPOINTS2 = 32
};
struct breakpoint2
{
// High-level information on breakpoint
unsigned int address;
unsigned int mask_pointer;
bpType type;
bool enabled;
// Used to flag end of list
bool last;
// Low-level information on breakpoint
bool icestatus; // Status of breakpoint in ICE itself: 'true'
// when is enabled in ACTUAL device
bool toremove; // Delete this guy in ICE
bool toadd; // Add this guy in ICE
uint8_t bpnum; // ICE's breakpoint number (0x00 for software)
};
const struct breakpoint2 default_bp =
{
0, /* address */
0, /* mask_pointer */
NONE, /* type */
false, /* enabled */
true, /* last */
false, /* icestatus */
false, /* toremove */
false, /* toadd */
0, /* bpnum*/
};
class jtag2: public jtag
{
public:
// Total breakpoints including software
breakpoint2 bp[MAX_TOTAL_BREAKPOINTS2];
private:
unsigned short command_sequence;
int devdescrlen;
bool signedIn;
bool haveHiddenBreakpoint;
bool useDebugWire;
bool is_xmega;
unsigned char flashCache[MAX_FLASH_PAGE_SIZE];
unsigned int flashCachePageAddr;
unsigned char eepromCache[MAX_EEPROM_PAGE_SIZE];
unsigned int eepromCachePageAddr;
breakpoint2 softBPcache[MAX_BREAKPOINTS2];
bool nonbreaking_events[EVT_MAX - EVT_BREAK + 1];
public:
jtag2(const char *dev, char *name, bool useDW = false,
bool is_dragon = false, bool nsrst = false,
bool xmega = false):
jtag(dev, name, is_dragon? EMULATOR_DRAGON: EMULATOR_JTAGICE) {
signedIn = haveHiddenBreakpoint = false;
command_sequence = 0;
devdescrlen = sizeof(jtag2_device_desc_type);
useDebugWire = useDW;
apply_nSRST = nsrst;
is_xmega = xmega;
flashCachePageAddr = (unsigned long)-1;
eepromCachePageAddr = (unsigned short)-1;
for (int i = 0; i < MAX_BREAKPOINTS2; i++)
softBPcache[i].type = NONE;
for (int j = 0; j < MAX_TOTAL_BREAKPOINTS2; j++)
bp[j] = default_bp;
};
virtual ~jtag2(void);
virtual bool isMk2() { return true; }
virtual void initJtagBox(void);
virtual void initJtagOnChipDebugging(unsigned long bitrate);
virtual void deleteAllBreakpoints(void);
virtual bool deleteBreakpoint(unsigned int address, bpType type, unsigned int length);
virtual bool addBreakpoint(unsigned int address, bpType type, unsigned int length);
virtual void updateBreakpoints(void);
virtual bool layoutBreakpoints(void);
virtual bool codeBreakpointAt(unsigned int address);
virtual bool codeBreakpointBetween(unsigned int start, unsigned int end);
virtual bool stopAt(unsigned int address);
virtual void parseEvents(const char *);
virtual void enableProgramming(void);
virtual void disableProgramming(void);
virtual void eraseProgramMemory(void);
virtual void eraseProgramPage(unsigned long address);
virtual void downloadToTarget(const char* filename, bool program, bool verify);
virtual unsigned long getProgramCounter(void);
virtual bool setProgramCounter(unsigned long pc);
virtual bool resetProgram(bool ignored = false);
virtual bool interruptProgram(void);
virtual bool resumeProgram(void);
virtual bool jtagSingleStep(bool useHLL = false);
virtual bool jtagContinue(void);
virtual uint8_t *jtagRead(unsigned long addr, unsigned int numBytes);
virtual bool jtagWrite(unsigned long addr, unsigned int numBytes, uint8_t buffer[]);
private:
virtual void changeBitRate(int newBitRate);
virtual void setDeviceDescriptor(jtag_device_def_type *dev);
virtual bool synchroniseAt(int bitrate);
virtual void startJtagLink(void);
virtual void deviceAutoConfig(void);
virtual void configDaisyChain(void);
void sendFrame(uint8_t *command, int commandSize);
int recvFrame(unsigned char *&msg, unsigned short &seqno);
int recv(unsigned char *&msg);
public:
bool sendJtagCommand(uint8_t *command, int commandSize, int &tries,
uint8_t *&msg, int &msgsize, bool verify = true);
/** Send a command to the jtag, with retries, and return the
'responseSize' byte &response, response size in
&responseSize. If retryOnTimeout is true, retry the command
if no (positive or negative) response arrived in time, abort
after too many retries.
If a negative response arrived, return false, otherwise true.
Caller must delete [] the response.
**/
bool doJtagCommand(uint8_t *command, int commandSize,
uint8_t *&response, int &responseSize,
bool retryOnTimeout = true);
/** Simplified form of doJtagCommand:
Send 1-byte command 'cmd' to JTAG ICE, with retries, expecting a
response that consists only of the status byte which must be
RSP_OK.
**/
void doSimpleJtagCommand(uint8_t cmd);
// Miscellaneous
// -------------
/** Set JTAG ICE parameter 'item' to 'newValue' **/
void setJtagParameter(uint8_t item, uint8_t *newValue, int valSize);
/** Return value of JTAG ICE parameter 'item'; caller must delete
[] resp
**/
void getJtagParameter(uint8_t item, uint8_t *&resp, int &respSize);
uint8_t memorySpace(unsigned long &addr);
/** debugWire version of the breakpoint updater.
**/
void updateBreakpintsDW(void);
private:
/** Wait until either the ICE or GDB issued an event. As this is
the heart of jtagContinue for the mkII, it returns true when a
breakpoint was reached, and false for GDB input.
**/
bool eventLoop(void);
virtual void startPolling();
virtual bool pollDevice(bool *gdbInterrupt, bool *breakpoint);
};
#endif
Jump to Line
Something went wrong with that request. Please try again.