static int mrvlqspi_stop_transfer(struct flash_bank *bank) { int retval; uint32_t regval; struct target *target = bank->target; int timeout = QSPI_TIMEOUT; /* wait for xfer_ready and wfifo_empty to set */ for (;;) { retval = target_read_u32(target, mrvlqspi_get_reg(bank, CNTL), ®val); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%08" PRIx32, regval); if ((regval & (XFER_RDY | WFIFO_EMPTY)) == (XFER_RDY | WFIFO_EMPTY)) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } retval = target_read_u32(target, mrvlqspi_get_reg(bank, CONF), ®val); if (retval != ERROR_OK) return retval; regval |= XFER_STOP; retval = target_write_u32(target, mrvlqspi_get_reg(bank, CONF), regval); if (retval != ERROR_OK) return retval; /* wait for xfer_start to reset */ for (;;) { retval = target_read_u32(target, mrvlqspi_get_reg(bank, CONF), ®val); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%08" PRIx32, regval); if ((regval & XFER_START) == 0) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } retval = mrvlqspi_set_ss_state(bank, QSPI_SS_DISABLE, QSPI_TIMEOUT); if (retval != ERROR_OK) return retval; return ERROR_OK; }
/* Poll the SSP busy flag. When this comes back as 0, the transfer is complete * and the controller is idle. */ static int poll_ssp_busy(struct target *target, uint32_t ssp_base, int timeout) { long long endtime; uint32_t value; int retval; retval = ssp_read_reg(target, ssp_base, SSP_SR, &value); if ((retval == ERROR_OK) && (value & SSP_BSY) == 0) return ERROR_OK; else if (retval != ERROR_OK) return retval; endtime = timeval_ms() + timeout; do { alive_sleep(1); retval = ssp_read_reg(target, ssp_base, SSP_SR, &value); if ((retval == ERROR_OK) && (value & SSP_BSY) == 0) return ERROR_OK; else if (retval != ERROR_OK) return retval; } while (timeval_ms() < endtime); LOG_ERROR("Timeout while polling BSY"); return ERROR_FLASH_OPERATION_FAILED; }
static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank) { struct target *target = bank->target; uint32_t status; int retval = ERROR_OK; int timeout = 100; /* wait for busy to clear */ for (;;) { retval = target_read_u32(target, FLASH_SR, &status); if (retval != ERROR_OK) return retval; if ((status & FLASH_SR__BSY) == 0) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } if (status & FLASH_SR__WRPERR) { LOG_ERROR("access denied / write protected"); retval = ERROR_FAIL; } if (status & FLASH_SR__PGAERR) { LOG_ERROR("invalid program address"); retval = ERROR_FAIL; } return retval; }
static int xmc4xxx_wait_status_busy(struct flash_bank *bank, int timeout) { int res; uint32_t status; res = xmc4xxx_get_flash_status(bank, &status); if (res != ERROR_OK) return res; /* While the flash controller is busy, wait */ while (status & FSR_PBUSY_MASK) { res = xmc4xxx_get_flash_status(bank, &status); if (res != ERROR_OK) return res; if (timeout-- <= 0) { LOG_ERROR("Timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); keep_alive(); } if (status & FSR_PROER_MASK) { LOG_ERROR("XMC4xxx flash protected"); res = ERROR_FAIL; } return res; }
static int mrvlqspi_fifo_flush(struct flash_bank *bank, int timeout) { int retval; uint32_t val; struct target *target = bank->target; retval = target_read_u32(target, mrvlqspi_get_reg(bank, CONF), &val); if (retval != ERROR_OK) return retval; val |= FIFO_FLUSH; retval = target_write_u32(target, mrvlqspi_get_reg(bank, CONF), val); if (retval != ERROR_OK) return retval; /* wait for fifo_flush to clear */ for (;;) { retval = target_read_u32(target, mrvlqspi_get_reg(bank, CONF), &val); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%08" PRIX32, val); if ((val & FIFO_FLUSH) == 0) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } return ERROR_OK; }
int arm926ejs_soft_reset_halt(struct target *target) { int retval = ERROR_OK; struct arm926ejs_common *arm926ejs = target_to_arm926(target); struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT]; retval = target_halt(target); if (retval != ERROR_OK) return retval; int64_t then = timeval_ms(); int timeout; while (!(timeout = ((timeval_ms()-then) > 1000))) { if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0) { embeddedice_read_reg(dbg_stat); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; } else break; if (debug_level >= 1) { /* do not eat all CPU, time out after 1 se*/ alive_sleep(100); } else keep_alive(); } if (timeout) { LOG_ERROR("Failed to halt CPU after 1 sec"); return ERROR_TARGET_TIMEOUT; } target->state = TARGET_HALTED; /* SVC, ARM state, IRQ and FIQ disabled */ uint32_t cpsr; cpsr = buf_get_u32(arm->cpsr->value, 0, 32); cpsr &= ~0xff; cpsr |= 0xd3; arm_set_cpsr(arm, cpsr); arm->cpsr->dirty = 1; /* start fetching from 0x0 */ buf_set_u32(arm->pc->value, 0, 32, 0x0); arm->pc->dirty = 1; arm->pc->valid = 1; retval = arm926ejs_disable_mmu_caches(target, 1, 1, 1); if (retval != ERROR_OK) return retval; arm926ejs->armv4_5_mmu.mmu_enabled = 0; arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0; arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0; return target_call_event_callbacks(target, TARGET_EVENT_HALTED); }
static int str9xpec_erase_area(struct flash_bank *bank, int first, int last) { struct scan_field field; uint8_t status; struct jtag_tap *tap; int i; uint8_t *buffer = NULL; struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv; tap = str9xpec_info->tap; if (!str9xpec_info->isc_enable) str9xpec_isc_enable(bank); if (!str9xpec_info->isc_enable) return ISC_STATUS_ERROR; buffer = calloc(DIV_ROUND_UP(64, 8), 1); LOG_DEBUG("erase: first_bank: %i, last_bank: %i", first, last); /* last bank: 0xFF signals a full erase (unlock complete device) */ /* last bank: 0xFE signals a option byte erase */ if (last == 0xFF) { for (i = 0; i < 64; i++) buf_set_u32(buffer, i, 1, 1); } else if (last == 0xFE) buf_set_u32(buffer, 49, 1, 1); else { for (i = first; i <= last; i++) buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1); } LOG_DEBUG("ISC_ERASE"); /* execute ISC_ERASE command */ str9xpec_set_instr(tap, ISC_ERASE, TAP_IRPAUSE); field.num_bits = 64; field.out_value = buffer; field.in_value = NULL; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_execute_queue(); jtag_add_sleep(10); /* wait for erase completion */ while (!((status = str9xpec_isc_status(tap)) & ISC_STATUS_BUSY)) alive_sleep(1); free(buffer); str9xpec_isc_disable(bank); return status; }
static int mrvlqspi_flash_busy_status(struct flash_bank *bank, int timeout) { uint8_t val; int retval; /* Flush read/write fifo's */ retval = mrvlqspi_fifo_flush(bank, FIFO_FLUSH_TIMEOUT); if (retval != ERROR_OK) return retval; /* Set instruction/addr count value */ retval = mrvlqspi_set_hdr_cnt(bank, 0x1); if (retval != ERROR_OK) return retval; /* Read flash status register in continuous manner */ retval = mrvlqspi_set_din_cnt(bank, 0x0); if (retval != ERROR_OK) return retval; /* Set instruction */ retval = mrvlqspi_set_instr(bank, INS_READ_STATUS); if (retval != ERROR_OK) return retval; /* Set data and addr pin length */ retval = mrvlqspi_set_conf(bank, 0x0); if (retval != ERROR_OK) return retval; /* Enable read mode transfer */ retval = mrvlqspi_start_transfer(bank, QSPI_R_EN); if (retval != ERROR_OK) return retval; for (;;) { retval = mrvlqspi_read_byte(bank, &val); if (retval != ERROR_OK) return retval; if (!(val & 0x1)) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } return mrvlqspi_stop_transfer(bank); }
static int nuc910_nand_ready(struct nand_device *nand, int timeout) { struct target *target = nand->target; uint32_t status; do { target_read_u32(target, NUC910_SMISR, &status); if (status & NUC910_SMISR_RB_) { return 1; } alive_sleep(1); } while (timeout-- > 0); return 0; }
static uint32_t lpc288x_wait_status_busy(struct flash_bank *bank, int timeout) { uint32_t status; struct target *target = bank->target; do { alive_sleep(1); timeout--; target_read_u32(target, F_STAT, &status); } while (((status & FS_DONE) == 0) && timeout); if (timeout == 0) { LOG_DEBUG("Timedout!"); return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; }
/* timeout in ms */ static int poll_tff(struct target *target, uint32_t io_base, int timeout) { long long endtime; if (SMI_READ_REG(SMI_SR) & SMI_TFF) return ERROR_OK; endtime = timeval_ms() + timeout; do { alive_sleep(1); if (SMI_READ_REG(SMI_SR) & SMI_TFF) return ERROR_OK; } while (timeval_ms() < endtime); LOG_ERROR("Timeout while polling TFF"); return ERROR_FLASH_OPERATION_FAILED; }
/* wait up to timeout_ms for controller to not be busy, * then check whether the command passed or failed. * * this function sleeps 1ms between checks (after the first one), * so in some cases may slow things down without a usleep after the first read */ static int aduc702x_check_flash_completion(struct target* target, unsigned int timeout_ms) { uint8_t v = 4; long long endtime = timeval_ms() + timeout_ms; while (1) { target_read_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEESTA, &v); if ((v & 4) == 0) break; alive_sleep(1); if (timeval_ms() >= endtime) break; } if (v & 2) return ERROR_FAIL; // if a command is ignored, both the success and fail bits may be 0 else if ((v & 3) == 0) return ERROR_FAIL; else return ERROR_OK; }
static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout) { struct target *target = bank->target; uint32_t status; int retval = ERROR_OK; /* wait for busy to clear */ for (;;) { retval = stm32x_get_flash_status(bank, &status); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%" PRIx32 "", status); if ((status & FLASH_BSY) == 0) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } if (status & FLASH_WRPRTERR) { LOG_ERROR("stm32x device protected"); retval = ERROR_FAIL; } if (status & FLASH_PGERR) { LOG_ERROR("stm32x device programming failed"); retval = ERROR_FAIL; } /* Clear but report errors */ if (status & (FLASH_WRPRTERR | FLASH_PGERR)) { /* If this operation fails, we ignore it and report the original * retval */ target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_SR), FLASH_WRPRTERR | FLASH_PGERR); } return retval; }
static uint32_t stm32x_wait_status_busy(struct flash_bank *bank, int timeout) { struct target *target = bank->target; uint32_t status; /* wait for busy to clear */ while (((status = stm32x_get_flash_status(bank)) & FLASH_BSY) && (timeout-- > 0)) { LOG_DEBUG("status: 0x%" PRIx32 "", status); alive_sleep(1); } /* Clear but report errors */ if (status & (FLASH_WRPRTERR | FLASH_PGERR)) { target_write_u32(target, STM32_FLASH_SR, FLASH_WRPRTERR | FLASH_PGERR); } return status; }
static int jtagspi_wait(struct flash_bank *bank, int timeout_ms) { uint32_t status; int64_t t0 = timeval_ms(); int64_t dt; do { dt = timeval_ms() - t0; jtagspi_read_status(bank, &status); if ((status & SPIFLASH_BSY_BIT) == 0) { LOG_DEBUG("waited %" PRId64 " ms", dt); return ERROR_OK; } alive_sleep(1); } while (dt <= timeout_ms); LOG_ERROR("timeout, device still busy"); return ERROR_FAIL; }
/** * Determine if the NAND device is ready by looking at the ready/~busy pin. * * @param nand NAND device to check. * @param timeout Time in milliseconds to wait for NAND to be ready. * @return True if the NAND is ready in the timeout period. */ static int at91sam9_nand_ready(struct nand_device *nand, int timeout) { struct at91sam9_nand *info = nand->controller_priv; struct target *target = nand->target; uint32_t status; if (!at91sam9_halted(target, "nand ready")) return 0; do { target_read_u32(target, info->busy.pioc + AT91C_PIOx_PDSR, &status); if (status & (1 << info->busy.num)) return 1; alive_sleep(1); } while (timeout-- > 0); return 0; }
/* wait for flash to become idle or report errors. FIX!!! what's the maximum timeout??? The documentation doesn't state any maximum time.... by inspection it seems > 1000ms is to be expected. 10000ms is long enough that it should cover anything, yet not quite be equivalent to an infinite loop. */ static int str7x_waitbusy(struct flash_bank *bank) { int err; int i; struct target *target = bank->target; struct str7x_flash_bank *str7x_info = bank->driver_priv; for (i = 0 ; i < 10000; i++) { uint32_t retval; err = target_read_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), &retval); if (err != ERROR_OK) return err; if ((retval & str7x_info->busy_bits) == 0) return ERROR_OK; alive_sleep(1); } LOG_ERROR("Timed out waiting for str7x flash"); return ERROR_FAIL; }
static int s3c2410_nand_ready(struct nand_device *nand, int timeout) { struct target *target = nand->target; uint8_t status; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use S3C24XX NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } do { target_read_u8(target, S3C2410_NFSTAT, &status); if (status & S3C2410_NFSTAT_BUSY) return 1; alive_sleep(1); } while (timeout-- > 0); return 0; }
/* timeout in ms */ static int wait_till_ready(struct flash_bank *bank, int timeout) { uint32_t status; int retval; long long endtime; endtime = timeval_ms() + timeout; do { /* read flash status register */ retval = read_status_reg(bank, &status); if (retval != ERROR_OK) return retval; if ((status & SPIFLASH_BSY_BIT) == 0) return ERROR_OK; alive_sleep(1); } while (timeval_ms() < endtime); LOG_ERROR("timeout"); return ERROR_FAIL; }
int s3c2410_nand_ready(struct nand_device_s *device, int timeout) { s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv; target_t *target = s3c24xx_info->target; u8 status; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use S3C24XX NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } do { target_read_u8(target, S3C2410_NFSTAT, &status); if (status & S3C2410_NFSTAT_BUSY) return 1; alive_sleep(1); } while (timeout-- > 0); return 0; }
static int mrvlqspi_set_ss_state(struct flash_bank *bank, bool state, int timeout) { int retval; uint32_t regval; struct target *target = bank->target; retval = target_read_u32(target, mrvlqspi_get_reg(bank, CNTL), ®val); if (retval != ERROR_OK) return retval; if (state) regval |= SS_EN; else regval &= ~(SS_EN); retval = target_write_u32(target, mrvlqspi_get_reg(bank, CNTL), regval); if (retval != ERROR_OK) return retval; /* wait for xfer_ready to set */ for (;;) { retval = target_read_u32(target, mrvlqspi_get_reg(bank, CNTL), ®val); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%08" PRIx32, regval); if ((regval & XFER_RDY) == XFER_RDY) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } return ERROR_OK; }
static int or1k_is_cpu_running(struct target *target, int *running) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); int retval; int tries = 0; const int RETRIES_MAX = 5; /* Have a retry loop to determine of the CPU is running. If target has been hard reset for any reason, it might take a couple of goes before it's ready again. */ while (tries < RETRIES_MAX) { tries++; retval = du_core->or1k_is_cpu_running(&or1k->jtag, running); if (retval != ERROR_OK) { LOG_WARNING("Debug IF CPU control reg read failure."); /* Try once to restart the JTAG infrastructure - quite possibly the board has just been reset. */ LOG_WARNING("Resetting JTAG TAP state and reconnectiong to debug IF."); du_core->or1k_jtag_init(&or1k->jtag); LOG_WARNING("...attempt %d of %d", tries, RETRIES_MAX); alive_sleep(2); continue; } else return ERROR_OK; } LOG_ERROR("Could not re-establish communication with target"); return retval; }
static int str9x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; uint32_t words_remaining = (count / 2); uint32_t bytes_remaining = (count & 0x00000001); uint32_t address = bank->base + offset; uint32_t bytes_written = 0; uint8_t status; int retval; uint32_t check_address = offset; uint32_t bank_adr; int i; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset & 0x1) { LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } for (i = 0; i < bank->num_sectors; i++) { uint32_t sec_start = bank->sectors[i].offset; uint32_t sec_end = sec_start + bank->sectors[i].size; /* check if destination falls within the current sector */ if ((check_address >= sec_start) && (check_address < sec_end)) { /* check if destination ends in the current sector */ if (offset + count < sec_end) check_address = offset + count; else check_address = sec_end; } } if (check_address != offset + count) return ERROR_FLASH_DST_OUT_OF_BANK; /* multiple half words (2-byte) to be programmed? */ if (words_remaining > 0) { /* try using a block write */ retval = str9x_write_block(bank, buffer, offset, words_remaining); if (retval != ERROR_OK) { if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { /* if block write failed (no sufficient working area), * we use normal (slow) single dword accesses */ LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); } else if (retval == ERROR_FLASH_OPERATION_FAILED) { LOG_ERROR("flash writing failed"); return ERROR_FLASH_OPERATION_FAILED; } } else { buffer += words_remaining * 2; address += words_remaining * 2; words_remaining = 0; } } while (words_remaining > 0) { bank_adr = address & ~0x03; /* write data command */ target_write_u16(target, bank_adr, 0x40); target_write_memory(target, address, 2, 1, buffer + bytes_written); /* get status command */ target_write_u16(target, bank_adr, 0x70); int timeout; for (timeout = 0; timeout < 1000; timeout++) { target_read_u8(target, bank_adr, &status); if (status & 0x80) break; alive_sleep(1); } if (timeout == 1000) { LOG_ERROR("write timed out"); return ERROR_FAIL; } /* clear status reg and read array */ target_write_u16(target, bank_adr, 0x50); target_write_u16(target, bank_adr, 0xFF); if (status & 0x10) return ERROR_FLASH_OPERATION_FAILED; else if (status & 0x02) return ERROR_FLASH_OPERATION_FAILED; bytes_written += 2; words_remaining--; address += 2; } if (bytes_remaining) { uint8_t last_halfword[2] = {0xff, 0xff}; /* copy the last remaining bytes into the write buffer */ memcpy(last_halfword, buffer+bytes_written, bytes_remaining); bank_adr = address & ~0x03; /* write data command */ target_write_u16(target, bank_adr, 0x40); target_write_memory(target, address, 2, 1, last_halfword); /* query status command */ target_write_u16(target, bank_adr, 0x70); int timeout; for (timeout = 0; timeout < 1000; timeout++) { target_read_u8(target, bank_adr, &status); if (status & 0x80) break; alive_sleep(1); } if (timeout == 1000) { LOG_ERROR("write timed out"); return ERROR_FAIL; } /* clear status reg and read array */ target_write_u16(target, bank_adr, 0x50); target_write_u16(target, bank_adr, 0xFF); if (status & 0x10) return ERROR_FLASH_OPERATION_FAILED; else if (status & 0x02) return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; }
void zy1000_reset(int trst, int srst) { LOG_DEBUG("zy1000 trst=%d, srst=%d", trst, srst); if(!srst) { ZY1000_POKE(ZY1000_JTAG_BASE+0x14, 0x00000001); } else { /* Danger!!! if clk!=0 when in * idle in TAP_IDLE, reset halt on str912 will fail. */ ZY1000_POKE(ZY1000_JTAG_BASE+0x10, 0x00000001); } if(!trst) { ZY1000_POKE(ZY1000_JTAG_BASE+0x14, 0x00000002); } else { /* assert reset */ ZY1000_POKE(ZY1000_JTAG_BASE+0x10, 0x00000002); } if (trst||(srst&&(jtag_reset_config & RESET_SRST_PULLS_TRST))) { waitIdle(); /* we're now in the RESET state until trst is deasserted */ ZY1000_POKE(ZY1000_JTAG_BASE+0x20, TAP_RESET); } else { /* We'll get RCLK failure when we assert TRST, so clear any false positives here */ ZY1000_POKE(ZY1000_JTAG_BASE+0x14, 0x400); } /* wait for srst to float back up */ if (!srst) { int i; for (i=0; i<1000; i++) { // We don't want to sense our own reset, so we clear here. // There is of course a timing hole where we could loose // a "real" reset. if (!readSRST()) break; /* wait 1ms */ alive_sleep(1); } if (i==1000) { LOG_USER("SRST didn't deassert after %dms", i); } else if (i>1) { LOG_USER("SRST took %dms to deassert", i); } } }
static int str9x_erase(struct flash_bank *bank, int first, int last) { struct target *target = bank->target; int i; uint32_t adr; uint8_t status; uint8_t erase_cmd; int total_timeout; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* Check if we can erase whole bank */ if ((first == 0) && (last == (bank->num_sectors - 1))) { /* Optimize to run erase bank command instead of sector */ erase_cmd = 0x80; /* Add timeout duration since erase bank takes more time */ total_timeout = 1000 * bank->num_sectors; } else { /* Erase sector command */ erase_cmd = 0x20; total_timeout = 1000; } /* this is so the compiler can *know* */ assert(total_timeout > 0); for (i = first; i <= last; i++) { int retval; adr = bank->base + bank->sectors[i].offset; /* erase sectors or block */ retval = target_write_u16(target, adr, erase_cmd); if (retval != ERROR_OK) return retval; retval = target_write_u16(target, adr, 0xD0); if (retval != ERROR_OK) return retval; /* get status */ retval = target_write_u16(target, adr, 0x70); if (retval != ERROR_OK) return retval; int timeout; for (timeout = 0; timeout < total_timeout; timeout++) { retval = target_read_u8(target, adr, &status); if (retval != ERROR_OK) return retval; if (status & 0x80) break; alive_sleep(1); } if (timeout == total_timeout) { LOG_ERROR("erase timed out"); return ERROR_FAIL; } /* clear status, also clear read array */ retval = target_write_u16(target, adr, 0x50); if (retval != ERROR_OK) return retval; /* read array command */ retval = target_write_u16(target, adr, 0xFF); if (retval != ERROR_OK) return retval; if (status & 0x22) { LOG_ERROR("error erasing flash bank, status: 0x%x", status); return ERROR_FLASH_OPERATION_FAILED; } /* If we ran erase bank command, we are finished */ if (erase_cmd == 0x80) break; } for (i = first; i <= last; i++) bank->sectors[i].is_erased = 1; return ERROR_OK; }
static int str9x_erase(struct flash_bank *bank, int first, int last) { struct target *target = bank->target; int i; uint32_t adr; uint8_t status; uint8_t erase_cmd; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /*A slower but stable way of erasing*/ /* Erase sector command */ erase_cmd = 0x20; for (i = first; i <= last; i++) { int retval; adr = bank->base + bank->sectors[i].offset; /* erase sectors */ if ((retval = target_write_u16(target, adr, erase_cmd)) != ERROR_OK) { return retval; } if ((retval = target_write_u16(target, adr, 0xD0)) != ERROR_OK) { return retval; } /* get status */ if ((retval = target_write_u16(target, adr, 0x70)) != ERROR_OK) { return retval; } int timeout; for (timeout = 0; timeout < 1000; timeout++) { if ((retval = target_read_u8(target, adr, &status)) != ERROR_OK) { return retval; } if (status & 0x80) break; alive_sleep(1); } if (timeout == 1000) { LOG_ERROR("erase timed out"); return ERROR_FAIL; } /* clear status, also clear read array */ if ((retval = target_write_u16(target, adr, 0x50)) != ERROR_OK) { return retval; } /* read array command */ if ((retval = target_write_u16(target, adr, 0xFF)) != ERROR_OK) { return retval; } if (status & 0x22) { LOG_ERROR("error erasing flash bank, status: 0x%x", status); return ERROR_FLASH_OPERATION_FAILED; } } for (i = first; i <= last; i++) bank->sectors[i].is_erased = 1; return ERROR_OK; }