/* * avarice - The "avarice" program. * Copyright (C) 2001 Scott Finneran * Copyright (C) 2002, 2003, 2004 Intel Corporation * Copyright (C) 2005, 2006, 2007 Joerg Wunsch * * 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 contains functions for interfacing with the GDB remote protocol. * * $Id: jtag.h,v 1.27 2007/08/29 11:04:42 joerg_wunsch Exp $ */ #ifndef JTAG_H #define JTAG_H #include #include #include "ioreg.h" /* The data in this structure will be sent directorly to the jtagice box. */ typedef struct { unsigned char cmd; // The jtag command to prefix the desc. /* The following arrays are bitmaps where each bit is a flag denoting wether the register can be read or written. Bit 0 of byte 0 represents the IO register at sram addres 0x20, while bit 7 of byte 7 represents the register at 0x5f. */ unsigned char rd[8]; // IO read access. unsigned char wr[8]; // IO write access. unsigned char sh_rd[8]; // IO shadow read access. unsigned char sh_wr[8]; // IO shadow write access. /* Same as above, except that first bit is register at sram address 0x60 and last bit is register at 0xff. */ unsigned char ext_rd[20]; // Extended IO read access. unsigned char ext_wr[20]; // Extended IO write access. unsigned char ext_sh_rd[20]; // Extended IO shadow read access. unsigned char ext_sh_wr[20]; // Extended IO shadow write access. /* Register locations. */ unsigned char idr_addr; // IDR address in IO space. unsigned char spmcr_addr; // SPMCR address in SRAM space. unsigned char rampz_addr; // RAMPZ address in IO space. /* Memory programming page sizes (in bytes). */ unsigned char flash_pg_sz[2]; // [0]->little end; [1]->big end unsigned char eeprom_pg_sz; unsigned char boot_addr[4]; // Boot loader start address. // This is a WORD address. // [0]->little end; [3]->big end unsigned char last_ext_io_addr; // Last extended IO location, 0 if no // extended IO. unsigned char eom[2]; // JTAG command terminator. } jtag1_device_desc_type; // In appnote AVR067, struct device_descriptor is written with // int/long field types. We cannot use them directly, as they were // neither properly aligned for portability, nor did they care for // endianess issues. We thus use arrays of unsigned chars, plus // conversion macros. typedef struct { unsigned char cmd; // The jtag command to prefix the desc. unsigned char ucReadIO[8]; //LSB = IOloc 0, MSB = IOloc63 unsigned char ucReadIOShadow[8]; //LSB = IOloc 0, MSB = IOloc63 unsigned char ucWriteIO[8]; //LSB = IOloc 0, MSB = IOloc63 unsigned char ucWriteIOShadow[8]; //LSB = IOloc 0, MSB = IOloc63 unsigned char ucReadExtIO[52]; //LSB = IOloc 96, MSB = IOloc511 unsigned char ucReadIOExtShadow[52]; //LSB = IOloc 96, MSB = IOloc511 unsigned char ucWriteExtIO[52]; //LSB = IOloc 96, MSB = IOloc511 unsigned char ucWriteIOExtShadow[52];//LSB = IOloc 96, MSB = IOloc511 unsigned char ucIDRAddress; //IDR address unsigned char ucSPMCRAddress; //SPMCR Register address and dW BasePC unsigned char ucRAMPZAddress; //RAMPZ Register address in SRAM I/O //space unsigned char uiFlashPageSize[2]; //Device Flash Page Size unsigned char ucEepromPageSize; //Device Eeprom Page Size in bytes unsigned char ulBootAddress[4]; //Device Boot Loader Start Address unsigned char uiUpperExtIOLoc[2]; //Topmost (last) extended I/O //location, 0 if no external I/O unsigned char ulFlashSize[4]; //Device Flash Size unsigned char ucEepromInst[20]; //Instructions for W/R EEPROM unsigned char ucFlashInst[3]; //Instructions for W/R FLASH unsigned char ucSPHaddr; // stack pointer high unsigned char ucSPLaddr; // stack pointer low // new as of 16-02-2004 unsigned char uiFlashpages[2]; // number of pages in flash unsigned char ucDWDRAddress; // DWDR register address unsigned char ucDWBasePC; // base/mask value of the PC // new as of 30-04-2004 unsigned char ucAllowFullPageBitstream; // FALSE on ALL new //parts unsigned char uiStartSmallestBootLoaderSection[2]; // // new as of 18-10-2004 unsigned char EnablePageProgramming; // For JTAG parts only, // default TRUE unsigned char ucCacheType; // CacheType_Normal 0x00, // CacheType_CAN 0x01, // CacheType_HEIMDALL 0x02 // new as of 27-10-2004 unsigned char uiSramStartAddr[2]; // Start of SRAM unsigned char ucResetType; // Selects reset type. ResetNormal = 0x00 // ResetAT76CXXX = 0x01 unsigned char ucPCMaskExtended; // For parts with extended PC unsigned char ucPCMaskHigh; // PC high mask unsigned char ucEindAddress; // Selects reset type. [EIND address...] // new as of early 2005, firmware 4.x unsigned char EECRAddress[2]; // EECR IO address } jtag2_device_desc_type; #define fill_b4(u) \ { ((u) & 0xffUL), (((u) & 0xff00UL) >> 8), \ (((u) & 0xff0000UL) >> 16), (((u) & 0xff000000UL) >> 24) } #define fill_b2(u) \ { ((u) & 0xff), (((u) & 0xff00) >> 8) } enum dev_flags { DEVFL_NONE = 0x000000, DEVFL_NO_SOFTBP = 0x000001, // Device cannot use software BPs (no BREAK insn) DEVFL_MKII_ONLY = 0x000002, // Device is only supported in JTAG ICE mkII }; typedef struct { const char* name; const unsigned int device_id; // Part Number from JTAG Device // Identification Register unsigned int flash_page_size; // Flash memory page size in bytes unsigned int flash_page_count; // Flash memory page count unsigned char eeprom_page_size; // EEPROM page size in bytes unsigned int eeprom_page_count; // EEPROM page count unsigned int vectors_end; // End of interrupt vector table enum dev_flags device_flags; // See above. gdb_io_reg_def_type *io_reg_defs; jtag1_device_desc_type dev_desc1; // Device descriptor to download to // mkI device jtag2_device_desc_type dev_desc2; // Device descriptor to download to // mkII device } jtag_device_def_type; extern jtag_device_def_type *global_p_device_def, deviceDefinitions[]; // various enums enum { // Constants common to both mkI and mkII // Address space offsets FLASH_SPACE_ADDR_OFFSET = 0x000000, DATA_SPACE_ADDR_OFFSET = 0x800000, EEPROM_SPACE_ADDR_OFFSET = 0x810000, FUSE_SPACE_ADDR_OFFSET = 0x820000, LOCK_SPACE_ADDR_OFFSET = 0x830000, SIG_SPACE_ADDR_OFFSET = 0x840000, BREAKPOINT_SPACE_ADDR_OFFSET = 0x900000, ADDR_SPACE_MASK = (DATA_SPACE_ADDR_OFFSET | EEPROM_SPACE_ADDR_OFFSET | FUSE_SPACE_ADDR_OFFSET | LOCK_SPACE_ADDR_OFFSET | SIG_SPACE_ADDR_OFFSET | BREAKPOINT_SPACE_ADDR_OFFSET), // JTAG communication timeouts, in microseconds // RESPONSE is for the first response byte // COMM is for subsequent response bytes MAX_JTAG_COMM_ATTEMPS = 10, MAX_JTAG_SYNC_ATTEMPS = 3, JTAG_RESPONSE_TIMEOUT = 1000000, JTAG_COMM_TIMEOUT = 100000, // Lock Bit Values LOCK_BITS_ALL_UNLOCKED = 0xff, // Fuse Bit Values // XXX -- should be configurable, newer devices might no // longer match that fixed pattern. Basically, the pattern // is the ATmega64/128 one. FUSE_M103C = 0x02, FUSE_WDTON = 0x01, FUSE_OCDEN = 0x80, FUSE_JTAGEN = 0x40, FUSE_SPIEN = 0x20, FUSE_CKOPT = 0x10, FUSE_EESAVE = 0x08, FUSE_BOOTSZ1 = 0x04, FUSE_BOOTSZ0 = 0x02, FUSE_BOOTRST = 0x01, FUSE_BODLEVEL = 0x80, FUSE_BODEN = 0x40, FUSE_SUT1 = 0x20, FUSE_SUT0 = 0x10, FUSE_CKSEL3 = 0x08, FUSE_CKSEL2 = 0x04, FUSE_CKSEL1 = 0x02, FUSE_CKSEL0 = 0x01, MAX_FLASH_PAGE_SIZE = 256, MAX_EEPROM_PAGE_SIZE = 16, // JTAG ICE mkI protocol constants // Address space selector values ADDR_PROG_SPACE_PROG_ENABLED = 0xB0, ADDR_PROG_SPACE_PROG_DISABLED = 0xA0, ADDR_DATA_SPACE = 0x20, ADDR_EEPROM_SPACE = 0xB1, ADDR_FUSE_SPACE = 0xB2, ADDR_LOCK_SPACE = 0xB3, ADDR_SIG_SPACE = 0xB4, ADDR_BREAKPOINT_SPACE = 0x60, // Comms link bit rates BIT_RATE_9600 = 0xf4, BIT_RATE_14400 = 0xf8, BIT_RATE_19200 = 0xfa, BIT_RATE_38400 = 0xfd, BIT_RATE_57600 = 0xfe, BIT_RATE_115200 = 0xff, // Breakpoints (match values returned by JTAG box). BREAKPOINT_NONE = 0x00, BREAKPOINT_X = 0x04, BREAKPOINT_Y = 0x08, BREAKPOINT_Z = 0x10, // Responses from JTAG ICE JTAG_R_OK = 'A', JTAG_R_BREAK = 'B', JTAG_R_INFO = 'G', JTAG_R_FAILED = 'F', JTAG_R_SYNC_ERROR = 'E', JTAG_R_SLEEP = 'H', JTAG_R_POWER = 'I', // JTAG parameters JTAG_P_BITRATE = 'b', JTAG_P_SW_VERSION = 0x7b, JTAG_P_HW_VERSION = 0x7a, JTAG_P_IREG_HIGH = 0x81, JTAG_P_IREG_LOW = 0x82, JTAG_P_OCD_VTARGET = 0x84, JTAG_P_OCD_BREAK_CAUSE = 0x85, JTAG_P_CLOCK = 0x86, JTAG_P_EXTERNAL_RESET = 0x8b, /* W */ JTAG_P_FLASH_PAGESIZE_LOW = 0x88, /* W */ JTAG_P_FLASH_PAGESIZE_HIGH = 0x89, /* W */ JTAG_P_EEPROM_PAGESIZE = 0x8a, /* W */ JTAG_P_TIMERS_RUNNING = 0xa0, JTAG_P_BP_FLOW = 0xa1, JTAG_P_BP_X_HIGH = 0xa2, JTAG_P_BP_X_LOW = 0xa3, JTAG_P_BP_Y_HIGH = 0xa4, JTAG_P_BP_Y_LOW = 0xa5, JTAG_P_BP_MODE = 0xa6, JTAG_P_JTAGID_BYTE0 = 0xa7, /* R */ JTAG_P_JTAGID_BYTE1 = 0xa8, /* R */ JTAG_P_JTAGID_BYTE2 = 0xa9, /* R */ JTAG_P_JTAGID_BYTE3 = 0xaa, /* R */ JTAG_P_UNITS_BEFORE = 0xab, /* W */ JTAG_P_UNITS_AFTER = 0xac, /* W */ JTAG_P_BIT_BEFORE = 0xad, /* W */ JTAG_P_BIT_AFTER = 0xae, /* W */ JTAG_P_PSB0_LOW = 0xaf, /* W */ JTAG_P_PSBO_HIGH = 0xb0, /* W */ JTAG_P_PSB1_LOW = 0xb1, /* W */ JTAG_P_PSB1_HIGH = 0xb2, /* W */ JTAG_P_MCU_MODE = 0xb3, /* R */ // JTAG commands JTAG_C_SET_DEVICE_DESCRIPTOR = 0xA0, // Set JTAG bitrate to 1MHz // ff: 1MHz, fe: 500kHz, fd: 250khz, fb: 125Khz // JTAG bitrates JTAG_BITRATE_1_MHz = 0xff, JTAG_BITRATE_500_KHz = 0xfe, JTAG_BITRATE_250_KHz = 0xfd, JTAG_BITRATE_125_KHz = 0xfb, // JTAG ICE mkII stuff goes here. Most of this is straight from // AppNote AVR067. // Communication with the JTAG ICE works in frames. The protocol // somewhat resembles the STK500v2 protocol, yet it is sufficiently // different to prevent a direct code reuse. :-( // // Frame format: // // +---------------------------------------------------------------+ // | 0 | 1 . 2 | 3 . 4 . 5 . 6 | 7 | ... | N-1 . N | // | | | | | | | // | start | LSB MSB | LSB ....... MSB | token | msg | LSB MSB | // | 0x1B | sequence# | message size | 0x0E | | CRC16 | // +---------------------------------------------------------------+ // // Each request message will be returned by a response with a matching // sequence #. Sequence # 0xffff is reserved for asynchronous event // notifications that will be sent by the ICE without a request // message (e.g. when the target hit a breakpoint). // // The message size excludes the framing overhead (10 bytes). // // The first byte of the message is always the request or response // code, which is roughly classified as: // // . Messages (commands) use 0x00 through 0x3f. (The documentation // claims that messages start at 0x01, but actually CMND_SIGN_OFF is // 0x00.) // . Internal commands use 0x40 through 0x7f (not documented). // . Success responses use 0x80 through 0x9f. // . Failure responses use 0xa0 through 0xbf. // . Events use 0xe0 through 0xff. MESSAGE_START = 0x1b, TOKEN = 0x0e, // Max message size we are willing to accept. Prevents us from trying // to allocate too much VM in case we received a nonsensical packet // length. We have to allocate the buffer as soon as we've got the // length information (and thus have to trust that information by that // time at first), as the final CRC check can only be done once the // entire packet came it. MAX_MESSAGE = 100000, // ICE command codes CMND_CHIP_ERASE = 0x13, CMND_CLEAR_EVENTS = 0x22, CMND_CLR_BREAK = 0x1A, CMND_ENTER_PROGMODE = 0x14, CMND_ERASEPAGE_SPM = 0x0D, CMND_FORCED_STOP = 0x0A, CMND_GET_BREAK = 0x12, CMND_GET_PARAMETER = 0x03, CMND_GET_SIGN_ON = 0x01, CMND_GET_SYNC = 0x0f, CMND_GO = 0x08, CMND_LEAVE_PROGMODE = 0x15, CMND_READ_MEMORY = 0x05, CMND_READ_PC = 0x07, CMND_RESET = 0x0B, CMND_RESTORE_TARGET = 0x23, CMND_RUN_TO_ADDR = 0x1C, CMND_SELFTEST = 0x10, CMND_SET_BREAK = 0x11, CMND_SET_DEVICE_DESCRIPTOR = 0x0C, CMND_SET_N_PARAMETERS = 0x16, CMND_SET_PARAMETER = 0x02, CMND_SIGN_OFF = 0x00, CMND_SINGLE_STEP = 0x09, CMND_SPI_CMD = 0x1D, CMND_WRITE_MEMORY = 0x04, CMND_WRITE_PC = 0x06, // ICE responses RSP_DEBUGWIRE_SYNC_FAILED = 0xAC, RSP_FAILED = 0xA0, RSP_GET_BREAK = 0x83, RSP_ILLEGAL_BREAKPOINT = 0xA8, RSP_ILLEGAL_COMMAND = 0xAA, RSP_ILLEGAL_EMULATOR_MODE = 0xA4, RSP_ILLEGAL_JTAG_ID = 0xA9, RSP_ILLEGAL_MCU_STATE = 0xA5, RSP_ILLEGAL_MEMORY_TYPE = 0xA2, RSP_ILLEGAL_MEMORY_RANGE = 0xA3, RSP_ILLEGAL_PARAMETER = 0xA1, RSP_ILLEGAL_POWER_STATE = 0xAD, RSP_ILLEGAL_VALUE = 0xA6, RSP_MEMORY = 0x82, RSP_NO_TARGET_POWER = 0xAB, RSP_OK = 0x80, RSP_PARAMETER = 0x81, RSP_PC = 0x84, RSP_SELFTEST = 0x85, RSP_SET_N_PARAMETERS = 0xA7, RSP_SIGN_ON = 0x86, RSP_SPI_DATA = 0x88, // ICE events EVT_BREAK = 0xE0, EVT_DEBUG = 0xE6, EVT_ERROR_PHY_FORCE_BREAK_TIMEOUT = 0xE2, EVT_ERROR_PHY_MAX_BIT_LENGTH_DIFF = 0xED, EVT_ERROR_PHY_OPT_RECEIVE_TIMEOUT = 0xF9, EVT_ERROR_PHY_OPT_RECEIVED_BREAK = 0xFA, EVT_ERROR_PHY_RECEIVED_BREAK = 0xF8, EVT_ERROR_PHY_RECEIVE_TIMEOUT = 0xF7, EVT_ERROR_PHY_RELEASE_BREAK_TIMEOUT = 0xE3, EVT_ERROR_PHY_SYNC_OUT_OF_RANGE = 0xF5, EVT_ERROR_PHY_SYNC_TIMEOUT = 0xF0, EVT_ERROR_PHY_SYNC_TIMEOUT_BAUD = 0xF4, EVT_ERROR_PHY_SYNC_WAIT_TIMEOUT = 0xF6, EVT_RESULT_PHY_NO_ACTIVITY = 0xFB, EVT_EXT_RESET = 0xE7, EVT_ICE_POWER_ERROR_STATE = 0xEA, EVT_ICE_POWER_OK = 0xEB, EVT_IDR_DIRTY = 0xEC, EVT_NONE = 0xEF, EVT_PDSB_BREAK = 0xF2, EVT_PDSMB_BREAK = 0xF3, EVT_PROGRAM_BREAK = 0xF1, EVT_RUN = 0xE1, EVT_TARGET_POWER_OFF = 0xE5, EVT_TARGET_POWER_ON = 0xE4, EVT_TARGET_SLEEP = 0xE8, EVT_TARGET_WAKEUP = 0xE9, // trailer EVT_MAX = 0xFF, // memory types for CMND_{READ,WRITE}_MEMORY MTYPE_IO_SHADOW = 0x30, // cached IO registers? MTYPE_SRAM = 0x20, // target's SRAM or [ext.] IO registers MTYPE_EEPROM = 0x22, // EEPROM, what way? MTYPE_EVENT = 0x60, // ICE event memory MTYPE_EVENT_COMPRESSED = 0x61, // ICE event memory, bit-mapped MTYPE_SPM = 0xA0, // flash through LPM/SPM MTYPE_FLASH_PAGE = 0xB0, // flash in programming mode MTYPE_EEPROM_PAGE = 0xB1, // EEPROM in programming mode MTYPE_FUSE_BITS = 0xB2, // fuse bits in programming mode MTYPE_LOCK_BITS = 0xB3, // lock bits in programming mode MTYPE_SIGN_JTAG = 0xB4, // signature in programming mode MTYPE_OSCCAL_BYTE = 0xB5, // osccal cells in programming mode MTYPE_CAN = 0xB6, // CAN mailbox // (some) ICE parameters, for CMND_{GET,SET}_PARAMETER PAR_HW_VERSION = 0x01, PAR_FW_VERSION = 0x02, PAR_EMULATOR_MODE = 0x03, EMULATOR_MODE_DEBUGWIRE = 0x00, EMULATOR_MODE_JTAG = 0x01, EMULATOR_MODE_UNKNOWN = 0x02, EMULATOR_MODE_SPI = 0x03, PAR_IREG = 0x04, PAR_BAUD_RATE = 0x05, PAR_BAUD_2400 = 0x01, PAR_BAUD_4800 = 0x02, PAR_BAUD_9600 = 0x03, PAR_BAUD_19200 = 0x04, // default PAR_BAUD_38400 = 0x05, PAR_BAUD_57600 = 0x06, PAR_BAUD_115200 = 0x07, PAR_BAUD_14400 = 0x08, PAR_OCD_VTARGET = 0x06, PAR_OCD_JTAG_CLK = 0x07, PAR_OCD_BREAK_CAUSE = 0x08, PAR_TIMERS_RUNNING = 0x09, PAR_BREAK_ON_CHANGE_FLOW = 0x0A, PAR_BREAK_ADDR1 = 0x0B, PAR_BREAK_ADDR2 = 0x0C, PAR_COMBBREAKCTRL = 0x0D, PAR_JTAGID = 0x0E, PAR_UNITS_BEFORE = 0x0F, PAR_UNITS_AFTER = 0x10, PAR_BIT_BEFORE = 0x11, PAR_BIT_ATER = 0x12, PAR_EXTERNAL_RESET = 0x13, PAR_FLASH_PAGE_SIZE = 0x14, PAR_EEPROM_PAGE_SIZE = 0x15, PAR_UNUSED1 = 0x16, PAR_PSB0 = 0x17, PAR_PSB1 = 0x18, PAR_PROTOCOL_DEBUG_EVENT = 0x19, PAR_MCU_STATE = 0x1A, STOPPED = 0x00, RUNNING = 0x01, PROGRAMMING = 0x02, PAR_DAISY_CHAIN_INFO = 0x1B, PAR_BOOT_ADDRESS = 0x1C, PAR_TARGET_SIGNATURE = 0x1D, PAR_DEBUGWIRE_BAUDRATE = 0x1E, PAR_PROGRAM_ENTRY_POINT = 0x1F, PAR_PACKET_PARSING_ERRORS = 0x40, PAR_VALID_PACKETS_RECEIVED = 0x41, PAR_INTERCOMMUNICATION_TX_FAILURES = 0x42, PAR_INTERCOMMUNICATION_RX_FAILURES = 0x43, PAR_CRC_ERRORS = 0x44, PAR_POWER_SOURCE = 0x45, POWER_EXTERNAL = 0x00, POWER_USB = 0x01, PAR_CAN_FLAG = 0x22, DONT_READ_CAN_MAILBOX = 0x00, READ_CAN_MAILBOX = 0x01, PAR_ENABLE_IDR_IN_RUN_MODE = 0x23, ACCESS_OSCCAL = 0x00, ACCESS_IDR = 0x01, PAR_ALLOW_PAGEPROGRAMMING_IN_SCANCHAIN = 0x24, PAGEPROG_NOT_ALLOWED = 0x00, PAGEPROG_ALLOWED = 0x01, }; enum { PC_INVALID = 0xffffffff }; enum bpType { NONE, // disabled. CODE, // normal code space breakpoint. SOFTCODE, // code software BP (not yet used). WRITE_DATA, // write data space breakpoint (ie "watch"). READ_DATA, // read data space breakpoint (ie "watch"). ACCESS_DATA, // read/write data space breakpoint (ie "watch"). DATA_MASK, // mask for data space breakpoint. // keep mask bits last HAS_MASK = 0x80000000, // data space BP has an associated mask in // next slot }; // Enumerations for target memory type. typedef enum { MEM_FLASH = 0, MEM_EEPROM = 1, MEM_RAM = 2, } BFDmemoryType; extern const char *BFDmemoryTypeString[]; extern const int BFDmemorySpaceOffset[]; enum emulator { EMULATOR_JTAGICE, EMULATOR_DRAGON, }; // Allocate 1 meg for image buffer. This is where the file data is // stored before writing occurs. #define MAX_IMAGE_SIZE 1000000 typedef struct { uchar val; bool used; } AVRMemoryByte; // Struct that holds the memory image. We read from file using BFD // into this struct, then pass the entire struct to the target writer. typedef struct { AVRMemoryByte image[MAX_IMAGE_SIZE]; int last_address; int first_address; bool first_address_ok; bool has_data; const char *name; } BFDimage; // The Sync_CRC/EOP message terminator (no real CRC in sight...) #define JTAG_EOM 0x20, 0x20 // A generic error message when nothing good comes to mind #define JTAG_CAUSE "JTAG ICE communication failed" class jtag { protected: // The initial serial port parameters. We restore them on exit. struct termios oldtio; bool oldtioValid; // The file descriptor used while talking to the JTAG ICE int jtagBox; // For the mkII device, is the box attached via USB? bool is_usb; // A control pipe to talk to the USB daemon. int ctrlPipe; // The type of our emulator: JTAG ICE, or AVR Dragon. emulator emu_type; public: // Whether we are in "programming mode" (changes how program memory // is written, apparently) bool programmingEnabled; // Name of the device controlled by the JTAG ICE char *device_name; // Daisy chain info struct { unsigned char units_before; unsigned char units_after; unsigned char bits_before; unsigned char bits_after; } dchain; protected: pid_t openUSB(const char *jtagDeviceName); int safewrite(const void *b, int count); void changeLocalBitRate(int newBitRate); void restoreSerialPort(void); virtual void changeBitRate(int newBitRate) = 0; virtual void setDeviceDescriptor(jtag_device_def_type *dev) = 0; virtual bool synchroniseAt(int bitrate) = 0; virtual void startJtagLink(void) = 0; virtual void deviceAutoConfig(void) = 0; void jtag_flash_image(BFDimage *image, BFDmemoryType memtype, bool program, bool verify); // Return page address of unsigned int page_addr(unsigned int addr, BFDmemoryType memtype) { unsigned int page_size = get_page_size( memtype ); return (unsigned int)(addr & (~(page_size - 1))); }; unsigned int get_page_size(BFDmemoryType memtype); public: jtag(void); jtag(const char *dev, char *name, emulator type = EMULATOR_JTAGICE); virtual ~jtag(void); // Basic JTAG I/O // ------------- /** If status < 0: Report JTAG ICE communication error & exit **/ void jtagCheck(int status); /** Send initial configuration to setup the JTAG box itself. **/ virtual void initJtagBox(void) = 0; /** Send initial configuration to the JTAG box when starting a new debug session. (Note: when attaching to a running target, fuse bits cannot be set so debugging must have been enabled earlier) The bitrate sets the JTAG bitrate. The bitrate must be less than 1/4 that of the target avr frequency or the jtagice will have problems reading from the target. The problems are usually manifested as failed calls to jtagRead(). **/ virtual void initJtagOnChipDebugging(unsigned long bitrate) = 0; /** A timed-out read from file descriptor 'fd'. 'timeout' is in microseconds, it is the maximum interval within which the read must make progress (i.e., it's a per-byte timeout) Returns the number of bytes read or -1 for errors other than timeout. Note: EOF and timeout cannot be distinguished **/ int timeout_read(void *buf, size_t count, unsigned long timeout); // Breakpoints // ----------- /** Clear out the breakpoints. */ virtual void deleteAllBreakpoints(void) = 0; /** Delete breakpoint at the specified address. */ virtual bool deleteBreakpoint(unsigned int address, bpType type, unsigned int length) = 0; /** Add a code breakpoint at the specified address. */ virtual bool addBreakpoint(unsigned int address, bpType type, unsigned int length) = 0; /** Send the breakpoint details down to the JTAG box. */ virtual void updateBreakpoints(void) = 0; /** True if there is a breakpoint at address */ virtual bool codeBreakpointAt(unsigned int address) = 0; /** True if there is a breakpoint between start (inclusive) and end (exclusive) */ virtual bool codeBreakpointBetween(unsigned int start, unsigned int end) = 0; virtual bool stopAt(unsigned int address) = 0; /** Parse a list of event names to *not* cause a break. */ virtual void parseEvents(const char *) = 0; // Writing to program memory // ------------------------- /** Switch to faster programming mode, allows chip erase */ virtual void enableProgramming(void) = 0; /** Switch back to normal programming mode **/ virtual void disableProgramming(void) = 0; /** Erase all chip memory **/ virtual void eraseProgramMemory(void) = 0; virtual void eraseProgramPage(unsigned long address) = 0; /** Download an image contained in the specified file. */ virtual void downloadToTarget(const char* filename, bool program, bool verify) = 0; // Running, single stepping, etc // ----------------------------- /** Retrieve the current Program Counter value, or PC_INVALID if fails */ virtual unsigned long getProgramCounter(void) = 0; /** Set program counter to 'pc'. Return true iff successful **/ virtual bool setProgramCounter(unsigned long pc) = 0; /** Reset AVR. Return true iff successful **/ virtual bool resetProgram(void) = 0; /** Interrupt AVR. Return true iff successful **/ virtual bool interruptProgram(void) = 0; /** Resume program execution. Return true iff successful. Note: the gdb 'continue' command is handled by jtagContinue, this is just the low level command to resume after interruptProgram **/ virtual bool resumeProgram(void) = 0; /** Issue a "single step" command to the JTAG box. Return true iff successful **/ virtual bool jtagSingleStep(bool useHLL = false) = 0; /** Send the program on it's merry way, and wait for a breakpoint or input from gdb. Return true for a breakpoint, false for gdb input. **/ virtual bool jtagContinue(void) = 0; // R/W memory // ---------- /** Read 'numBytes' from target memory address 'addr'. The memory space is selected by the high order bits of 'addr' (see above). Returns a dynamically allocated buffer with the requested bytes if successful (caller must free), or NULL if the read failed. **/ virtual uchar *jtagRead(unsigned long addr, unsigned int numBytes) = 0; /** Write 'numBytes' bytes from 'buffer' to target memory address 'addr' The memory space is selected by the high order bits of 'addr' (see above). Returns true for a successful write, false for a failed one. Note: The current behaviour for program-space writes is pretty weird (does not match jtagRead). See comments in jtagrw.cc. **/ virtual bool jtagWrite(unsigned long addr, unsigned int numBytes, uchar buffer[]) = 0; /** Write fuses to target. The input parameter is a string from command-line, as produced by printf("%x", 0xaabbcc ); **/ void jtagWriteFuses(char *fuses); /** Read fuses from target. Shows extended, high and low fuse byte. */ void jtagReadFuses(void); /** Display fuses. Shows extended, high and low fuse byte. */ void jtagDisplayFuses(uchar *fuseBits); /** Write lockbits to target. The input parameter is a string from command-line, as produced by printf("%x", 0xaa); **/ void jtagWriteLockBits(char *lock); /** Read the lock bits from the target and display them. **/ void jtagReadLockBits(void); /** Display lockbits. Shows raw value and individual bits. **/ void jtagDisplayLockBits(uchar *lockBits); }; extern struct jtag *theJtagICE; #endif