⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jtagrw.cc

📁 avrrice软件用于AVR单片机的JTAG调试.
💻 CC
字号:
/* *	avarice - The "avarice" program. *	Copyright (C) 2001 Scott Finneran *	Copyright (C) 2002, 2003, 2004 Intel Corporation * *	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 JTAG box. */#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/stat.h>#include <termios.h>#include <fcntl.h>#include <string.h>#include <assert.h>#include "avarice.h"#include "jtag.h"#include "remote.h"/** Return the memory space code for the memory space indicated by the    high-order bits of '*addr'. Also clear these high order bits in '*addr'**/static uchar memorySpace(unsigned long *addr){    int mask;    // We can't just mask the bits off, because 0x10000->0x1ffff are    // valid code addresses    if (*addr & DATA_SPACE_ADDR_OFFSET)    {	mask = *addr & ADDR_SPACE_MASK;	*addr &= ~ADDR_SPACE_MASK;    }    else	mask = 0;    switch (mask)    {    case  EEPROM_SPACE_ADDR_OFFSET: return ADDR_EEPROM_SPACE;    case FUSE_SPACE_ADDR_OFFSET: return ADDR_FUSE_SPACE;    case LOCK_SPACE_ADDR_OFFSET: return ADDR_LOCK_SPACE;    case SIG_SPACE_ADDR_OFFSET: return ADDR_SIG_SPACE;    case BREAKPOINT_SPACE_ADDR_OFFSET: return ADDR_BREAKPOINT_SPACE;    case DATA_SPACE_ADDR_OFFSET: return ADDR_DATA_SPACE;    default: return 0; // program memory, handled specially    }}static void swapBytes(uchar *buffer, int count){    assert(!(count & 1));    for (unsigned int i = 0; i < count; i += 2)    {	uchar temp = buffer[i];	buffer[i] = buffer[i + 1];	buffer[i + 1] = temp;    }}uchar *jtagRead(unsigned long addr, unsigned int numBytes){    uchar *response;    int whichSpace = 0;    uchar command[] = { 'R', 0, 0, 0, 0, 0, JTAG_EOM };     if (numBytes == 0)    {	response = new uchar[1];	response[0] = '\0';	return response;    }    debugOut("jtagRead ");    whichSpace = memorySpace(&addr);    if (whichSpace)    {	command[1] = whichSpace;	if (numBytes > 256)	    return NULL;	command[2] = numBytes - 1;	encodeAddress(&command[3], addr);	// Response will be the number of data bytes with an 'A' at the	// start and end. As such, the response size will be number of bytes	// + 2. Then add an additional byte for the trailing zero (see	// protocol document).	response = doJtagCommand(command, sizeof command, numBytes + 2);	if (response[numBytes + 1] == JTAG_R_OK)	    return response;	delete [] response;	return NULL;    }    else    {	// Reading program memory	whichSpace = programmingEnabled ?	    ADDR_PROG_SPACE_PROG_ENABLED : ADDR_PROG_SPACE_PROG_DISABLED;	// Program space is 16 bits wide, with word reads	int numLocations;	if (addr & 1)	    numLocations = (numBytes + 2) / 2;	else	    numLocations = (numBytes + 1) / 2;	if (numLocations > 256)	    return false;	command[1] = whichSpace;	command[2] = numLocations - 1;	encodeAddress(&command[3], addr / 2);	response = doJtagCommand(command, sizeof command, numLocations * 2 + 2);	if (response[numLocations * 2 + 1] == JTAG_R_OK)	{	    // Programming mode and regular mode are byte-swapped...	    if (!programmingEnabled)		swapBytes(response, numLocations * 2);	    if (addr & 1)		// we read one byte early. move stuff down.		memmove(response, response + 1, numBytes);	    return response;	}    }    delete [] response;        return NULL;}bool jtagWrite(unsigned long addr, unsigned int numBytes, uchar buffer[]){    uchar *response;    int whichSpace = 0;    unsigned int numLocations;    uchar command[] = { 'W', 0, 0, 0, 0, 0, JTAG_EOM };     if (numBytes == 0)	return true;    debugOut("jtagWrite ");    whichSpace = memorySpace(&addr);    if (whichSpace)	numLocations = numBytes;    else    {	// Writing program memory, which is word (16-bit) addressed	// We don't handle odd lengths or start addresses	if ((addr & 1))        {            debugOut ("\nOdd pgm wr addr\n");	    return false;        }        // Odd length: Write one more byte.        if ((numBytes & 1))        {            debugOut ("\nOdd pgm wr length\n");            numBytes+=1;        }	addr /= 2;	numLocations = numBytes / 2;	if (programmingEnabled)	    whichSpace = ADDR_PROG_SPACE_PROG_ENABLED;	else	{	    whichSpace = ADDR_PROG_SPACE_PROG_DISABLED;	    swapBytes(buffer, numBytes);#if 0	    // Doesn't work out of programming mode, as far as I can tell	    // (there's probably some magic that would make it work, but...)	    return false;#endif	}    }    // This is the maximum write size    if (numLocations > 256)	return false;    // Writing is a two part process    // Part 1: send the address    command[1] = whichSpace;    command[2] = numLocations - 1;    encodeAddress(&command[3], addr);    response = doJtagCommand(command, sizeof command, 0);    if (!response)	return false;    delete [] response;    // Part 2: send the data in the following form:    // h [data byte]...[data byte] __    // Before we begin, a little note on the endianness.    // Firstly, data space is 8 bits wide and the only data written by    // this routine will be byte-wide, so endianness does not matter.    // For code space, the data is 16 bit wide. The data appears to be    // formatted big endian in the processor memory. The JTAG box    // expects little endian data. The object files output from GCC are    // already word-wise little endian.    // As this data is already formatted, and currently the only writes    // to program space are for code download, it is simpler at this    // stage to simply pass the data straight through. This may need to    // change in the future.    uchar *txBuffer = new uchar[numBytes + 3]; // allow for header and trailer    txBuffer[0] = 'h';    memcpy(&txBuffer[1], buffer, numBytes);    txBuffer[numBytes + 1] = ' ';    txBuffer[numBytes + 2] = ' ';    response = doJtagCommand(txBuffer, numBytes + 3, 1);    delete [] txBuffer;    if (!response)	return false;    delete [] response;    return true;}void jtagWriteFuses(char *fuses){    int temp[3];    uchar fuseBits[3];    uchar *readfuseBits;    unsigned int c;    check(fuses,          "Error: No fuses string given");    // Convert fuses to hex values (this avoids endianess issues)    c = sscanf(fuses, "%02x%02x%02x", temp+2, temp+1, temp );    check(c == 3,          "Error: Fuses specified are not in hexidecimal");    fuseBits[0] = (uchar)temp[0];    fuseBits[1] = (uchar)temp[1];    fuseBits[2] = (uchar)temp[2];                    statusOut("\nWriting Fuse Bytes:\n");    jtagDisplayFuses(fuseBits);    enableProgramming();        check(jtagWrite(FUSE_SPACE_ADDR_OFFSET + 0, 3, fuseBits),          "Error writing fuses");    readfuseBits = jtagRead(FUSE_SPACE_ADDR_OFFSET + 0, 3);    disableProgramming();    check(memcmp(fuseBits, readfuseBits, 3) == 0,          "Error verifying written fuses");    delete [] readfuseBits;}void jtagReadFuses(void){    uchar *fuseBits = 0;    enableProgramming();    statusOut("\nReading Fuse Bytes:\n");    fuseBits = jtagRead(FUSE_SPACE_ADDR_OFFSET + 0, 3);    disableProgramming();    check(fuseBits, "Error reading fuses");    jtagDisplayFuses(fuseBits);    delete [] fuseBits;}void jtagDisplayFuses(uchar *fuseBits){    statusOut("  Extended Fuse byte -> 0x%02x\n", fuseBits[2]);    statusOut("      High Fuse byte -> 0x%02x\n", fuseBits[1]);    statusOut("       Low Fuse byte -> 0x%02x\n", fuseBits[0]);}void jtagWriteLockBits(char *lock){    int temp[1];    uchar lockBits[1];    uchar *readlockBits;    unsigned int c;    check(lock,          "Error: No lock bit string given");    check(strlen(lock) == 2,          "Error: Fuses must be one byte exactly");    // Convert lockbits to hex value    c = sscanf(lock, "%02x", temp);    check(c == 1,          "Error: Fuses specified are not in hexidecimal");    lockBits[0] = (uchar)temp[0];    statusOut("\nWriting Lock Bits -> 0x%02x\n", lockBits[0]);    enableProgramming();    check(jtagWrite(LOCK_SPACE_ADDR_OFFSET + 0, 1, lockBits),          "Error writing lockbits" );    readlockBits = jtagRead(LOCK_SPACE_ADDR_OFFSET + 0, 1);    disableProgramming();    check(memcmp(lockBits, readlockBits, 1) == 0,          "Error verifying written lock bits");    delete [] readlockBits;}void jtagReadLockBits(void){    uchar *lockBits = 0;    enableProgramming();    statusOut("\nReading Lock Bits:\n");    lockBits = jtagRead(LOCK_SPACE_ADDR_OFFSET + 0, 1);    disableProgramming();    check(lockBits, "Error reading lock bits");    jtagDisplayLockBits(lockBits);    delete [] lockBits;}void jtagDisplayLockBits(uchar *lockBits){    statusOut("Lock bits -> 0x%02x\n\n", lockBits[0]);    statusOut("    Bit 7 [ Reserved ] -> %d\n", (lockBits[0] >> 7) & 1);    statusOut("    Bit 6 [ Reserved ] -> %d\n", (lockBits[0] >> 6) & 1);    statusOut("    Bit 5 [ BLB12    ] -> %d\n", (lockBits[0] >> 5) & 1);    statusOut("    Bit 4 [ BLB11    ] -> %d\n", (lockBits[0] >> 4) & 1);    statusOut("    Bit 3 [ BLB02    ] -> %d\n", (lockBits[0] >> 3) & 1);    statusOut("    Bit 2 [ BLB01    ] -> %d\n", (lockBits[0] >> 2) & 1);    statusOut("    Bit 1 [ LB2      ] -> %d\n", (lockBits[0] >> 1) & 1);    statusOut("    Bit 0 [ LB1      ] -> %d\n", (lockBits[0] >> 0) & 1);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -