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_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_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; }
bool lpc11xx_probe(target *t) { uint32_t idcode; /* read the device ID register */ idcode = target_mem_read32(t, LPC11XX_DEVICE_ID); switch (idcode) { case 0x041E502B: case 0x2516D02B: case 0x0416502B: case 0x2516902B: /* lpc1111 */ case 0x2524D02B: case 0x0425502B: case 0x2524902B: case 0x1421102B: /* lpc1112 */ case 0x0434502B: case 0x2532902B: case 0x0434102B: case 0x2532102B: /* lpc1113 */ case 0x0444502B: case 0x2540902B: case 0x0444102B: case 0x2540102B: case 0x1440102B: /* lpc1114 */ case 0x0A40902B: case 0x1A40902B: case 0x2058002B: /* lpc1115 */ case 0x1431102B: /* lpc11c22 */ case 0x1430102B: /* lpc11c24 */ case 0x095C802B: /* lpc11u12x/201 */ case 0x295C802B: case 0x097A802B: /* lpc11u13/201 */ case 0x297A802B: case 0x0998802B: /* lpc11u14x/201 */ case 0x2998802B: case 0x2972402B: /* lpc11u23/301 */ case 0x2988402B: /* lpc11u24x/301 */ case 0x2980002B: /* lpc11u24x/401 */ t->driver = "LPC11xx"; target_add_ram(t, 0x10000000, 0x2000); lpc11xx_add_flash(t, 0x00000000, 0x20000, 0x1000); return true; } idcode = target_mem_read32(t, LPC8XX_DEVICE_ID); switch (idcode) { case 0x00008100: /* LPC810M021FN8 */ case 0x00008110: /* LPC811M001JDH16 */ case 0x00008120: /* LPC812M101JDH16 */ case 0x00008121: /* LPC812M101JD20 */ case 0x00008122: /* LPC812M101JDH20 / LPC812M101JTB16 */ t->driver = "LPC8xx"; target_add_ram(t, 0x10000000, 0x1000); lpc11xx_add_flash(t, 0x00000000, 0x4000, 0x400); return true; } return false; }
static int kl_gen_flash_done(struct target_flash *f) { struct kinetis_flash *kf = (struct kinetis_flash *)f; if (unsafe_enabled) return 0; if (target_mem_read8(f->t, FLASH_SECURITY_BYTE_ADDRESS) == FLASH_SECURITY_BYTE_UNSECURED) return 0; /* Load the security byte based on the alignment (determine 8 byte phrases * vs 4 byte phrases). */ if (kf->write_len == 8) { uint32_t vals[2]; vals[0] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS-4); vals[1] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS); vals[1] = (vals[1] & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED; kl_gen_command(f->t, FTFE_CMD_PROGRAM_PHRASE, FLASH_SECURITY_BYTE_ADDRESS - 4, (uint8_t*)vals); } else { uint32_t val = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS); val = (val & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED; kl_gen_command(f->t, FTFA_CMD_PROGRAM_LONGWORD, FLASH_SECURITY_BYTE_ADDRESS, (uint8_t*)&val); } 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 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 stm32f4_probe(target *t) { bool f2 = false; uint32_t idcode; idcode = target_mem_read32(t, DBGMCU_IDCODE); idcode &= 0xFFF; if (idcode == 0x411) { /* F405 revision A have a wrong IDCODE, use ARM_CPUID to make the * distinction with F205. Revision is also wrong (0x2000 instead * of 0x1000). See F40x/F41x errata. */ uint32_t cpuid = target_mem_read32(t, ARM_CPUID); if ((cpuid & 0xFFF0) == 0xC240) idcode = 0x413; else f2 = true; } switch(idcode) { case 0x419: /* 427/437 */ /* Second bank for 2M parts. */ stm32f4_add_flash(t, 0x8100000, 0x10000, 0x4000, 12); stm32f4_add_flash(t, 0x8110000, 0x10000, 0x10000, 16); stm32f4_add_flash(t, 0x8120000, 0xE0000, 0x20000, 17); /* Fall through for stuff common to F40x/F41x */ case 0x411: /* F205 */ case 0x413: /* F405 */ case 0x421: /* F446 */ case 0x423: /* F401 B/C RM0368 Rev.3 */ case 0x431: /* F411 RM0383 Rev.4 */ case 0x433: /* F401 D/E RM0368 Rev.3 */ t->driver = f2 ? stm32f2_driver_str : stm32f4_driver_str; if (!f2) target_add_ram(t, 0x10000000, 0x10000); target_add_ram(t, 0x20000000, 0x30000); stm32f4_add_flash(t, 0x8000000, 0x10000, 0x4000, 0); stm32f4_add_flash(t, 0x8010000, 0x10000, 0x10000, 4); stm32f4_add_flash(t, 0x8020000, 0xE0000, 0x20000, 5); target_add_commands(t, stm32f4_cmd_list, f2 ? "STM32F2" : "STM32F4"); break; case 0x449: /* F7x6 RM0385 Rev.2 */ t->driver = stm32f7_driver_str; target_add_ram(t, 0x00000000, 0x4000); target_add_ram(t, 0x20000000, 0x50000); stm32f4_add_flash(t, 0x8000000, 0x20000, 0x8000, 0); stm32f4_add_flash(t, 0x8020000, 0x20000, 0x20000, 4); stm32f4_add_flash(t, 0x8040000, 0xC0000, 0x40000, 5); target_add_commands(t, stm32f4_cmd_list, "STM32F7"); break; default: return false; } t->idcode = idcode; return true; }
/** * Reads the EFM32 Extended Unique Identifier */ uint64_t efm32_read_eui(target *t) { uint64_t eui; eui = (uint64_t)target_mem_read32(t, EFM32_DI_EUI64_1) << 32; eui |= (uint64_t)target_mem_read32(t, EFM32_DI_EUI64_0) << 0; return eui; }
static bool stm32f1_cmd_option(target *t, int argc, char *argv[]) { uint32_t addr, val; uint32_t flash_obp_rdp_key; uint32_t rdprt; switch(t->idcode) { case 0x422: /* STM32F30x */ case 0x432: /* STM32F37x */ case 0x438: /* STM32F303x6/8 and STM32F328 */ case 0x440: /* STM32F0 */ case 0x446: /* STM32F303xD/E and STM32F398xE */ flash_obp_rdp_key = FLASH_OBP_RDP_KEY_F3; break; default: flash_obp_rdp_key = FLASH_OBP_RDP_KEY; } rdprt = target_mem_read32(t, FLASH_OBR) & FLASH_OBR_RDPRT; stm32f1_flash_unlock(t); target_mem_write32(t, FLASH_OPTKEYR, KEY1); target_mem_write32(t, FLASH_OPTKEYR, KEY2); if ((argc == 2) && !strcmp(argv[1], "erase")) { stm32f1_option_erase(t); stm32f1_option_write_erased(t, FLASH_OBP_RDP, flash_obp_rdp_key); } else if (rdprt) { tc_printf(t, "Device is Read Protected\n"); tc_printf(t, "Use \"monitor option erase\" to unprotect, erasing device\n"); return true; } else if (argc == 3) { addr = strtol(argv[1], NULL, 0); val = strtol(argv[2], NULL, 0); stm32f1_option_write(t, addr, val); } else { tc_printf(t, "usage: monitor option erase\n"); tc_printf(t, "usage: monitor option <addr> <value>\n"); } if (0 && flash_obp_rdp_key == FLASH_OBP_RDP_KEY_F3) { /* Reload option bytes on F0 and F3*/ val = target_mem_read32(t, FLASH_CR); val |= FLASH_CR_OBL_LAUNCH; stm32f1_option_write(t, FLASH_CR, val); val &= ~FLASH_CR_OBL_LAUNCH; stm32f1_option_write(t, FLASH_CR, val); } for (int i = 0; i < 0xf; i += 4) { addr = 0x1ffff800 + i; val = target_mem_read32(t, addr); tc_printf(t, "0x%08X: 0x%04X\n", addr, val & 0xFFFF); tc_printf(t, "0x%08X: 0x%04X\n", addr + 2, val >> 16); } 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; }
uint32_t generic_crc32(target *t, uint32_t base, int len) { uint32_t data; uint32_t crc; size_t i; CRC_CR |= CRC_CR_RESET; while (len > 3) { data = target_mem_read32(t, base); CRC_DR = __builtin_bswap32(data); base += 4; len -= 4; } crc = CRC_DR; while (len--) { data = target_mem_read8(t, base++); crc ^= data << 24; for (i = 0; i < 8; i++) { if (crc & 0x80000000) crc = (crc << 1) ^ 0x4C11DB7; else crc <<= 1; } } return crc; }
bool stm32f4_probe(target *t) { uint32_t idcode; idcode = target_mem_read32(t, DBGMCU_IDCODE); switch(idcode & 0xFFF) { case 0x419: /* 427/437 */ /* Second bank for 2M parts. */ stm32f4_add_flash(t, 0x8100000, 0x10000, 0x4000, 12); stm32f4_add_flash(t, 0x8110000, 0x10000, 0x10000, 16); stm32f4_add_flash(t, 0x8120000, 0xE0000, 0x20000, 17); /* Fall through for stuff common to F40x/F41x */ case 0x411: /* Documented to be 0x413! This is what I read... */ case 0x413: /* F407VGT6 */ case 0x423: /* F401 B/C RM0368 Rev.3 */ case 0x431: /* F411 RM0383 Rev.4 */ case 0x433: /* F401 D/E RM0368 Rev.3 */ t->driver = stm32f4_driver_str; target_add_ram(t, 0x10000000, 0x10000); target_add_ram(t, 0x20000000, 0x30000); stm32f4_add_flash(t, 0x8000000, 0x10000, 0x4000, 0); stm32f4_add_flash(t, 0x8010000, 0x10000, 0x10000, 4); stm32f4_add_flash(t, 0x8020000, 0xE0000, 0x20000, 5); target_add_commands(t, stm32f4_cmd_list, "STM32F4"); return true; } return false; }
/* Program flash */ static int msp432_flash_write(struct target_flash *f, target_addr dest, const void *src, size_t len) { struct msp432_flash *mf = (struct msp432_flash *)f; target *t = f->t; /* Prepare RAM buffer in target */ target_mem_write(t, SRAM_WRITE_BUFFER, src, len); /* Unprotect sector, len is always < SECTOR_SIZE */ uint32_t old_prot = msp432_sector_unprotect(mf, dest); DEBUG("Flash protect: 0x%08"PRIX32"\n", target_mem_read32(t, mf->flash_protect_register)); /* Prepare input data */ uint32_t regs[t->regs_size / sizeof(uint32_t)]; // Use of VLA target_regs_read(t, regs); regs[0] = SRAM_WRITE_BUFFER; // Address of buffer to be flashed in R0 regs[1] = dest; // Flash address to be write to in R1 regs[2] = len; // Size of buffer to be flashed in R2 DEBUG("Writing 0x%04" PRIX32 " bytes at 0x%08" PRI_SIZET "\n", dest, len); /* Call ROM */ msp432_call_ROM(t, mf->FlashCtl_programMemory, regs); /* Restore original protection */ target_mem_write32(t, mf->flash_protect_register, old_prot); DEBUG("ROM return value: %"PRIu32"\n", regs[0]); // Result value in R0 is true for success return !regs[0]; }
static bool stm32f1_option_write(target *t, uint32_t addr, uint16_t value) { uint16_t opt_val[8]; int i, index; index = (addr - FLASH_OBP_RDP) / 2; if ((index < 0) || (index > 7)) return false; /* Retrieve old values */ for (i = 0; i < 16; i = i +4) { uint32_t val = target_mem_read32(t, FLASH_OBP_RDP + i); opt_val[i/2] = val & 0xffff; opt_val[i/2 +1] = val >> 16; } if (opt_val[index] == value) return true; /* Check for erased value */ if (opt_val[index] != 0xffff) if (!(stm32f1_option_erase(t))) return false; opt_val[index] = value; /* Write changed values*/ for (i = 0; i < 8; i++) if (!(stm32f1_option_write_erased (t, FLASH_OBP_RDP + i*2,opt_val[i]))) return false; return true; }
/** * 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 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 bool nrf51_cmd_read_hwid(target *t) { uint32_t hwid = target_mem_read32(t, NRF51_FICR_CONFIGID) & 0xFFFF; tc_printf(t, "Hardware ID: 0x%04X\n", hwid); return true; }
/* Erase a single sector at addr calling the ROM routine*/ static bool msp432_sector_erase(struct target_flash *f, target_addr addr) { target *t = f->t; struct msp432_flash *mf = (struct msp432_flash *)f; /* Unprotect sector */ uint32_t old_prot = msp432_sector_unprotect(mf, addr); DEBUG("Flash protect: 0x%08"PRIX32"\n", target_mem_read32(t, mf->flash_protect_register)); /* Prepare input data */ uint32_t regs[t->regs_size / sizeof(uint32_t)]; // Use of VLA target_regs_read(t, regs); regs[0] = addr; // Address of sector to erase in R0 DEBUG("Erasing sector at 0x%08"PRIX32"\n", addr); /* Call ROM */ msp432_call_ROM(t, mf->FlashCtl_eraseSector, regs); // Result value in R0 is true for success DEBUG("ROM return value: %"PRIu32"\n", regs[0]); /* Restore original protection */ target_mem_write32(t, mf->flash_protect_register, old_prot); return !regs[0]; }
static bool stm32f4_cmd_option(target *t, int argc, char *argv[]) { uint32_t start, val; int len; if (t->idcode == 0x449) { start = 0x1FFF0000; len = 0x20; } else { start = 0x1FFFC000; len = 0x10; } if ((argc == 2) && !strcmp(argv[1], "erase")) { stm32f4_option_write(t, 0x0fffaaed); } else if ((argc == 3) && !strcmp(argv[1], "write")) { val = strtoul(argv[2], NULL, 0); stm32f4_option_write(t, val); } else { gdb_out("usage: monitor option erase\n"); gdb_out("usage: monitor option write <value>\n"); } for (int i = 0; i < len; i += 8) { uint32_t addr = start + i; val = target_mem_read32(t, addr); gdb_outf("0x%08X: 0x%04X\n", addr, val & 0xFFFF); } return true; }
static void stm32f4_flash_unlock(target *t) { if (target_mem_read32(t, FLASH_CR) & FLASH_CR_LOCK) { /* Enable FPEC controller access */ target_mem_write32(t, FLASH_KEYR, KEY1); target_mem_write32(t, FLASH_KEYR, KEY2); } }
/** * 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 sam3x_cmd_gpnvm_get(target *t) { uint32_t base = sam3x_flash_base(t); sam3x_flash_cmd(t, base, EEFC_FCR_FCMD_GGPB, 0); tc_printf(t, "GPNVM: 0x%08X\n", target_mem_read32(t, EEFC_FRR(base))); return true; }
static bool stm32l4_cmd_option(target *t, int argc, char *argv[]) { uint32_t addr, val; (void) argc; (void) argv; for (int i = 0; i < 0x23; i += 8) { addr = 0x1fff7800 + i; val = target_mem_read32(t, addr); tc_printf(t, "0x%08X: 0x%08x\n", addr, val); } for (int i = 8; i < 0x23; i += 8) { addr = 0x1ffff800 + i; val = target_mem_read32(t, addr); tc_printf(t, "0x%08X: 0x%08X\n", addr, val); } 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; }
/* Protect or unprotect the sector containing address */ static inline uint32_t msp432_sector_unprotect(struct msp432_flash *mf, target_addr addr) { /* Read the old protection register */ uint32_t old_mask = target_mem_read32(mf->f.t, mf->flash_protect_register); /* Find the bit representing the sector and set it to 0 */ uint32_t sec_mask = ~(1u << ((addr - mf->f.start) / SECTOR_SIZE)); /* Clear the potection bit */ sec_mask &= old_mask; target_mem_write32(mf->f.t, mf->flash_protect_register, sec_mask); return old_mask; }
/** * Reads the SAM D20 Peripheral ID */ uint64_t samd_read_pid(target *t) { uint64_t pid = 0; uint8_t i, j; /* Five PID registers to read LSB first */ for (i = 0, j = 0; i < 5; i++, j += 8) pid |= (target_mem_read32(t, SAMD_DSU_PID(i)) & 0xFF) << j; return pid; }
/** * Reads the SAM D20 Component ID */ uint32_t samd_read_cid(target *t) { uint64_t cid = 0; uint8_t i, j; /* Four CID registers to read LSB first */ for (i = 0, j = 0; i < 4; i++, j += 8) cid |= (target_mem_read32(t, SAMD_DSU_CID(i)) & 0xFF) << j; return cid; }
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_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; }