static bool stm32f4_option_write(target *t, uint32_t *val, int count) { target_mem_write32(t, FLASH_OPTKEYR, OPTKEY1); target_mem_write32(t, FLASH_OPTKEYR, OPTKEY2); while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return -1; /* WRITE option bytes instruction */ if (((t->idcode == ID_STM32F42X) || (t->idcode == ID_STM32F46X) || (t->idcode == ID_STM32F72X) || (t->idcode == ID_STM32F74X) || (t->idcode == ID_STM32F76X)) && (count > 1)) /* Checkme: Do we need to read old value and then set it? */ target_mem_write32(t, FLASH_OPTCR + 4, val[1]); if ((t->idcode == ID_STM32F72X) && (count > 2)) target_mem_write32(t, FLASH_OPTCR + 8, val[2]); target_mem_write32(t, FLASH_OPTCR, val[0]); target_mem_write32(t, FLASH_OPTCR, val[0] | FLASH_OPTCR_OPTSTRT); /* Read FLASH_SR to poll for BSY bit */ while(target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return false; target_mem_write32(t, FLASH_OPTCR, FLASH_OPTCR_OPTLOCK); return true; }
static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, int len, uint32_t pagesize) { ADIv5_AP_t *ap = adiv5_target_ap(target); uint16_t sr; addr &= ~(pagesize - 1); len &= ~(pagesize - 1); stm32f1_flash_unlock(ap); while(len) { /* Flash page erase instruction */ adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_PER); /* write address to FMA */ adiv5_ap_mem_write(ap, FLASH_AR, addr); /* Flash page erase start instruction */ adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_STRT | FLASH_CR_PER); /* Read FLASH_SR to poll for BSY bit */ while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(target)) return -1; len -= pagesize; addr += pagesize; } /* Check for error */ sr = adiv5_ap_mem_read(ap, FLASH_SR); if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP)) return -1; return 0; }
static int nrf51_flash_write(struct target_flash *f, uint32_t dest, const void *src, size_t len) { target *t = f->t; uint32_t data[2 + len/4]; /* FIXME rewrite stub to use register args */ /* Construct data buffer used by stub */ data[0] = dest; data[1] = len; /* length must always be a multiple of 4 */ memcpy((uint8_t *)&data[2], src, len); /* Enable write */ target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_WEN); /* Poll for NVMC_READY */ while (target_mem_read32(t, NRF51_NVMC_READY) == 0) if(target_check_error(t)) return -1; /* Write stub and data to target ram and call stub */ target_mem_write(t, SRAM_BASE, nrf51_flash_write_stub, sizeof(nrf51_flash_write_stub)); target_mem_write(t, STUB_BUFFER_BASE, data, len + 8); cortexm_run_stub(t, SRAM_BASE, 0, 0, 0, 0); /* Return to read-only */ target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN); return 0; }
static int stm32f1_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len) { ADIv5_AP_t *ap = adiv5_target_ap(target); uint32_t offset = dest % 4; uint32_t words = (offset + len + 3) / 4; uint32_t data[2 + words]; /* Construct data buffer used by stub */ data[0] = dest - offset; data[1] = words * 4; /* length must always be a multiple of 4 */ data[2] = 0xFFFFFFFF; /* pad partial words with all 1s to avoid */ data[words + 1] = 0xFFFFFFFF; /* damaging overlapping areas */ memcpy((uint8_t *)&data[2] + offset, src, len); /* Write stub and data to target ram and set PC */ target_mem_write_words(target, 0x20000000, (void*)stm32f1_flash_write_stub, 0x2C); target_mem_write_words(target, 0x2000002C, data, len + 8); target_pc_write(target, 0x20000000); if(target_check_error(target)) return -1; /* Execute the stub */ target_halt_resume(target, 0); while(!target_halt_wait(target)); /* Check for error */ if (adiv5_ap_mem_read(ap, FLASH_SR) & SR_ERROR_MASK) return -1; return 0; }
/** * Erase flash row by row */ static int efm32_flash_erase(struct target_flash *f, target_addr addr, size_t len) { target *t = f->t; /* Set WREN bit to enabel MSC write and erase functionality */ target_mem_write32(t, EFM32_MSC_WRITECTRL, 1); while (len) { /* Write address of first word in row to erase it */ target_mem_write32(t, EFM32_MSC_ADDRB, addr); target_mem_write32(t, EFM32_MSC_WRITECMD, EFM32_MSC_WRITECMD_LADDRIM); /* Issue the erase command */ target_mem_write32(t, EFM32_MSC_WRITECMD, EFM32_MSC_WRITECMD_ERASEPAGE ); /* Poll MSC Busy */ while ((target_mem_read32(t, EFM32_MSC_STATUS) & EFM32_MSC_STATUS_BUSY)) { if (target_check_error(t)) return -1; } addr += f->blocksize; len -= f->blocksize; } return 0; }
static int stm32f1_flash_erase(struct target_flash *f, target_addr addr, size_t len) { target *t = f->t; uint16_t sr; stm32f1_flash_unlock(t); while(len) { /* Flash page erase instruction */ target_mem_write32(t, FLASH_CR, FLASH_CR_PER); /* write address to FMA */ target_mem_write32(t, FLASH_AR, addr); /* Flash page erase start instruction */ target_mem_write32(t, FLASH_CR, FLASH_CR_STRT | FLASH_CR_PER); /* Read FLASH_SR to poll for BSY bit */ while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return -1; len -= f->blocksize; addr += f->blocksize; } /* Check for error */ sr = target_mem_read32(t, FLASH_SR); if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP)) return -1; return 0; }
static bool stm32l4_cmd_erase(target *t, uint32_t action) { const char spinner[] = "|/-\\"; int spinindex = 0; tc_printf(t, "Erasing flash... This may take a few seconds. "); stm32l4_flash_unlock(t); /* Flash erase action start instruction */ target_mem_write32(t, FLASH_CR, action); target_mem_write32(t, FLASH_CR, action | FLASH_CR_STRT); /* Read FLASH_SR to poll for BSY bit */ while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) { tc_printf(t, "\b%c", spinner[spinindex++ % 4]); if(target_check_error(t)) { tc_printf(t, "\n"); return false; } } tc_printf(t, "\n"); /* Check for error */ uint16_t sr = target_mem_read32(t, FLASH_SR); if (sr & FLASH_SR_ERROR_MASK) return false; return true; }
bool cortexa_attach(target *t) { struct cortexa_priv *priv = t->priv; int tries; /* Clear any pending fault condition */ target_check_error(t); /* Enable halting debug mode */ uint32_t dbgdscr = apb_read(t, DBGDSCR); dbgdscr |= DBGDSCR_HDBGEN | DBGDSCR_ITREN; dbgdscr = (dbgdscr & ~DBGDSCR_EXTDCCMODE_MASK) | DBGDSCR_EXTDCCMODE_STALL; apb_write(t, DBGDSCR, dbgdscr); DEBUG("DBGDSCR = 0x%08"PRIx32"\n", dbgdscr); target_halt_request(t); tries = 10; while(!platform_srst_get_val() && !target_halt_poll(t, NULL) && --tries) platform_delay(200); if(!tries) return false; /* Clear any stale breakpoints */ for(unsigned i = 0; i < priv->hw_breakpoint_max; i++) { apb_write(t, DBGBCR(i), 0); } priv->hw_breakpoint_mask = 0; priv->bcr0 = 0; platform_srst_set_val(false); return true; }
static int stm32f4_flash_erase(struct target_flash *f, uint32_t addr, size_t len) { target *t = f->t; uint16_t sr; uint8_t sector = ((struct stm32f4_flash *)f)->base_sector + (addr - f->start)/f->blocksize; stm32f4_flash_unlock(t); while(len) { uint32_t cr = FLASH_CR_EOPIE | FLASH_CR_ERRIE | FLASH_CR_SER | (sector << 3); /* Flash page erase instruction */ target_mem_write32(t, FLASH_CR, cr); /* write address to FMA */ target_mem_write32(t, FLASH_CR, cr | FLASH_CR_STRT); /* Read FLASH_SR to poll for BSY bit */ while(target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return -1; len -= f->blocksize; sector++; } /* Check for error */ sr = target_mem_read32(t, FLASH_SR); if(sr & SR_ERROR_MASK) return -1; return 0; }
static bool stm32f4_cmd_erase_mass(target *t) { const char spinner[] = "|/-\\"; int spinindex = 0; gdb_out("Erasing flash... This may take a few seconds. "); stm32f4_flash_unlock(t); /* Flash mass erase start instruction */ target_mem_write32(t, FLASH_CR, FLASH_CR_MER); target_mem_write32(t, FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER); /* Read FLASH_SR to poll for BSY bit */ while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) { gdb_outf("\b%c", spinner[spinindex++ % 4]); if(target_check_error(t)) { gdb_out("\n"); return false; } } gdb_out("\n"); /* Check for error */ uint16_t sr = target_mem_read32(t, FLASH_SR); if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP)) return false; return true; }
static bool stm32f4_option_write(target *t, uint32_t value) { target_mem_write32(t, FLASH_OPTKEYR, OPTKEY1); target_mem_write32(t, FLASH_OPTKEYR, OPTKEY2); value &= ~FLASH_OPTCR_RESERVED; while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return -1; /* WRITE option bytes instruction */ target_mem_write32(t, FLASH_OPTCR, value); target_mem_write32(t, FLASH_OPTCR, value | FLASH_OPTCR_OPTSTRT); /* Read FLASH_SR to poll for BSY bit */ while(target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return false; target_mem_write32(t, FLASH_OPTCR, value | FLASH_OPTCR_OPTLOCK); return true; }
static bool stm32f1_option_erase(target *t) { /* Erase option bytes instruction */ target_mem_write32(t, FLASH_CR, FLASH_CR_OPTER | FLASH_CR_OPTWRE); target_mem_write32(t, FLASH_CR, FLASH_CR_STRT | FLASH_CR_OPTER | FLASH_CR_OPTWRE); /* Read FLASH_SR to poll for BSY bit */ while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return false; return true; }
static int nrf51_flash_erase(struct target_flash *f, target_addr addr, size_t len) { target *t = f->t; /* Enable erase */ target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN); /* Poll for NVMC_READY */ while (target_mem_read32(t, NRF51_NVMC_READY) == 0) if(target_check_error(t)) return -1; while (len) { if (addr == NRF51_UICR) { // Special Case /* Write to the ERASE_UICR register to erase */ target_mem_write32(t, NRF51_NVMC_ERASEUICR, 0x1); } else { // Standard Flash Page /* Write address of first word in page to erase it */ target_mem_write32(t, NRF51_NVMC_ERASEPAGE, addr); } /* Poll for NVMC_READY */ while (target_mem_read32(t, NRF51_NVMC_READY) == 0) if(target_check_error(t)) return -1; addr += f->blocksize; len -= f->blocksize; } /* Return to read-only */ target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN); /* Poll for NVMC_READY */ while (target_mem_read32(t, NRF51_NVMC_READY) == 0) if(target_check_error(t)) return -1; return 0; }
static bool nrf51_cmd_erase_all(target *t) { tc_printf(t, "erase..\n"); /* Enable erase */ target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN); /* Poll for NVMC_READY */ while (target_mem_read32(t, NRF51_NVMC_READY) == 0) if(target_check_error(t)) return false; /* Erase all */ target_mem_write32(t, NRF51_NVMC_ERASEALL, 1); /* Poll for NVMC_READY */ while (target_mem_read32(t, NRF51_NVMC_READY) == 0) if(target_check_error(t)) return false; return true; }
static bool stm32f1_option_write_erased(target *t, uint32_t addr, uint16_t value) { if (value == 0xffff) return true; /* Erase option bytes instruction */ target_mem_write32(t, FLASH_CR, FLASH_CR_OPTPG | FLASH_CR_OPTWRE); target_mem_write16(t, addr, value); /* Read FLASH_SR to poll for BSY bit */ while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return false; return true; }
static bool stm32f1_option_erase(target *t) { ADIv5_AP_t *ap = adiv5_target_ap(t); /* Erase option bytes instruction */ adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_OPTER | FLASH_CR_OPTWRE); adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_STRT | FLASH_CR_OPTER | FLASH_CR_OPTWRE); /* Read FLASH_SR to poll for BSY bit */ while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return false; return true; }
static bool stm32f1_option_write_erased(target *t, uint32_t addr, uint16_t value) { ADIv5_AP_t *ap = adiv5_target_ap(t); if (value == 0xffff) return true; /* Erase option bytes instruction */ adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_OPTPG | FLASH_CR_OPTWRE); adiv5_ap_mem_write_halfword(ap, addr, value); /* Read FLASH_SR to poll for BSY bit */ while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return false; return true; }
static int sam3x_flash_cmd(target *t, uint32_t base, uint8_t cmd, uint16_t arg) { DEBUG("%s: base = 0x%08x cmd = 0x%02X, arg = 0x%06X\n", __func__, base, cmd, arg); target_mem_write32(t, EEFC_FCR(base), EEFC_FCR_FKEY | cmd | ((uint32_t)arg << 8)); while (!(target_mem_read32(t, EEFC_FSR(base)) & EEFC_FSR_FRDY)) if(target_check_error(t)) return -1; uint32_t sr = target_mem_read32(t, EEFC_FSR(base)); return sr & EEFC_FSR_ERROR; }
/** * Overloads the default cortexm reset function with a version that * removes the target from extended reset where required. */ static void samd_reset(target *t) { /** * SRST is not asserted here as it appears to reset the adiv5 * logic, meaning that subsequent adiv5_* calls PLATFORM_FATAL_ERROR. * * This is ok as normally you can just connect the debugger and go, * but if that's not possible (protection or SWCLK being used for * something else) then having SWCLK low on reset should get you * debug access (cold-plugging). TODO: Confirm this * * See the SAM D20 datasheet §12.6 Debug Operation for more * details. * * jtagtap_srst(true); * jtagtap_srst(false); */ /* Read DHCSR here to clear S_RESET_ST bit before reset */ target_mem_read32(t, CORTEXM_DHCSR); /* Request system reset from NVIC: SRST doesn't work correctly */ /* This could be VECTRESET: 0x05FA0001 (reset only core) * or SYSRESETREQ: 0x05FA0004 (system reset) */ target_mem_write32(t, CORTEXM_AIRCR, CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ); /* Exit extended reset */ if (target_mem_read32(t, SAMD_DSU_CTRLSTAT) & SAMD_STATUSA_CRSTEXT) { /* Write bit to clear from extended reset */ target_mem_write32(t, SAMD_DSU_CTRLSTAT, SAMD_STATUSA_CRSTEXT); } /* Poll for release from reset */ while (target_mem_read32(t, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST); /* Reset DFSR flags */ target_mem_write32(t, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); /* Clear any target errors */ target_check_error(t); }
static bool stm32f1_cmd_erase_mass(target *t) { stm32f1_flash_unlock(t); /* Flash mass erase start instruction */ target_mem_write32(t, FLASH_CR, FLASH_CR_MER); target_mem_write32(t, FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER); /* Read FLASH_SR to poll for BSY bit */ while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return false; /* Check for error */ uint16_t sr = target_mem_read32(t, FLASH_SR); if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP)) return false; return true; }
static bool stm32f1_cmd_erase_mass(target *t) { ADIv5_AP_t *ap = adiv5_target_ap(t); stm32f1_flash_unlock(ap); /* Flash mass erase start instruction */ adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_MER); adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER); /* Read FLASH_SR to poll for BSY bit */ while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return false; /* Check for error */ uint16_t sr = adiv5_ap_mem_read(ap, FLASH_SR); if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP)) return false; return true; }
static int stm32l4_flash_erase(struct target_flash *f, target_addr addr, size_t len) { target *t = f->t; uint16_t sr; uint32_t bank1_start = ((struct stm32l4_flash *)f)->bank1_start; uint32_t page; stm32l4_flash_unlock(t); page = (addr - 0x08000000) / PAGE_SIZE; while(len) { uint32_t cr; cr = FLASH_CR_PER | (page << FLASH_CR_PAGE_SHIFT ); if (addr >= bank1_start) cr |= FLASH_CR_BKER; /* Flash page erase instruction */ target_mem_write32(t, FLASH_CR, cr); /* write address to FMA */ cr |= FLASH_CR_STRT; target_mem_write32(t, FLASH_CR, cr); /* Read FLASH_SR to poll for BSY bit */ while(target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return -1; len -= PAGE_SIZE; addr += PAGE_SIZE; page++; } /* Check for error */ sr = target_mem_read32(t, FLASH_SR); if(sr & FLASH_SR_ERROR_MASK) return -1; return 0; }
/** * Uses the MSC ERASEMAIN0 command to erase the entire flash */ static bool efm32_cmd_erase_all(target *t) { /* Set WREN bit to enabel MSC write and erase functionality */ target_mem_write32(t, EFM32_MSC_WRITECTRL, 1); /* Unlock mass erase */ target_mem_write32(t, EFM32_MSC_MASSLOCK, EFM32_MSC_MASSLOCK_LOCKKEY); /* Erase operation */ target_mem_write32(t, EFM32_MSC_WRITECMD, EFM32_MSC_WRITECMD_ERASEMAIN0); /* Poll MSC Busy */ while ((target_mem_read32(t, EFM32_MSC_STATUS) & EFM32_MSC_STATUS_BUSY)) { if (target_check_error(t)) return false; } /* Relock mass erase */ target_mem_write32(t, EFM32_MSC_MASSLOCK, 0); tc_printf(t, "Erase successful!\n"); return true; }
static int nrf51_flash_write(struct target_flash *f, target_addr dest, const void *src, size_t len) { target *t = f->t; /* Enable write */ target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_WEN); /* Poll for NVMC_READY */ while (target_mem_read32(t, NRF51_NVMC_READY) == 0) if(target_check_error(t)) return -1; /* Write stub and data to target ram and call stub */ target_mem_write(t, SRAM_BASE, nrf51_flash_write_stub, sizeof(nrf51_flash_write_stub)); target_mem_write(t, STUB_BUFFER_BASE, src, len); int ret = cortexm_run_stub(t, SRAM_BASE, dest, STUB_BUFFER_BASE, len, 0); /* Return to read-only */ target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN); return ret; }
/* Memory access functions */ int target_mem_read(target *t, void *dest, target_addr src, size_t len) { t->mem_read(t, dest, src, len); return target_check_error(t); }
int target_mem_write(target *t, target_addr dest, const void *src, size_t len) { t->mem_write(t, dest, src, len); return target_check_error(t); }
void gdb_main(void) { int size; bool single_step = false; char last_activity = 0; DEBUG("Entring GDB protocol main loop\n"); /* GDB protocol main loop */ while(1) { SET_IDLE_STATE(1); size = gdb_getpacket(pbuf, BUF_SIZE); SET_IDLE_STATE(0); continue_activity: switch(pbuf[0]) { /* Implementation of these is mandatory! */ case 'g': { /* 'g': Read general registers */ ERROR_IF_NO_TARGET(); uint8_t arm_regs[target_regs_size(cur_target)]; target_regs_read(cur_target, arm_regs); gdb_putpacket(hexify(pbuf, arm_regs, sizeof(arm_regs)), sizeof(arm_regs) * 2); break; } case 'm': { /* 'm addr,len': Read len bytes from addr */ uint32_t addr, len; ERROR_IF_NO_TARGET(); sscanf(pbuf, "m%" SCNx32 ",%" SCNx32, &addr, &len); DEBUG("m packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); uint8_t mem[len]; target_mem_read(cur_target, mem, addr, len); if(target_check_error(cur_target)) gdb_putpacketz("E01"); else gdb_putpacket(hexify(pbuf, mem, len), len*2); break; } case 'G': { /* 'G XX': Write general registers */ ERROR_IF_NO_TARGET(); uint8_t arm_regs[target_regs_size(cur_target)]; unhexify(arm_regs, &pbuf[1], sizeof(arm_regs)); target_regs_write(cur_target, arm_regs); gdb_putpacketz("OK"); break; } case 'M': { /* 'M addr,len:XX': Write len bytes to addr */ uint32_t addr, len; int hex; ERROR_IF_NO_TARGET(); sscanf(pbuf, "M%" SCNx32 ",%" SCNx32 ":%n", &addr, &len, &hex); DEBUG("M packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); uint8_t mem[len]; unhexify(mem, pbuf + hex, len); target_mem_write(cur_target, addr, mem, len); if(target_check_error(cur_target)) gdb_putpacketz("E01"); else gdb_putpacketz("OK"); break; } case 's': /* 's [addr]': Single step [start at addr] */ single_step = true; // Fall through to resume target case 'c': /* 'c [addr]': Continue [at addr] */ if(!cur_target) { gdb_putpacketz("X1D"); break; } target_halt_resume(cur_target, single_step); SET_RUN_STATE(1); single_step = false; // Fall through to wait for target halt case '?': { /* '?': Request reason for target halt */ /* This packet isn't documented as being mandatory, * but GDB doesn't work without it. */ uint32_t watch_addr; int sig; if(!cur_target) { /* Report "target exited" if no target */ gdb_putpacketz("W00"); break; } last_activity = pbuf[0]; /* Wait for target halt */ while(!(sig = target_halt_wait(cur_target))) { unsigned char c = gdb_if_getchar_to(0); if((c == '\x03') || (c == '\x04')) { target_halt_request(cur_target); last_activity = 's'; } } SET_RUN_STATE(0); /* Negative signal indicates we're in a syscall */ if (sig < 0) break; /* Target disappeared */ if (cur_target == NULL) { gdb_putpacket_f("X%02X", sig); break; } /* Report reason for halt */ if(target_check_hw_wp(cur_target, &watch_addr)) { /* Watchpoint hit */ gdb_putpacket_f("T%02Xwatch:%08X;", sig, watch_addr); } else { gdb_putpacket_f("T%02X", sig); } break; } case 'F': { /* Semihosting call finished */ int retcode, errcode, items; char c, *p; if (pbuf[1] == '-') p = &pbuf[2]; else p = &pbuf[1]; items = sscanf(p, "%x,%x,%c", &retcode, &errcode, &c); if (pbuf[1] == '-') retcode = -retcode; target_hostio_reply(cur_target, retcode, errcode); /* if break is requested */ if (items == 3 && c == 'C') { gdb_putpacketz("T02"); break; } pbuf[0] = last_activity; goto continue_activity; } /* Optional GDB packet support */ case '!': /* Enable Extended GDB Protocol. */ /* This doesn't do anything, we support the extended * protocol anyway, but GDB will never send us a 'R' * packet unless we answer 'OK' here. */ gdb_putpacketz("OK"); break; case 0x04: case 'D': /* GDB 'detach' command. */ if(cur_target) target_detach(cur_target); last_target = cur_target; cur_target = NULL; gdb_putpacketz("OK"); break; case 'k': /* Kill the target */ if(cur_target) { target_reset(cur_target); target_detach(cur_target); last_target = cur_target; cur_target = NULL; } break; case 'r': /* Reset the target system */ case 'R': /* Restart the target program */ if(cur_target) target_reset(cur_target); else if(last_target) { cur_target = target_attach(last_target, gdb_target_destroy_callback); target_reset(cur_target); } break; case 'X': { /* 'X addr,len:XX': Write binary data to addr */ uint32_t addr, len; int bin; ERROR_IF_NO_TARGET(); sscanf(pbuf, "X%" SCNx32 ",%" SCNx32 ":%n", &addr, &len, &bin); DEBUG("X packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); target_mem_write(cur_target, addr, pbuf+bin, len); if(target_check_error(cur_target)) gdb_putpacketz("E01"); else gdb_putpacketz("OK"); break; } case 'q': /* General query packet */ handle_q_packet(pbuf, size); break; case 'v': /* General query packet */ handle_v_packet(pbuf, size); break; /* These packet implement hardware break-/watchpoints */ case 'Z': /* Z type,addr,len: Set breakpoint packet */ case 'z': /* z type,addr,len: Clear breakpoint packet */ ERROR_IF_NO_TARGET(); handle_z_packet(pbuf, size); break; default: /* Packet not implemented */ DEBUG("*** Unsupported packet: %s\n", pbuf); gdb_putpacketz(""); } } }