00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00031 #include <stdio.h>
00032 #include <unistd.h>
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;
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];
00091 int nbi = fread(buffer, 4, 2*1024, f);
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
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
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;
00165 data[1] = 0;
00166 data[2] = 0;
00167 data[3] = 0;
00168 data[4] = parity(data);
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);
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
00210
00211
00212 assert((address & 0x1F) == 0);
00213 unsigned char data[8];
00214
00215 if (mini) {
00216
00217 intToCharArrayLE((address << 1) | 0x03, data);
00218 data[4] = address >> 31;
00219 } else {
00220
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
00228 intToCharArrayLE(instructions[i], data);
00229 data[4] = parity(data);
00230 jtag->dreg(data,33);
00231 }
00232 }
00233
00234 void JTAGpxa250::getReadyForUpload() {
00235
00236
00237
00238
00239
00240
00241
00242 jtag->cpuReset(true);
00243 jtag->trst(true);
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 jtag->trst(false);
00254
00255 check();
00256
00257 jtag->idle(36);
00258
00259
00260
00261
00262
00263
00264 unsigned char instr = JTAG_DCSR;
00265 ireg(instr);
00266 unsigned char data[8];
00267 unsigned int dcsr = DCSR_GE | DCSR_H;
00268 intToCharArrayLE((dcsr << 3) | 0x2, data);
00269 data[4] = (dcsr >> 29);
00270
00271
00272 jtag->dreg(data, 36);
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 jtag->cpuReset(false);
00285
00286
00287 usleep(300000);
00288
00289
00290 jtag->idle(2030);
00291
00292
00293 ldic();
00294
00295
00296
00297 doPolling = false;
00298
00299
00300
00301
00302
00303 }
00304
00305 void JTAGpxa250::boot() {
00306
00307
00308 jtag->idle(15);
00309
00310
00311 unsigned char instr =JTAG_DCSR;
00312 ireg(instr);
00313 unsigned char data[8];
00314 unsigned int dcsr = DCSR_GE | DCSR_H | DCSR_TR;
00315 intToCharArrayLE(dcsr << 3, data);
00316 data[4] = (dcsr >> 29);
00317 jtag->dreg(data, 36);
00318
00319 usleep(10000);
00320 doPolling = true;
00321 pollForTX();
00322
00323
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 bool JTAGpxa250::loadIC(bool mini, unsigned int startAddr, unsigned int instructions[],
00335 unsigned int nbInst) {
00336
00337
00338 if (startAddr & 0x1F) return false;
00339
00340 if (mini) {
00341
00342
00343 if (nbInst > 64*8) return false;
00344 } else {
00345
00346
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];
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;
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;
00375 }
00376
00377
00378 bool JTAGpxa250::writeRX(unsigned int val)
00379 {
00380 unsigned char cdata[5];
00381 int retryCount=0;
00382
00383
00384 ireg(JTAG_DBGRX);
00385
00386 do {
00387
00388 intToCharArrayLE((val << 3) | 0x0, cdata);
00389 cdata[4] = (val >> 29);
00390
00391 cdata[4] |= 0x8;
00392
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];
00415
00416
00417 intToCharArrayLE((val << 3) | ((cont) ? 0x4 : 0x0) , cdata);
00418 cdata[4] = (val >> 29);
00419
00420 cdata[4] |= 0x8;
00421
00422
00423 jtag->dreg(cdata, 36, true);
00424
00425
00426 if (!cont)
00427 jtag->flushQueue();
00428 }
00429
00435 bool JTAGpxa250::readTX(unsigned int *val, int max_retry)
00436 {
00437 unsigned char cdata[5];
00438 int retryCount=0;
00439
00440
00441 ireg(JTAG_DBGTX);
00442
00443 while (true)
00444 {
00445
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
00480 unsigned char instr = JTAG_DBGRX;
00481 ireg(instr);
00482
00483
00484 writeRX((unsigned int)'p');
00485 writeRX(startAddr);
00486 writeRX(halfword ? 1 : 0);
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
00519 unsigned char instr = JTAG_DBGRX;
00520 ireg(instr);
00521
00522
00523 writeRX((unsigned int)'g');
00524 writeRX(startAddr);
00525 writeRX(words);
00526 unsigned int pos=0;
00527
00528
00529 instr = JTAG_DBGTX;
00530 ireg(instr);
00531 while (pos<words)
00532 {
00533
00534
00535 readTX(data+pos);
00536 pos++;
00537 }
00538 pollForTX();
00539 }
00540
00541
00542
00543
00544
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
00556
00557
00558 unsigned char instr = JTAG_DCSR;
00559 ireg(instr);
00560
00561 unsigned char data[5];
00562
00563 unsigned int dcsr = DCSR_GE | DCSR_H;
00564 intToCharArrayLE((dcsr << 3) | 0x4, data);
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
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
00619 printf("Unknown target to host command: 0x%08X (%d, %c)\n", tx, tx, tx);
00620 }
00621 }
00622
00623
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
00637 ireg(JTAG_DBGRX);
00638
00639
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
00676 writeRX('b');
00677
00678
00679 writeRX((unsigned int) reg);
00680
00681
00682 writeRX(value);
00683
00684 pollForTX();
00685
00686 return true;
00687 }
00688