📄 jtagrw.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 + -