📄 jtagpxa250.cpp
字号:
/* * This file is part of Jelie, * (c) 2002 Julien Pilet <julien.pilet@epfl.ch> and * Stephane Magnenat <stephane.magnenat@epfl.ch> * * Jelie is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * Jelie 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 Foobar; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//*! \file * \brief High level PXA250 JTAG commands. * * Using a JTAGControl object to access a jtag port, the JTAGpxa250 class can * pilot a PXA250/210. * * \author Julien Pilet <julien.pilet@epfl.ch> * \author Stephane Magnenat <stephane.magnenat@epfl.ch> */#include <stdio.h>#include <unistd.h> // for sleep() and usleep()#include "jtagpxa250.h"#include "filemanager.h"#include <assert.h>#include <string.h>#ifdef HAVE_CONFIG_H#include "config.h"#endifJTAGpxa250 *pxa250Ptr=0;JTAGpxa250::JTAGpxa250(JTAGControl *jtag) : doPolling(false), isTargetReady(false), jtag(jtag){}void JTAGpxa250::registerTargetReadyCallback(void (*func)(void*), void *arg) { Callback cb; cb.callback = func; cb.arg = arg; targetReadyCallback.push_back(cb);}void JTAGpxa250::unregisterTargetReadyCallback(void (*func)(void*)) { for (std::vector<Callback>::iterator it=targetReadyCallback.begin(); it!=targetReadyCallback.end(); ++it) { if (it->callback == func) { targetReadyCallback.erase(it); return; } }}bool JTAGpxa250::init(int argc, char **argv) { currentIREG= JTAG_UNSET; doPolling = false; return true; // check();}/*! I'm not sure about this method. The work is also done in LoadICCmd::exec(). * Anyway, it might still be usefull. */bool JTAGpxa250::loadDebugHandler() { if (!check()) return false; getReadyForUpload(); FILE *f = fileManagerPtr->openFP(DEBUG_HANDLER_FILE, "rb"); if (!f) { perror(DEBUG_HANDLER_FILE); return false; } else { bool mini = true; unsigned address = 0; unsigned int buffer[2*1024]; // 2kbyte buffer (512 instructions) int nbi = fread(buffer, 4, 2*1024, f); // read instructions little endian format printf("%d instructions read from " DEBUG_HANDLER_FILE "\n", nbi);#ifdef WORDS_BIGENDIAN for (int i=0; i<nbi;i++) { unsigned char *cp= (unsigned char *) &buffer[i]; buffer[i] = JTAGpxa250::charArrayLEToInt(cp); }#endif loadIC(mini, address, buffer, nbi); boot(); return true; }}bool JTAGpxa250::check() { unsigned char idcode = JTAG_IDCODE; unsigned char data[4]={0,0,0,0}; unsigned int datareg=0; jtag->jtagReset(); jtag->trst(false); ireg(idcode); // TODO : fix ugly typecast jtag->dreg(data, 32); datareg=charArrayLEToInt(data); unsigned int jedec = datareg&0xFFF; unsigned int pnum = (datareg& 0xFFFF000) >> 12; unsigned int version = (datareg& 0xF0000000) >> 28; printf("idcode 0x%08x:\n", datareg); if (jedec == 0x13) { switch (pnum) { case 0x9264: printf("PXA250 "); break; case 0x926C: printf("PXA210 "); break; default: printf("Unknown part numer: %x\n", pnum); } printf("version %d detected\n", version); return (pnum == 0x9264); } else { printf("unknown JEDEC type !\n"); return false; }}unsigned int JTAGpxa250::parity(unsigned char data[]) { int nb1=0; for (int b=0; b<4; b++) { for (int i=0; i<=7; i++) { if ((data[b] & (1<<i)) != 0) nb1++; } } // even parity return (nb1 & 1);}void JTAGpxa250::ldic(){ ireg(JTAG_LDIC);}void JTAGpxa250::invalidateMiniIC() { unsigned char data[8]; ldic(); data[0] = 1; // invalidate mini IC command data[1] = 0; data[2] = 0; data[3] = 0; data[4] = parity(data); // parity jtag->dreg(data, 33);}/*! * Invalidate a cache line. A cache line contains 8 instructions, * thus addresses in the range [address, address + 31] will be * invalidated. * * \param address the address to invalidate */void JTAGpxa250::invalidateMainICLine(unsigned int address) { unsigned char data[5]; assert((address & 0x1F) == 0); unsigned char instr = JTAG_LDIC; ireg(instr); data[0] = address & 0xE0; data[1] = (address >> 8); data[2] = (address >> 16); data[3] = (address >> 24); data[4] = parity(data); // parity jtag->dreg(data, 33);}void JTAGpxa250::intToCharArrayLE(unsigned int src, unsigned char dest[]) { for (int i=0; i<4; i++) dest[i] = (src >> (i*8)) & 0xFF;}int JTAGpxa250::charArrayLEToInt(unsigned char src[]) { int res = 0; for (int i=0; i<4; i++) res += src[i] << (i*8); return res;}void JTAGpxa250::loadICLine(bool mini, unsigned int address, unsigned int instructions[]) { // do not use : make sure LDIC is loaded in JTAG ireg // ldic(); assert((address & 0x1F) == 0); unsigned char data[8]; if (mini) { // load mini IC line with command 011 intToCharArrayLE((address << 1) | 0x03, data); data[4] = address >> 31; } else { // load main IC line with command 010 intToCharArrayLE( (address << 1) | 0x02, data); data[4]= address >> 31; } jtag->dreg(data,33); for (int i=0; i<8; i++) { // load each instruction intToCharArrayLE(instructions[i], data); data[4] = parity(data); jtag->dreg(data,33); }}void JTAGpxa250::getReadyForUpload() { // do the steps 1 - 5 described on page 10-35 of "Intel(r) XScale(tm) // Microarchitecture for the PXA250 and PXA210 Applications Processors // user's manual" // 1. assert RESET and TRST. JTAG IR => idcode, invalidates instruction // cache (main & mini). jtag->cpuReset(true); jtag->trst(true); /*unsigned int datareg; datareg=0; jtag->jtagReset(); jtag->dreg((unsigned char *)&datareg, 32); printf("idcode 0x%08x\n", datareg);*/ //check();*/ //jtag->idle(36); jtag->trst(false); check(); //jtag->jtagReset(); jtag->idle(36); //milliSecondsWait(200); //sleep(1); //jtag->trst(false); // 2. DCSR, setup Halt Mode + hold_rst unsigned char instr = JTAG_DCSR; ireg(instr); unsigned char data[8]; unsigned int dcsr = DCSR_GE | DCSR_H; // enable, halt intToCharArrayLE((dcsr << 3) | 0x2, data); // no external debug event, hold_rst data[4] = (dcsr >> 29); //printf("data debut = [%02x] [%02x] [%02x] [%02x] [%02x]\n", data[0], data[1], data[2], data[3], data[4]); jtag->dreg(data, 36); /*intToCharArrayLE(0 | 0x2, data); // no external debug event, hold_rst data[4] = (0); printf("data milieu = [%02x] [%02x] [%02x] [%02x] [%02x]\n", data[0], data[1], data[2], data[3], data[4]); jtag->dreg(data, 36); printf("data fin = [%02x] [%02x] [%02x] [%02x] [%02x]\n", data[0], data[1], data[2], data[3], data[4]); */ // 3. Deassert RESET. The cpu stays in internal reset state. jtag->cpuReset(false); // We need to wait until the onboard MAX has deasserted reset usleep(300000); // 4. wait 2030 TCK jtag->idle(2030); // 5. Load the LDIC instruction into JTAG IR ldic(); // do not mess trying to read something from the target when it's // in internal reset state doPolling = false; // wait a bit //usleep(5000); // ready for IC loading.}void JTAGpxa250::boot() { // 7. wait 15 TCK jtag->idle(15); // 8. clear hold_rst unsigned char instr =JTAG_DCSR; ireg(instr); unsigned char data[8]; unsigned int dcsr = DCSR_GE | DCSR_H | DCSR_TR; // global enable, halt (see page 10-35) intToCharArrayLE(dcsr << 3, data); // no external debug event, clear hold_rst data[4] = (dcsr >> 29); jtag->dreg(data, 36); usleep(10000); doPolling = true; pollForTX(); // done ! the cpu should execute the reset vector at 0.}// This function loads code in the mini or main instruction cache.// it will pad with NOP to have a number of instruction multiple of 8.//// \param mini if true: load in the mini IC. Otherwise: load in the main IC.// \param startAddr address of the 1st instruction. Must be a multiple of 8.// \param instructions array of nbInst instructions // \param nbInst number of instruction in the 'instructions' array// \return true on sucess, false on error (watch the size)bool JTAGpxa250::loadIC(bool mini, unsigned int startAddr, unsigned int instructions[], unsigned int nbInst) { // start address has to be a multiple of 8 instructions (32 bytes) if (startAddr & 0x1F) return false; if (mini) { // the mini IC is 2k big, so there's size for // 64 lines of 8 instructions 32 bits width if (nbInst > 64*8) return false; } else { // the main IC has 32KB
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -