static int aduc702x_erase(struct flash_bank *bank, int first, int last) { //int res; int x; int count; //uint32_t v; struct target *target = bank->target; aduc702x_set_write_enable(target, 1); /* mass erase */ if (((first | last) == 0) || ((first == 0) && (last >= bank->num_sectors))) { LOG_DEBUG("performing mass erase.\n"); target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEDAT, 0x3cff); target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, 0xffc3); target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x06); if (aduc702x_check_flash_completion(target, 3500) != ERROR_OK) { LOG_ERROR("mass erase failed\n"); aduc702x_set_write_enable(target, 0); return ERROR_FLASH_OPERATION_FAILED; } LOG_DEBUG("mass erase successful.\n"); return ERROR_OK; } else { unsigned long adr; count = last - first + 1; for (x = 0; x < count; ++x) { adr = bank->base + ((first + x) * 512); target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, adr); target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x05); if (aduc702x_check_flash_completion(target, 50) != ERROR_OK) { LOG_ERROR("failed to erase sector at address 0x%08lX\n", adr); aduc702x_set_write_enable(target, 0); return ERROR_FLASH_SECTOR_NOT_ERASED; } LOG_DEBUG("erased sector at address 0x%08lX\n", adr); } } aduc702x_set_write_enable(target, 0); return ERROR_OK; }
/* sets FEEMOD bit 3 * enable = 1 enables writes & erases, 0 disables them */ static int aduc702x_set_write_enable(struct target *target, int enable) { /* don't bother to preserve int enable bit here */ target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEMOD, enable ? 8 : 0); return ERROR_OK; }
/* write a word (16bit) from the pc to the netx */ int fn_write_data16(void *pvHandle, unsigned long ulNetxAddress, unsigned short usData) { command_context_t *cmd_ctx; target_t *target; int iResult; /* cast the handle to the command context */ cmd_ctx = (command_context_t*)pvHandle; /* get the target from the command context */ target = get_current_target(cmd_ctx); /* read the data from the netX */ iResult = target_write_u16(target, ulNetxAddress, usData); if( iResult==ERROR_OK ) { iResult = 0; } else { iResult = 1; } wxMilliSleep(1); return iResult; }
/** Checks whether a memory region is zeroed. */ int armv7m_blank_check_memory(struct target *target, uint32_t address, uint32_t count, uint32_t* blank) { struct working_area *erase_check_algorithm; struct reg_param reg_params[3]; struct armv7m_algorithm armv7m_info; int retval; uint32_t i; static const uint16_t erase_check_code[] = { /* loop: */ 0xF810, 0x3B01, /* ldrb r3, [r0], #1 */ 0xEA02, 0x0203, /* and r2, r2, r3 */ 0x3901, /* subs r1, r1, #1 */ 0xD1F9, /* bne loop */ 0xBE00, /* bkpt #0 */ }; /* make sure we have a working area */ if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK) { return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* convert flash writing code into a buffer in target endianness */ for (i = 0; i < ARRAY_SIZE(erase_check_code); i++) target_write_u16(target, erase_check_algorithm->address + i*sizeof(uint16_t), erase_check_code[i]); armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARMV7M_MODE_ANY; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); buf_set_u32(reg_params[0].value, 0, 32, address); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); buf_set_u32(reg_params[1].value, 0, 32, count); init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT); buf_set_u32(reg_params[2].value, 0, 32, 0xff); retval = target_run_algorithm(target, 0, NULL, 3, reg_params, erase_check_algorithm->address, erase_check_algorithm->address + (sizeof(erase_check_code) - 2), 10000, &armv7m_info); if (retval == ERROR_OK) *blank = buf_get_u32(reg_params[2].value, 0, 32); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); target_free_working_area(target, erase_check_algorithm); return retval; }
/* All-JTAG, single-access method. Very slow. Used only if there is no * working area available. */ static int aduc702x_write_single(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { uint32_t x; uint8_t b; struct target *target = bank->target; aduc702x_set_write_enable(target, 1); for (x = 0; x < count; x += 2) { /* FEEADR = address */ target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, offset + x); /* set up data */ if ((x + 1) == count) { /* last byte */ target_read_u8(target, offset + x + 1, &b); } else b = buffer[x + 1]; target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEDAT, buffer[x] | (b << 8)); /* do single-write command */ target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x02); if (aduc702x_check_flash_completion(target, 1) != ERROR_OK) { LOG_ERROR("single write failed for address 0x%08lX", (unsigned long)(offset + x)); aduc702x_set_write_enable(target, 0); return ERROR_FLASH_OPERATION_FAILED; } } LOG_DEBUG("wrote %d bytes at address 0x%08lX", (int)count, (unsigned long)(offset + x)); aduc702x_set_write_enable(target, 0); return ERROR_OK; }
int s3c24xx_address(struct nand_device *nand, uint8_t address) { struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv; struct target *target = nand->target; if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use S3C24XX NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } target_write_u16(target, s3c24xx_info->addr, address); return ERROR_OK; }
static int str9x_protect(struct flash_bank *bank, int set, int first, int last) { struct target *target = bank->target; int i; uint32_t adr; uint8_t status; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } for (i = first; i <= last; i++) { /* Level One Protection */ adr = bank->base + bank->sectors[i].offset; target_write_u16(target, adr, 0x60); if (set) target_write_u16(target, adr, 0x01); else target_write_u16(target, adr, 0xD0); /* query status */ target_read_u8(target, adr, &status); /* clear status, also clear read array */ target_write_u16(target, adr, 0x50); /* read array command */ target_write_u16(target, adr, 0xFF); } return ERROR_OK; }
static int str9x_protect_check(struct flash_bank *bank) { int retval; struct str9x_flash_bank *str9x_info = bank->driver_priv; struct target *target = bank->target; int i; uint32_t adr; uint32_t status = 0; uint16_t hstatus = 0; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* read level one protection */ if (str9x_info->variant) { if (str9x_info->bank1) { adr = bank1start + 0x18; retval = target_write_u16(target, adr, 0x90); if (retval != ERROR_OK) return retval; retval = target_read_u16(target, adr, &hstatus); if (retval != ERROR_OK) return retval; status = hstatus; } else { adr = bank1start + 0x14; retval = target_write_u16(target, adr, 0x90); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, adr, &status); if (retval != ERROR_OK) return retval; } } else { adr = bank1start + 0x10; retval = target_write_u16(target, adr, 0x90); if (retval != ERROR_OK) return retval; retval = target_read_u16(target, adr, &hstatus); if (retval != ERROR_OK) return retval; status = hstatus; } /* read array command */ retval = target_write_u16(target, adr, 0xFF); if (retval != ERROR_OK) return retval; for (i = 0; i < bank->num_sectors; i++) { if (status & str9x_info->sector_bits[i]) bank->sectors[i].is_protected = 1; else bank->sectors[i].is_protected = 0; } return ERROR_OK; }
static int stm32x_write(struct flash_bank *bank, 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; int retval; 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; } /* unlock flash registers */ retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY2); if (retval != ERROR_OK) return retval; /* multiple half words (2-byte) to be programmed? */ if (words_remaining > 0) { /* try using a block write */ if ((retval = stm32x_write_block(bank, buffer, offset, words_remaining)) != 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 { buffer += words_remaining * 2; address += words_remaining * 2; words_remaining = 0; } } if ((retval != ERROR_OK) && (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)) return retval; while (words_remaining > 0) { uint16_t value; memcpy(&value, buffer + bytes_written, sizeof(uint16_t)); retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PG); if (retval != ERROR_OK) return retval; retval = target_write_u16(target, address, value); if (retval != ERROR_OK) return retval; retval = stm32x_wait_status_busy(bank, 5); if (retval != ERROR_OK) return retval; bytes_written += 2; words_remaining--; address += 2; } if (bytes_remaining) { uint16_t value = 0xffff; memcpy(&value, buffer + bytes_written, bytes_remaining); retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PG); if (retval != ERROR_OK) return retval; retval = target_write_u16(target, address, value); if (retval != ERROR_OK) return retval; retval = stm32x_wait_status_busy(bank, 5); if (retval != ERROR_OK) return retval; } return target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK); }
static int stm32x_write_options(struct flash_bank *bank) { struct stm32x_flash_bank *stm32x_info = NULL; struct target *target = bank->target; stm32x_info = bank->driver_priv; /* unlock flash registers */ int retval = target_write_u32(target, STM32_FLASH_KEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, STM32_FLASH_KEYR, KEY2); if (retval != ERROR_OK) return retval; /* unlock option flash registers */ retval = target_write_u32(target, STM32_FLASH_OPTKEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, STM32_FLASH_OPTKEYR, KEY2); if (retval != ERROR_OK) return retval; /* program option bytes */ retval = target_write_u32(target, STM32_FLASH_CR, FLASH_OPTPG | FLASH_OPTWRE); if (retval != ERROR_OK) return retval; /* write user option byte */ retval = target_write_u16(target, STM32_OB_USER, stm32x_info->option_bytes.user_options); if (retval != ERROR_OK) return retval; retval = stm32x_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* write protection byte 1 */ retval = target_write_u16(target, STM32_OB_WRP0, stm32x_info->option_bytes.protection[0]); if (retval != ERROR_OK) return retval; retval = stm32x_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* write protection byte 2 */ retval = target_write_u16(target, STM32_OB_WRP1, stm32x_info->option_bytes.protection[1]); if (retval != ERROR_OK) return retval; retval = stm32x_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* write protection byte 3 */ retval = target_write_u16(target, STM32_OB_WRP2, stm32x_info->option_bytes.protection[2]); if (retval != ERROR_OK) return retval; retval = stm32x_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* write protection byte 4 */ retval = target_write_u16(target, STM32_OB_WRP3, stm32x_info->option_bytes.protection[3]); if (retval != ERROR_OK) return retval; retval = stm32x_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* write readout protection bit */ retval = target_write_u16(target, STM32_OB_RDP, stm32x_info->option_bytes.RDP); if (retval != ERROR_OK) return retval; retval = stm32x_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK); if (retval != ERROR_OK) return retval; return ERROR_OK; }
static int em357_write_options(struct flash_bank *bank) { struct em357_flash_bank *em357_info = NULL; struct target *target = bank->target; em357_info = bank->driver_priv; /* unlock flash registers */ int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2); if (retval != ERROR_OK) return retval; /* unlock option flash registers */ retval = target_write_u32(target, EM357_FLASH_OPTKEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_OPTKEYR, KEY2); if (retval != ERROR_OK) return retval; /* program option bytes */ retval = target_write_u32(target, EM357_FLASH_CR, FLASH_OPTPG | FLASH_OPTWRE); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* write protection byte 1 */ retval = target_write_u16(target, EM357_OB_WRP0, em357_info->option_bytes.protection[0]); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* write protection byte 2 */ retval = target_write_u16(target, EM357_OB_WRP1, em357_info->option_bytes.protection[1]); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* write protection byte 3 */ retval = target_write_u16(target, EM357_OB_WRP2, em357_info->option_bytes.protection[2]); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* write readout protection bit */ retval = target_write_u16(target, EM357_OB_RDP, em357_info->option_bytes.RDP); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_CR, FLASH_LOCK); if (retval != ERROR_OK) return retval; return ERROR_OK; }
static int fm3_erase(struct flash_bank *bank, int first, int last) { struct fm3_flash_bank *fm3_info = bank->driver_priv; struct target *target = bank->target; int retval = ERROR_OK; uint32_t u32DummyRead; int sector, odd; uint32_t u32FlashType; uint32_t u32FlashSeqAddress1; uint32_t u32FlashSeqAddress2; u32FlashType = (uint32_t) fm3_info->flashtype; if (u32FlashType == fm3_flash_type1) { u32FlashSeqAddress1 = 0x00001550; u32FlashSeqAddress2 = 0x00000AA8; } else if (u32FlashType == fm3_flash_type2) { u32FlashSeqAddress1 = 0x00000AA8; u32FlashSeqAddress2 = 0x00000554; } else { LOG_ERROR("Flash/Device type unknown!"); return ERROR_FLASH_OPERATION_FAILED; } if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } LOG_INFO("Fujitsu MB9Bxxx: Sector Erase ... (%d to %d)", first, last); /* FASZR = 0x01, Enables CPU Programming Mode (16-bit Flash acccess) */ retval = target_write_u32(target, 0x40000000, 0x0001); if (retval != ERROR_OK) return retval; /* dummy read of FASZR */ retval = target_read_u32(target, 0x40000000, &u32DummyRead); if (retval != ERROR_OK) return retval; for (sector = first ; sector <= last ; sector++) { uint32_t offset = bank->sectors[sector].offset; for (odd = 0; odd < 2 ; odd++) { if (odd) offset += 4; /* Flash unlock sequence */ retval = target_write_u16(target, u32FlashSeqAddress1, 0x00AA); if (retval != ERROR_OK) return retval; retval = target_write_u16(target, u32FlashSeqAddress2, 0x0055); if (retval != ERROR_OK) return retval; retval = target_write_u16(target, u32FlashSeqAddress1, 0x0080); if (retval != ERROR_OK) return retval; retval = target_write_u16(target, u32FlashSeqAddress1, 0x00AA); if (retval != ERROR_OK) return retval; retval = target_write_u16(target, u32FlashSeqAddress2, 0x0055); if (retval != ERROR_OK) return retval; /* Sector erase command (0x0030) */ retval = target_write_u16(target, offset, 0x0030); if (retval != ERROR_OK) return retval; retval = fm3_busy_wait(target, offset, 500); if (retval != ERROR_OK) return retval; } bank->sectors[sector].is_erased = 1; } /* FASZR = 0x02, Enables CPU Run Mode (32-bit Flash acccess) */ retval = target_write_u32(target, 0x40000000, 0x0002); if (retval != ERROR_OK) return retval; /* dummy read of FASZR */ retval = target_read_u32(target, 0x40000000, &u32DummyRead); return retval; }
/* Chip erase */ static int fm3_chip_erase(struct flash_bank *bank) { struct target *target = bank->target; struct fm3_flash_bank *fm3_info2 = bank->driver_priv; int retval = ERROR_OK; uint32_t u32DummyRead; uint32_t u32FlashType; uint32_t u32FlashSeqAddress1; uint32_t u32FlashSeqAddress2; u32FlashType = (uint32_t) fm3_info2->flashtype; if (u32FlashType == fm3_flash_type1) { LOG_INFO("*** Erasing mb9bfxxx type"); u32FlashSeqAddress1 = 0x00001550; u32FlashSeqAddress2 = 0x00000AA8; } else if (u32FlashType == fm3_flash_type2) { LOG_INFO("*** Erasing mb9afxxx type"); u32FlashSeqAddress1 = 0x00000AA8; u32FlashSeqAddress2 = 0x00000554; } else { LOG_ERROR("Flash/Device type unknown!"); return ERROR_FLASH_OPERATION_FAILED; } if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } LOG_INFO("Fujitsu MB9[AB]xxx: Chip Erase ... (may take several seconds)"); /* Implement Flash chip erase (mass erase) completely on host */ /* FASZR = 0x01, Enables CPU Programming Mode (16-bit Flash access) */ retval = target_write_u32(target, 0x40000000, 0x0001); if (retval != ERROR_OK) return retval; /* dummy read of FASZR */ retval = target_read_u32(target, 0x40000000, &u32DummyRead); if (retval != ERROR_OK) return retval; /* Flash unlock sequence */ retval = target_write_u16(target, u32FlashSeqAddress1, 0x00AA); if (retval != ERROR_OK) return retval; retval = target_write_u16(target, u32FlashSeqAddress2, 0x0055); if (retval != ERROR_OK) return retval; retval = target_write_u16(target, u32FlashSeqAddress1, 0x0080); if (retval != ERROR_OK) return retval; retval = target_write_u16(target, u32FlashSeqAddress1, 0x00AA); if (retval != ERROR_OK) return retval; retval = target_write_u16(target, u32FlashSeqAddress2, 0x0055); if (retval != ERROR_OK) return retval; /* Chip Erase command (0x0010) */ retval = target_write_u16(target, u32FlashSeqAddress1, 0x0010); if (retval != ERROR_OK) return retval; retval = fm3_busy_wait(target, u32FlashSeqAddress2, 20000); /* 20s timeout */ if (retval != ERROR_OK) return retval; /* FASZR = 0x02, Re-enables CPU Run Mode (32-bit Flash access) */ retval = target_write_u32(target, 0x40000000, 0x0002); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, 0x40000000, &u32DummyRead); /* dummy read of FASZR */ return retval; }
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; }
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_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; }
/** Generates a CRC32 checksum of a memory region. */ int armv7m_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t* checksum) { struct working_area *crc_algorithm; struct armv7m_algorithm armv7m_info; struct reg_param reg_params[2]; int retval; /* see contib/loaders/checksum/armv7m_crc.s for src */ static const uint16_t cortex_m3_crc_code[] = { 0x4602, /* mov r2, r0 */ 0xF04F, 0x30FF, /* mov r0, #0xffffffff */ 0x460B, /* mov r3, r1 */ 0xF04F, 0x0400, /* mov r4, #0 */ 0xE013, /* b ncomp */ /* nbyte: */ 0x5D11, /* ldrb r1, [r2, r4] */ 0xF8DF, 0x7028, /* ldr r7, CRC32XOR */ 0xEA80, 0x6001, /* eor r0, r0, r1, asl #24 */ 0xF04F, 0x0500, /* mov r5, #0 */ /* loop: */ 0x2800, /* cmp r0, #0 */ 0xEA4F, 0x0640, /* mov r6, r0, asl #1 */ 0xF105, 0x0501, /* add r5, r5, #1 */ 0x4630, /* mov r0, r6 */ 0xBFB8, /* it lt */ 0xEA86, 0x0007, /* eor r0, r6, r7 */ 0x2D08, /* cmp r5, #8 */ 0xD1F4, /* bne loop */ 0xF104, 0x0401, /* add r4, r4, #1 */ /* ncomp: */ 0x429C, /* cmp r4, r3 */ 0xD1E9, /* bne nbyte */ 0xBE00, /* bkpt #0 */ 0x1DB7, 0x04C1 /* CRC32XOR: .word 0x04C11DB7 */ }; uint32_t i; retval = target_alloc_working_area(target, sizeof(cortex_m3_crc_code), &crc_algorithm); if (retval != ERROR_OK) return retval; /* convert flash writing code into a buffer in target endianness */ for (i = 0; i < ARRAY_SIZE(cortex_m3_crc_code); i++) { retval = target_write_u16(target, crc_algorithm->address + i*sizeof(uint16_t), cortex_m3_crc_code[i]); if (retval != ERROR_OK) goto cleanup; } armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARMV7M_MODE_ANY; init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); buf_set_u32(reg_params[0].value, 0, 32, address); buf_set_u32(reg_params[1].value, 0, 32, count); int timeout = 20000 * (1 + (count / (1024 * 1024))); retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address, crc_algorithm->address + (sizeof(cortex_m3_crc_code) - 6), timeout, &armv7m_info); if (retval == ERROR_OK) *checksum = buf_get_u32(reg_params[0].value, 0, 32); else LOG_ERROR("error executing cortex_m3 crc algorithm"); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); cleanup: target_free_working_area(target, crc_algorithm); return retval; }