📄 remote.cc
字号:
mem2hex(&checksum, buf, 4); gdbOut("Bad checksum: my count = %s, ", buf); mem2hex(&xmitcsum, buf, 4); gdbOut("sent count = %s\n", buf); gdbOut(" -- Bad buffer: \"%s\"\n", buffer); putDebugChar('-'); // failed checksum } else { putDebugChar('+'); // successful transfer // if a sequence char is present, reply the sequence ID if(buffer[2] == ':') { putDebugChar(buffer[0]); putDebugChar(buffer[1]); return &buffer[3]; } return &buffer[0]; } } }}/** Send packet 'buffer' to gdb. Adds $, # and checksum wrappers. **/static void putpacket(char *buffer){ unsigned char checksum; int count; char ch; // $<packet info>#<checksum>. do { putDebugChar('$'); checksum = 0; count = 0; while((ch = buffer[count])) { putDebugChar(ch); checksum += ch; count += 1; } putDebugChar('#'); putDebugChar(hexchars[checksum >> 4]); putDebugChar(hexchars[checksum % 16]); } while(getDebugChar() != '+'); // wait for the ACK}/** Set remcomOutBuffer to "ok" response */static void ok(){ strcpy(remcomOutBuffer, "OK");}/** Set remcomOutBuffer to error 'n' response */static void error(int n){ char *ptr = remcomOutBuffer; *ptr++ = 'E'; ptr = byteToHex(n, ptr); *ptr = '\0';}static void repStatus(bool breaktime){ if (breaktime) reportStatusExtended(SIGTRAP); else { // A breakpoint did not occur. Assume that GDB sent a break. // Halt the target. interruptProgram(); // Report this as a user interrupt reportStatusExtended(SIGINT); }}void talkToGdb(void){ int addr, start, end; int length; int i; unsigned int newPC; int regno; char *ptr; bool adding = false; bool dontSendReply = false; char cmd; static char last_cmd = 0; ptr = getpacket(); debugOut("GDB: <%s>\n", ptr); // default empty response remcomOutBuffer[0] = 0; cmd = *ptr++; switch (cmd) { default: // Unknown code. Return an empty reply message. break; case 'k': // kill the program dontSendReply = true; break; case 'R': if (!resetProgram()) gdbOut("reset failed\n"); dontSendReply = true; break; case '!': ok(); break; case 'M': { uchar *jtagBuffer; int lead = 0; static bool last_orphan_pending = false; static uchar last_orphan = 0xff; // MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK // TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 error(1); // default is error if((hexToInt(&ptr, &addr)) && (*(ptr++) == ',') && (hexToInt(&ptr, &length)) && (*(ptr++) == ':') && (length > 0)) { debugOut("\nGDB: Write %d bytes to 0x%X\n", length, addr); // There is no gaurantee that gdb will send a word aligned stream // of bytes, so we need to try and catch that here. This ugly, but // it would more difficult to change in gdb and probably affect // more than avarice users. This hack will make the gdb 'load' // command less prone to failure. if (addr & 1) { // odd addr means there may be a byte from last 'M' to write if ((last_cmd == 'M') && (last_orphan_pending)) { length++; addr--; lead = 1; } } last_orphan_pending = false; jtagBuffer = new uchar[length]; hex2mem(ptr, jtagBuffer+lead, length); if (lead) jtagBuffer[0] = last_orphan; if ((addr < DATA_SPACE_ADDR_OFFSET) && (length & 1)) { // An odd length means we will have an orphan this round but // only if we are writing to PROG space. last_orphan_pending = true; last_orphan = jtagBuffer[length]; length--; } if (jtagWrite(addr, length, jtagBuffer)) ok(); delete [] jtagBuffer; } break; } case 'm': // mAA..AA,LLLL Read LLLL bytes at address AA..AA { uchar *jtagBuffer; error(1); // default is error if((hexToInt(&ptr, &addr)) && (*(ptr++) == ',') && (hexToInt(&ptr, &length))) { debugOut("\nGDB: Read %d bytes from 0x%X\n", length, addr); jtagBuffer = jtagRead(addr, length); if (jtagBuffer) { mem2hex(jtagBuffer, remcomOutBuffer, length); delete [] jtagBuffer; } } break; } case '?': // Report status. We don't actually know, so always report breakpoint reportStatus(SIGTRAP); break; case 'g': // return the value of the CPU registers { uchar *jtagBuffer; uchar regBuffer[40]; memset(regBuffer, 0, sizeof(regBuffer)); // Read the registers directly from memory // R0..R31 are at locations 0..31 // SP is at 0x5D & 0x5E // SREG is at 0x5F debugOut("\nGDB: (Registers)Read %d bytes from 0x%X\n", 0x20, 0x00 + DATA_SPACE_ADDR_OFFSET); jtagBuffer = jtagRead(0x00 + DATA_SPACE_ADDR_OFFSET, 0x20); if (jtagBuffer) { // Put GPRs into the first 32 locations memcpy(regBuffer, jtagBuffer, 0x20); delete [] jtagBuffer; jtagBuffer = 0; } else { error (1); break; } // Read in SPL SPH SREG jtagBuffer = jtagRead(0x5D + DATA_SPACE_ADDR_OFFSET, 0x03); if (jtagBuffer) { // We have SPL SPH SREG and need SREG SPL SPH // SREG regBuffer[0x20] = jtagBuffer[0x02]; // NOTE: Little endian, so SPL comes first. // SPL regBuffer[0x21] = jtagBuffer[0x00]; // SPH regBuffer[0x22] = jtagBuffer[0x01]; delete [] jtagBuffer; jtagBuffer = 0; } else { error (1); break; } // PC newPC = getProgramCounter(); regBuffer[35] = (unsigned char)(newPC & 0xff); regBuffer[36] = (unsigned char)((newPC & 0xff00) >> 8); regBuffer[37] = (unsigned char)((newPC & 0xff0000) >> 16); regBuffer[38] = (unsigned char)((newPC & 0xff000000) >> 24); debugOut("PC = %x\n", newPC); if (newPC == PC_INVALID) error(1); else mem2hex(regBuffer, remcomOutBuffer, 32 + 1 + 2 + 4); break; } case 'q': // general query { uchar* jtagBuffer; length = strlen("Ravr.io_reg"); if ( strncmp(ptr, "Ravr.io_reg", length) == 0 ) { int i, j, regcount; gdb_io_reg_def_type *io_reg_defs; debugOut("\nGDB: (io registers) Read %d bytes from 0x%X\n", 0x40, 0x20); /* If there is an io_reg_defs for this device then respond */ io_reg_defs = global_p_device_def->io_reg_defs; if (io_reg_defs) { // count the number of defined registers regcount = 0; while (io_reg_defs[regcount].name) { regcount++; } ptr += length; if (*ptr == '\0') { sprintf(remcomOutBuffer, "%02x", regcount); } else if (*ptr == ':') { // Request for a sequence of io registers int offset; i = 0; j = 0; unsigned int count; unsigned int addr; // Find the first register ptr++; hexToInt(&ptr,&i); // Confirm presence of ',' if (*ptr++ == ',') { hexToInt(&ptr,&j); } // i is the first register to read // j is the number of registers to read while ((j > 0) && (i < regcount)) { count = 0; if ((io_reg_defs[i].name != 0x00) && (io_reg_defs[i].flags != 0x00)) { // Register with special flags set offset = strlen(remcomOutBuffer); sprintf(&remcomOutBuffer[offset], "[-- %s --],00;", io_reg_defs[i].name); i++; j--; } else { // Get the address of the first io_register to be // read addr = io_reg_defs[i].reg_addr; // Count the number of consecutive address, // no-side effects, valid registers for (count = 0; count < j; count++) { if ((io_reg_defs[i+count].name == 0x00) || (io_reg_defs[i+count].flags != 0x00) || (io_reg_defs[i+count].reg_addr != addr)) { break; } addr++; } if (count) { // Read consecutive address io_registers jtagBuffer = jtagRead(DATA_SPACE_ADDR_OFFSET + io_reg_defs[i].reg_addr, count); if (jtagBuffer) { int k = 0; // successfully read while(count--) { offset = strlen(remcomOutBuffer); sprintf(&remcomOutBuffer[offset], "%s,%02x;", io_reg_defs[i].name, jtagBuffer[k++]); i++; j--; } delete [] jtagBuffer; jtagBuffer = 0; } } } } } } } break; } case 'P': // set the value of a single CPU register - return OK error(1); // error by default if (hexToInt(&ptr, ®no) && *ptr++ == '=') { uchar reg[4]; if (regno >= 0 && regno < NUMREGS) { hex2mem(ptr, reg, 1); if (jtagWrite(regno+DATA_SPACE_ADDR_OFFSET, 1, reg)) ok(); break; } else if (regno == SREG) { hex2mem(ptr, reg, 1); if (jtagWrite(0x5f+DATA_SPACE_ADDR_OFFSET, 1, reg)) ok(); } else if (regno == SP) { hex2mem(ptr, reg, 2); if (jtagWrite(0x5d+DATA_SPACE_ADDR_OFFSET, 2, reg)) ok(); } else if (regno == PC) { hex2mem(ptr, reg, 4); if (setProgramCounter(reg[0] | reg[1] << 8 | reg[2] << 16 | reg[3] << 24)) ok(); } } break; case 'G': // set the value of the CPU registers // It would appear that we don't need to support this as // we have 'P'. Report an error (rather than fail silently, // this will make errors in this comment more apparent...) error(1); break; case 's': // sAA..AA Step one instruction from AA..AA(optional) // try to read optional parameter, pc unchanged if no parm if (hexToInt(&ptr, &addr)) { if (!setProgramCounter(addr)) gdbOut("Failed to set PC"); } repStatus(singleStep()); break; case 'e': //eAA..AA,BB..BB continue until pc leaves [A..B[ range if (hexToInt(&ptr, &start) && *ptr++ == ',' && hexToInt(&ptr, &end)) { debugOut("single step from %x to %x\n", start, end); putpacket("OK"); repStatus(start == end ? singleStep() : stepThrough(start, end)); } break; case 'C': { /* Continue with signal command format: "C<sig>;<addr>" or "S<sig>;<addr>" "<sig>" should always be 2 hex digits, possibly zero padded. ";<addr>" part is optional. If addr is given, resume at that address, otherwise, resume at current address. */ int sig; if (hexToInt(&ptr, &sig)) { if (sig == SIGHUP) { if (resetProgram()) { reportStatusExtended(SIGTRAP); } } } break; } case 'c': // cAA..AA Continue from address AA..AA(optional) // try to read optional parameter, pc unchanged if no parm if (hexToInt(&ptr, &addr)) { if (!setProgramCounter(addr)) gdbOut("Failed to set PC"); } repStatus(jtagContinue(true)); break; case 'D': // Detach, resumes target. Can get control back with step // or continue if (resumeProgram()) ok(); else error(1); break; case 'Z': adding = true; case 'z': error(1); // assume the worst. // Add a Breakpoint. note: length specifier is ignored for now. if (hexToInt(&ptr, &i) && *ptr++ == ',' && hexToInt(&ptr, &addr) && *ptr++ == ',' && hexToInt(&ptr, &length)) { bpType mode = NONE; switch(i) { case 0: case 1: mode = CODE; break; case 2: mode = WRITE_DATA; break; case 3: mode = READ_DATA; break; case 4: mode = ACCESS_DATA; break; default: debugOut("Unknown breakpoint type from GDB.\n"); exit(1); } if (adding) { if (addBreakpoint(addr, mode, length)) ok(); } else { if (deleteBreakpoint(addr, mode, length)) ok(); } } break; } // switch last_cmd = cmd; // reply to the request if (!dontSendReply) { debugOut("->GDB: %s\n", remcomOutBuffer); putpacket(remcomOutBuffer); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -