Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

jtagpxa250.cpp

Go to the documentation of this file.
00001 /*
00002  * This file is part of Jelie,
00003  * (c) 2002 Julien Pilet <julien.pilet@epfl.ch> and
00004  * Stephane Magnenat <stephane.magnenat@epfl.ch>
00005  *
00006  * Jelie is free software; you can redistribute it
00007  * and/or modify it under the terms of the GNU General Public License as
00008  * published by the Free Software Foundation; either version 2 of the License,
00009  * or (at your option) any later version.
00010  *
00011  * Jelie is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with Foobar; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00031 #include <stdio.h>
00032 #include <unistd.h> // for sleep() and usleep()
00033 #include "jtagpxa250.h"
00034 #include "filemanager.h"
00035 #include <assert.h>
00036 #include <string.h>
00037 #ifdef HAVE_CONFIG_H
00038 #include "config.h"
00039 #endif
00040 
00041 JTAGpxa250 *pxa250Ptr=0;
00042 
00043 JTAGpxa250::JTAGpxa250(JTAGControl *jtag) : 
00044         doPolling(false),
00045         isTargetReady(false), jtag(jtag)
00046 {
00047 }
00048 
00049 void JTAGpxa250::registerTargetReadyCallback(void (*func)(void*), void *arg) {
00050         Callback cb;
00051         cb.callback = func;
00052         cb.arg = arg;
00053         targetReadyCallback.push_back(cb);
00054 }
00055 
00056 void JTAGpxa250::unregisterTargetReadyCallback(void (*func)(void*)) {
00057         for (std::vector<Callback>::iterator it=targetReadyCallback.begin(); it!=targetReadyCallback.end(); ++it)
00058         {
00059                 if (it->callback == func)
00060                 {
00061                         targetReadyCallback.erase(it);
00062                         return;
00063                 }
00064         }
00065 }
00066 
00067 bool JTAGpxa250::init(int argc, char **argv) {
00068         currentIREG= JTAG_UNSET;
00069         doPolling = false;
00070         return true; // check();
00071 }
00072 
00076 bool JTAGpxa250::loadDebugHandler() {
00077         if (!check())
00078                 return false;
00079 
00080         getReadyForUpload();
00081 
00082         FILE *f = fileManagerPtr->openFP(DEBUG_HANDLER_FILE, "rb");
00083 
00084         if (!f) {
00085                 perror(DEBUG_HANDLER_FILE);
00086                 return false;
00087         } else {
00088                 bool mini = true;
00089                 unsigned address = 0;
00090                 unsigned int buffer[2*1024];    // 2kbyte buffer (512 instructions)
00091                 int nbi = fread(buffer, 4, 2*1024, f);  // read instructions little endian format
00092                 printf("%d instructions read from " DEBUG_HANDLER_FILE "\n", nbi);
00093 
00094 #ifdef WORDS_BIGENDIAN
00095                 for (int i=0; i<nbi;i++) {
00096                         unsigned char *cp= (unsigned char *) &buffer[i];
00097                         buffer[i] = JTAGpxa250::charArrayLEToInt(cp);
00098                 }
00099 #endif
00100                 loadIC(mini, address, buffer, nbi);
00101                 boot();
00102                 return true;
00103         }
00104 
00105 }
00106 
00107 bool JTAGpxa250::check() {
00108 
00109         unsigned char idcode = JTAG_IDCODE;
00110         unsigned char data[4]={0,0,0,0};
00111         unsigned int datareg=0;
00112         jtag->jtagReset();
00113         jtag->trst(false);
00114         ireg(idcode);
00115         // TODO : fix ugly typecast
00116         jtag->dreg(data, 32);
00117         datareg=charArrayLEToInt(data);
00118 
00119         unsigned int jedec = datareg&0xFFF;
00120         unsigned int pnum = (datareg& 0xFFFF000) >> 12;
00121         unsigned int version = (datareg& 0xF0000000) >> 28;
00122         printf("idcode 0x%08x:\n", datareg);
00123 
00124         if (jedec == 0x13) {
00125                 switch (pnum) {
00126                         case 0x9264: printf("PXA250 ");
00127                                                  break;
00128                         case 0x926C: printf("PXA210 ");
00129                                                  break;
00130                         default:
00131                                                  printf("Unknown part numer: %x\n", pnum);
00132                 }
00133                 printf("version %d detected\n", version);
00134                 return (pnum == 0x9264);
00135         } else {
00136                 printf("unknown JEDEC type !\n");
00137                 return false;
00138         }
00139 }
00140 
00141 unsigned int JTAGpxa250::parity(unsigned char data[]) {
00142         int nb1=0;
00143 
00144         for (int b=0; b<4; b++) {
00145                 for (int i=0; i<=7; i++) {
00146                         if ((data[b] & (1<<i)) != 0)
00147                                 nb1++;
00148                 }
00149         }
00150 
00151         // even parity
00152         return (nb1 & 1);
00153 }
00154 
00155 void JTAGpxa250::ldic()
00156 {
00157         ireg(JTAG_LDIC);
00158 }
00159 
00160 void JTAGpxa250::invalidateMiniIC() {
00161         unsigned char data[8];
00162 
00163         ldic();
00164         data[0] = 1; // invalidate mini IC command
00165         data[1] = 0;
00166         data[2] = 0;
00167         data[3] = 0;
00168         data[4] = parity(data); // parity
00169         jtag->dreg(data, 33);
00170 }
00171 
00179 void JTAGpxa250::invalidateMainICLine(unsigned int address) {
00180         unsigned char data[5];
00181 
00182         assert((address & 0x1F) == 0);
00183 
00184         unsigned char instr = JTAG_LDIC;
00185         ireg(instr);
00186 
00187         data[0] = address & 0xE0;
00188         data[1] = (address >> 8);
00189         data[2] = (address >> 16);
00190         data[3] = (address >> 24);
00191         data[4] = parity(data); // parity
00192         jtag->dreg(data, 33);
00193 }
00194 
00195 void JTAGpxa250::intToCharArrayLE(unsigned int src, unsigned char dest[]) {
00196         for (int i=0; i<4; i++)
00197                 dest[i] = (src >> (i*8)) & 0xFF;
00198 }
00199 
00200 int JTAGpxa250::charArrayLEToInt(unsigned char src[]) {
00201         int res = 0;
00202         for (int i=0; i<4; i++)
00203                 res += src[i] << (i*8);
00204         return res;
00205 }
00206 
00207 void JTAGpxa250::loadICLine(bool mini,
00208                 unsigned int address, unsigned int instructions[]) {
00209         // do not use : make sure LDIC is loaded in JTAG ireg
00210         // ldic();
00211 
00212         assert((address & 0x1F) == 0);
00213         unsigned char data[8];
00214 
00215         if (mini) {
00216                 // load mini IC line with command 011
00217                 intToCharArrayLE((address << 1) | 0x03, data);
00218                 data[4] = address >> 31;
00219         } else {
00220                 // load main IC line with command 010
00221                 intToCharArrayLE( (address << 1) | 0x02, data);
00222                 data[4]= address >> 31;
00223         }
00224         jtag->dreg(data,33);
00225 
00226         for (int i=0; i<8; i++) {
00227                 // load each instruction
00228                 intToCharArrayLE(instructions[i], data);
00229                 data[4] = parity(data);
00230                 jtag->dreg(data,33);
00231         }
00232 }
00233 
00234 void JTAGpxa250::getReadyForUpload() {
00235 
00236         // do the steps 1 - 5 described on page 10-35 of "Intel(r) XScale(tm)
00237         // Microarchitecture for the PXA250 and PXA210 Applications Processors
00238         // user's manual"
00239 
00240         // 1. assert RESET and TRST. JTAG IR => idcode, invalidates instruction
00241         // cache (main & mini).
00242         jtag->cpuReset(true);
00243         jtag->trst(true);
00244 
00245         /*unsigned int datareg;
00246         datareg=0;
00247         jtag->jtagReset();
00248         jtag->dreg((unsigned char *)&datareg, 32);
00249         printf("idcode 0x%08x\n", datareg);*/
00250         //check();*/
00251         //jtag->idle(36);
00252 
00253         jtag->trst(false);
00254 
00255         check();
00256         //jtag->jtagReset();
00257         jtag->idle(36);
00258 
00259         //milliSecondsWait(200);
00260         //sleep(1);
00261         //jtag->trst(false);
00262 
00263         // 2. DCSR, setup Halt Mode + hold_rst
00264         unsigned char instr = JTAG_DCSR;
00265         ireg(instr);
00266         unsigned char data[8];
00267         unsigned int dcsr = DCSR_GE | DCSR_H; // enable, halt
00268         intToCharArrayLE((dcsr << 3) | 0x2, data); // no external debug event, hold_rst
00269         data[4] = (dcsr >> 29);
00270 
00271         //printf("data debut = [%02x] [%02x] [%02x] [%02x] [%02x]\n", data[0], data[1], data[2], data[3], data[4]);
00272         jtag->dreg(data, 36);
00273 
00274         /*intToCharArrayLE(0 | 0x2, data); // no external debug event, hold_rst
00275         data[4] = (0);
00276 
00277         printf("data milieu = [%02x] [%02x] [%02x] [%02x] [%02x]\n", data[0], data[1], data[2], data[3], data[4]);
00278         jtag->dreg(data, 36);
00279 
00280         printf("data fin = [%02x] [%02x] [%02x] [%02x] [%02x]\n", data[0], data[1], data[2], data[3], data[4]);
00281         */
00282 
00283         // 3. Deassert RESET. The cpu stays in internal reset state.
00284         jtag->cpuReset(false);
00285 
00286         // We need to wait until the onboard MAX has deasserted reset
00287         usleep(300000);
00288 
00289         // 4. wait 2030 TCK
00290         jtag->idle(2030);
00291 
00292         // 5. Load the LDIC instruction into JTAG IR
00293         ldic();
00294 
00295         // do not mess trying to read something from the target when it's
00296         // in internal reset state
00297         doPolling = false;
00298 
00299         // wait a bit
00300         //usleep(5000);
00301 
00302         // ready for IC loading.
00303 }
00304 
00305 void JTAGpxa250::boot() {
00306 
00307         // 7. wait 15 TCK
00308         jtag->idle(15);
00309 
00310         // 8. clear hold_rst
00311         unsigned char instr =JTAG_DCSR;
00312         ireg(instr);
00313         unsigned char data[8];
00314         unsigned int dcsr = DCSR_GE | DCSR_H | DCSR_TR; // global enable, halt (see page 10-35)
00315         intToCharArrayLE(dcsr << 3, data); // no external debug event, clear hold_rst
00316         data[4] = (dcsr >> 29);
00317         jtag->dreg(data, 36);
00318 
00319         usleep(10000);
00320         doPolling = true;
00321         pollForTX();
00322 
00323         // done ! the cpu should execute the reset vector at 0.
00324 }
00325 
00326 //  This function loads code in the mini or main instruction cache.
00327 //  it will pad with NOP to have a number of instruction multiple of 8.
00328 //
00329 //  \param mini if true: load in the mini IC. Otherwise: load in the main IC.
00330 //  \param startAddr    address of the 1st instruction. Must be a multiple of 8.
00331 //  \param instructions array of nbInst instructions 
00332 //  \param nbInst       number of instruction in the 'instructions' array
00333 //  \return true on sucess, false on error (watch the size)
00334 bool JTAGpxa250::loadIC(bool mini, unsigned int startAddr, unsigned int instructions[],
00335                 unsigned int nbInst) {
00336 
00337         // start address has to be a multiple of 8 instructions (32 bytes)
00338         if (startAddr & 0x1F) return false;
00339         
00340         if (mini) {
00341                 // the mini IC is 2k big, so there's size for
00342                 // 64 lines of 8 instructions 32 bits width
00343                 if (nbInst > 64*8) return false;
00344         } else {
00345                 // the main IC has 32KB
00346                 // there's 1024 lines of 8 instructions 32 bits width
00347                 if (nbInst > 8*1024) return false;
00348         }
00349 
00350         unsigned int addr = startAddr;
00351 
00352         unsigned int i;
00353         for (i=0; i+8 < nbInst ; i+=8) {
00354                 loadICLine(mini, addr, instructions + i);
00355                 printf("\r%d on %d instructions loaded.         ", i+8, nbInst);
00356                 fflush(stdout);
00357                 addr += 8*4;
00358         }
00359 
00360         unsigned int remain = nbInst % 8;
00361         if (remain) {
00362                 unsigned int data[8]; // buffer, filled with nop.
00363                 for (unsigned int j=0; j<8; j++) { 
00364                         if (j < remain)
00365                                 data[j] = instructions[ nbInst - remain + j ];
00366                         else 
00367                                 data[j] = 0x0000A0E1; // NOP (?)
00368                 }
00369                 printf("adding %d nops\n", 8 - remain);
00370                 loadICLine(mini, addr, data);
00371         }
00372         printf("\r%d instructions successfully loaded.             \n", nbInst);
00373 
00374         return true; // everything went ok.
00375 }
00376 
00377 // returs true on success, false on error
00378 bool JTAGpxa250::writeRX(unsigned int val)
00379 {
00380         unsigned char cdata[5]; // 36 bits needs 5 bytes
00381         int retryCount=0;
00382         
00383         // Issue JTAG DBGRX Command
00384         ireg(JTAG_DBGRX);
00385 
00386         do {
00387                 // set dbg. d and dbg.flush to 0
00388                 intToCharArrayLE((val << 3) | 0x0, cdata);
00389                 cdata[4] = (val >> 29);
00390                 // set dbg.v to 1
00391                 cdata[4] |= 0x8;
00392                 // write 36 bits
00393                 jtag->dreg(cdata, 36);
00394 
00395                 if (retryCount)
00396                 {
00397                         printf("\rJTAG : writeRX : Retry to put jtag-data [%08x] (retry %d)       ", val, retryCount);
00398                         fflush(stdout);
00399                 }
00400                 if (++retryCount > MAX_RETRY_COUNT) 
00401                 {
00402                         printf("\nJTAG : writeRX : Writing RX failed\n");
00403                         return false;
00404                 }
00405 
00406         } while ( cdata[0]&0x1 );
00407 
00408         return true;
00409 }
00410 
00412 void JTAGpxa250::fastWriteRX(unsigned int val, bool cont)
00413 {
00414         unsigned char cdata[5]; // 36 bits needs 5 bytes
00415 
00416         // set dbg. d to one and dbg.flush to 0
00417         intToCharArrayLE((val << 3) | ((cont) ? 0x4 : 0x0) , cdata);
00418         cdata[4] = (val >> 29);
00419         // set dbg.v to 1
00420         cdata[4] |= 0x8;
00421 
00422         // write 36 bits, write only
00423         jtag->dreg(cdata, 36, true);
00424 
00425         // flush queu when high speed transfer is finished
00426         if (!cont)
00427                 jtag->flushQueue();
00428 }
00429 
00435 bool JTAGpxa250::readTX(unsigned int *val, int max_retry)
00436 {
00437         unsigned char cdata[5]; // 36 bits needs 5 bytes
00438         int retryCount=0;
00439         
00440         // Issue JTAG DBGTX Command
00441         ireg(JTAG_DBGTX);
00442 
00443         while (true)
00444         {
00445                 // set dbg.d, dbg.v and dbg.flush to 0
00446                 memset(cdata, 0, 5);
00447                 jtag->dreg(cdata, 36);
00448                 
00449                 if (cdata[0]&0x1==1)
00450                 {
00451                         *val=(cdata[0]>>3)|(cdata[1]<<5)|(cdata[2]<<13)|(cdata[3]<<21)|((cdata[4]&0x7)<<29);
00452                         return true;
00453                 }
00454 
00455                 if (retryCount>=max_retry)
00456                         break;
00457                 
00458                 printf("\rJTAG : readTX : Retry to get jtag-data (retry %d)      ", retryCount++);
00459                 fflush(stdout);
00460         }
00461 
00462         if (max_retry > 0)
00463         printf("\nJTAG : readTX : Reading TX failed. Got %02x %02x %02x %02x %02x\n", cdata[4], cdata[3], cdata[2], cdata[1], cdata[0]);
00464         return false;
00465 }
00466 
00475 void JTAGpxa250::putData(unsigned int startAddr, unsigned int words, unsigned int data[], bool halfword)
00476 {
00477         if (!readyForTargetCommand()) return;
00478 
00479         // Issue JTAG DBGRX Command
00480         unsigned char instr = JTAG_DBGRX;
00481         ireg(instr);
00482 
00483         // Send data
00484         writeRX((unsigned int)'p');
00485         writeRX(startAddr);
00486         writeRX(halfword ? 1 : 0);      // 16 or 32 bits access ? 0 means 32.
00487 
00488         unsigned int pos=0;
00489         unsigned int sum=0;
00490         while (pos<words)
00491         {
00492                 fastWriteRX(data[pos], true);
00493                 sum += data[pos];
00494                 pos++;
00495         }
00496         fastWriteRX(0, false);
00497 
00498         unsigned int result;
00499         if (!readTX(&result)) {
00500                 printf("Error: can't read checksum !\n");
00501         } else {
00502                 if (result != sum)
00503                         printf("Checksum error: %08X != %08X !\n", sum, result);
00504         }
00505         pollForTX();
00506 }
00507 
00514 void JTAGpxa250::getData(unsigned int startAddr, unsigned int words, unsigned int data[])
00515 {
00516         if (!readyForTargetCommand()) return;
00517 
00518         // Issue JTAG DBGRX Command
00519         unsigned char instr = JTAG_DBGRX;
00520         ireg(instr);
00521 
00522         // Get data
00523         writeRX((unsigned int)'g');
00524         writeRX(startAddr);
00525         writeRX(words);
00526         unsigned int pos=0;
00527 
00528         // Issue JTAG DBGTX Command
00529         instr = JTAG_DBGTX;
00530         ireg(instr);
00531         while (pos<words)
00532         {
00533                 //if (readTX(data+pos))
00534                 //      printf("word %d is success\n", pos);
00535                 readTX(data+pos);
00536                 pos++;
00537         }
00538         pollForTX();
00539 }
00540 
00541 // This function execute from an address with a given stack pointer
00542 //
00543 // \param startAddre address where the execution will begin
00544 // \param spAddr address of the stack pointer (grows downside)
00545 void JTAGpxa250::execute(unsigned int startAddr, unsigned int spAddr)
00546 {
00547         if (!isTargetReady) return;
00548         savePlaces[save_LR] = startAddr;
00549         savePlaces[save_R13] = spAddr;
00550         continueCmd();
00551 }
00552 
00553 void JTAGpxa250::extBreak() {
00554 
00555         // the SELCDSR instruction selects access to
00556         // the DCSR JTAG Data register, allowing us to 
00557         // generate an external debug break.
00558         unsigned char instr = JTAG_DCSR;
00559         ireg(instr);
00560 
00561         unsigned char data[5];
00562 
00563         unsigned int dcsr = DCSR_GE | DCSR_H; // enable, halt
00564         intToCharArrayLE((dcsr << 3) | 0x4, data); //  external debug event, no hold_rst
00565         data[4] = (dcsr >> 29);
00566 
00567         jtag->dreg(data,36);
00568         
00569         printf("DCSR: %08X\n", (data[4] << 29) | (data[3] << 21) | (data[2] << 13) | (data[1] << 5) | (data[0] >> 3));
00570 
00571         doPolling = true;
00572         pollForTX();
00573 }
00574 
00575 void JTAGpxa250::reboot() {
00576 
00577         jtag->cpuReset(true);
00578         jtag->cpuReset(false);
00579         isTargetReady= false;
00580         pollForTX();
00581 }
00582         
00583 void JTAGpxa250::pollForTX() {
00584         unsigned int tx;
00585 
00586         if (!doPolling) return;
00587 
00588 
00589         while (readTX(&tx, 0)) {
00590 
00591                 if ((tx == 0xFFFFFFFF) || (tx==0)) {
00592                         printf("Target disconnected.\n");
00593                         doPolling = false;
00594                         return;
00595                 }
00596                 switch (tx & TARGET_TO_HOST_CMD_MASK) {
00597                 case SAVE_ON_HOST: {
00598                         unsigned int place = tx & (~TARGET_TO_HOST_CMD_MASK);
00599                         assert(place < NBR_OF_SAVE_PLACES);
00600                         readTX(savePlaces + place);
00601                         //printf("Saving in place %d value %08X\n", place, savePlaces[place]);
00602                         break;
00603                         }
00604                 case LOAD_FROM_HOST: {
00605                         unsigned int place = tx & (~TARGET_TO_HOST_CMD_MASK);
00606                         assert(place < NBR_OF_SAVE_PLACES);
00607                         ireg(JTAG_DBGRX);
00608                         writeRX(savePlaces[place]);
00609                         break;
00610                         }
00611                 case TARGET_READY_FOR_CMD:
00612                         printf("(target ready at PC=%08X)\n", savePlaces[15]);
00613                         isTargetReady = true;
00614                         for (std::vector<Callback>::iterator it=targetReadyCallback.begin(); it!=targetReadyCallback.end(); ++it)
00615                                 it->callback(it->arg);
00616                         break;
00617                 default:
00618                         // we don't understand the debug handler :/
00619                         printf("Unknown target to host command: 0x%08X (%d, %c)\n", tx, tx, tx);
00620                 }
00621         }
00622 
00623         // nothing to do...
00624 }
00625 
00626 void JTAGpxa250::ireg(unsigned char instr) {
00627         if (currentIREG != instr) {
00628                 jtag->ireg(&instr);
00629                 currentIREG=instr;
00630         }
00631 }
00632 
00633 void JTAGpxa250::continueCmd() {
00634         if (!readyForTargetCommand()) return;
00635 
00636         // Issue JTAG DBGRX Command
00637         ireg(JTAG_DBGRX);
00638 
00639         // Send data
00640         writeRX((unsigned int)'c');
00641         pollForTX();
00642 }
00643 
00644 bool JTAGpxa250::readyForTargetCommand() {
00645         if (isTargetReady) {
00646                 isTargetReady=false; 
00647                 return true;
00648         } 
00649         printf("warning: trying to issue a command when the debug handler is not ready!\n");
00650         return false;
00651 }
00652 
00653 bool JTAGpxa250::setSavePlace(unsigned int place, unsigned int value) {
00654         assert(place < NBR_OF_SAVE_PLACES);
00655         savePlaces[place] = value;
00656 
00657         if (isTargetReady) {
00658                 return true;
00659         }
00660         printf("Warning: setting a register while the target is not ready!\n");
00661         return false;
00662 }
00663 
00664 unsigned int JTAGpxa250::getSavePlace(unsigned int place) {
00665         assert(place < NBR_OF_SAVE_PLACES);
00666         if (!isTargetReady)
00667                 printf("Warning: trying to read a register while the target is not ready!\n");
00668         return savePlaces[place];
00669 }
00670 
00671 bool JTAGpxa250::setCp15DebugRegister(unsigned int value, Cp15Reg reg) {
00672 
00673         if (!readyForTargetCommand()) return false;
00674 
00675         // SetBreakpoint command
00676         writeRX('b');
00677 
00678         // send the number of the register
00679         writeRX((unsigned int) reg);
00680 
00681         // send the value
00682         writeRX(value);
00683 
00684         pollForTX();
00685 
00686         return true;
00687 }
00688 

Generated on Fri May 16 13:01:45 2003 for Jelie by doxygen1.2.15