Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: mass erase target API #1619

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/include/target.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ bool target_mem_access_needs_halt(target_s *target);
bool target_flash_erase(target_s *target, target_addr_t addr, size_t len);
bool target_flash_write(target_s *target, target_addr_t dest, const void *src, size_t len);
bool target_flash_complete(target_s *target);
bool target_flash_mass_erase(target_s *target);

/* Register access functions */
size_t target_regs_size(target_s *target);
Expand Down
10 changes: 4 additions & 6 deletions src/target/at32f43x.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ static bool at32f43_flash_prepare(target_flash_s *flash);
static bool at32f43_flash_erase(target_flash_s *flash, target_addr_t addr, size_t len);
static bool at32f43_flash_write(target_flash_s *flash, target_addr_t dest, const void *src, size_t len);
static bool at32f43_flash_done(target_flash_s *flash);
static bool at32f43_mass_erase(target_s *target);
static bool at32f43_mass_erase(target_s *target, platform_timeout_s *print_progess);

/* Flash memory controller register map */
#define AT32F43x_FLASH_REG_BASE 0x40023c00U
Expand Down Expand Up @@ -538,17 +538,15 @@ static bool at32f43_mass_erase_bank(
return at32f43_flash_busy_wait(target, bank_reg_offset, timeout);
}

static bool at32f43_mass_erase(target_s *target)
static bool at32f43_mass_erase(target_s *const target, platform_timeout_s *const print_progess)
{
/* Datasheet: bank erase takes seconds to complete */
platform_timeout_s timeout;
platform_timeout_set(&timeout, 500);
if (!at32f43_mass_erase_bank(target, AT32F43x_FLASH_BANK1_REG_OFFSET, &timeout))
if (!at32f43_mass_erase_bank(target, AT32F43x_FLASH_BANK1_REG_OFFSET, print_progess))
return false;

/* For dual-bank targets, mass erase bank 2 as well */
if (target->flash->next)
return at32f43_mass_erase_bank(target, AT32F43x_FLASH_BANK2_REG_OFFSET, &timeout);
return at32f43_mass_erase_bank(target, AT32F43x_FLASH_BANK2_REG_OFFSET, print_progess);
return true;
}

Expand Down
25 changes: 11 additions & 14 deletions src/target/efm32.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@

static bool efm32_flash_erase(target_flash_s *f, target_addr_t addr, size_t len);
static bool efm32_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len);
static bool efm32_mass_erase(target_s *t);
static bool efm32_mass_erase(target_s *t, platform_timeout_s *print_progess);

static const uint16_t efm32_flash_write_stub[] = {
#include "flashstub/efm32.stub"
Expand Down Expand Up @@ -666,7 +666,7 @@ static bool efm32_flash_write(target_flash_s *f, target_addr_t dest, const void
}

/* Uses the MSC ERASEMAIN0/1 command to erase the entire flash */
static bool efm32_mass_erase(target_s *t)
static bool efm32_mass_erase(target_s *const t, platform_timeout_s *const print_progess)
{
efm32_priv_s *priv_storage = (efm32_priv_s *)t->target_storage;
if (!priv_storage || !priv_storage->device)
Expand All @@ -691,25 +691,23 @@ static bool efm32_mass_erase(target_s *t)
/* Erase operation */
target_mem32_write32(t, EFM32_MSC_WRITECMD(msc), EFM32_MSC_WRITECMD_ERASEMAIN0);

platform_timeout_s timeout;
platform_timeout_set(&timeout, 500);
/* Poll MSC Busy */
while ((target_mem32_read32(t, EFM32_MSC_STATUS(msc)) & EFM32_MSC_STATUS_BUSY)) {
if (target_check_error(t))
return false;
target_print_progress(&timeout);
target_print_progress(print_progess);
}

/* Parts with >= 512 kiB flash have 2 mass erase regions */
if (flash_kib >= 512) {
if (flash_kib >= 512U) {
/* Erase operation */
target_mem32_write32(t, EFM32_MSC_WRITECMD(msc), EFM32_MSC_WRITECMD_ERASEMAIN1);

/* Poll MSC Busy */
while ((target_mem32_read32(t, EFM32_MSC_STATUS(msc)) & EFM32_MSC_STATUS_BUSY)) {
if (target_check_error(t))
return false;
target_print_progress(&timeout);
target_print_progress(print_progess);
}
}

Expand Down Expand Up @@ -926,7 +924,7 @@ static bool efm32_cmd_bootloader(target_s *t, int argc, const char **argv)

#define CMDKEY 0xcfacc118U

static bool efm32_aap_mass_erase(target_s *t);
static bool efm32_aap_mass_erase(target_s *t, platform_timeout_s *print_progess);

/* AAP Probe */
typedef struct efm32_aap_priv {
Expand All @@ -950,6 +948,7 @@ bool efm32_aap_probe(adiv5_access_port_s *ap)
return false;
}

t->enter_flash_mode = target_enter_flash_mode_stub;
t->mass_erase = efm32_aap_mass_erase;

adiv5_ap_ref(ap);
Expand All @@ -968,9 +967,9 @@ bool efm32_aap_probe(adiv5_access_port_s *ap)
return true;
}

static bool efm32_aap_mass_erase(target_s *t)
static bool efm32_aap_mass_erase(target_s *const t, platform_timeout_s *const print_progess)
{
adiv5_access_port_s *ap = t->priv;
adiv5_access_port_s *ap = cortex_ap(t);
uint32_t status;

/* Read status */
Expand All @@ -985,14 +984,12 @@ static bool efm32_aap_mass_erase(target_s *t)

DEBUG_INFO("EFM32: Issuing DEVICEERASE...\n");
adiv5_ap_write(ap, AAP_CMDKEY, CMDKEY);
adiv5_ap_write(ap, AAP_CMD, 1);
adiv5_ap_write(ap, AAP_CMD, 1U);

platform_timeout_s timeout;
platform_timeout_set(&timeout, 500);
/* Read until 0, probably should have a timeout here... */
do {
status = adiv5_ap_read(ap, AAP_STATUS);
target_print_progress(&timeout);
target_print_progress(print_progess);
} while (status & AAP_STATUS_ERASEBUSY);

/* Read status */
Expand Down
42 changes: 21 additions & 21 deletions src/target/hc32l110.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ static bool hc32l110_flash_prepare(target_flash_s *flash);
static bool hc32l110_flash_done(target_flash_s *flash);
static bool hc32l110_flash_erase(target_flash_s *flash, target_addr_t addr, size_t length);
static bool hc32l110_flash_write(target_flash_s *flash, target_addr_t dest, const void *src, size_t length);
static bool hc32l110_mass_erase(target_s *target);
static bool hc32l110_mass_erase(target_s *target, platform_timeout_s *print_progess);

static void hc32l110_add_flash(target_s *target, const uint32_t flash_size)
{
Expand Down Expand Up @@ -130,7 +130,8 @@ static void hc32l110_flash_cr_unlock(target_s *const target)
target_mem32_write32(target, HC32L110_FLASH_BYPASS, 0xa5a5U);
}

static bool hc32l110_check_flash_completion(target_s *const target, const uint32_t timeout_ms)
static bool hc32l110_check_flash_completion(
target_s *const target, const uint32_t timeout_ms, platform_timeout_s *const print_progess)
{
platform_timeout_s timeout;
platform_timeout_set(&timeout, timeout_ms);
Expand All @@ -139,6 +140,8 @@ static bool hc32l110_check_flash_completion(target_s *const target, const uint32
status = target_mem32_read32(target, HC32L110_FLASH_CR);
if (target_check_error(target) || platform_timeout_is_expired(&timeout))
return false;
if (print_progess)
target_print_progress(print_progess);
}
return true;
}
Expand Down Expand Up @@ -174,18 +177,26 @@ static bool hc32l110_flash_prepare(target_flash_s *const flash)
{
hc32l110_flash_cr_unlock(flash->t);

uint32_t cr_operation = 0;
switch (flash->operation) {
case FLASH_OPERATION_WRITE:
target_mem32_write32(flash->t, HC32L110_FLASH_CR, HC32L110_FLASH_CR_OP_PROGRAM);
cr_operation = HC32L110_FLASH_CR_OP_PROGRAM;
break;
case FLASH_OPERATION_ERASE:
target_mem32_write32(flash->t, HC32L110_FLASH_CR, HC32L110_FLASH_CR_OP_ERASE_SECTOR);
cr_operation = HC32L110_FLASH_CR_OP_ERASE_SECTOR;
break;
case FLASH_OPERATION_MASS_ERASE:
cr_operation = HC32L110_FLASH_CR_OP_ERASE_CHIP;
break;
default:
DEBUG_WARN("unsupported operation %u", flash->operation);
return false;
}

target_mem32_write32(flash->t, HC32L110_FLASH_CR, cr_operation);
if (!hc32l110_check_flash_completion(flash->t, 500U, NULL))
return false;

hc32l110_slock_unlock_all(flash->t);
return true;
}
Expand All @@ -201,32 +212,21 @@ static bool hc32l110_flash_erase(target_flash_s *const flash, const target_addr_
(void)length;
/* The Flash controller automatically erases the whole sector after one write operation */
target_mem32_write32(flash->t, addr, 0);
return hc32l110_check_flash_completion(flash->t, 1000);
return hc32l110_check_flash_completion(flash->t, 1000, NULL);
}

static bool hc32l110_flash_write(
target_flash_s *const flash, const target_addr_t dest, const void *const src, const size_t length)
{
(void)length;
target_mem32_write32(flash->t, dest, *(const uint32_t *)src);
return hc32l110_check_flash_completion(flash->t, 1000);
return hc32l110_check_flash_completion(flash->t, 1000, NULL);
}

static bool hc32l110_mass_erase(target_s *target)
/* FIXME: looks like this might make sense as a flash->mass erase routine */
static bool hc32l110_mass_erase(target_s *const target, platform_timeout_s *const print_progess)
{
hc32l110_enter_flash_mode(target);

hc32l110_flash_cr_unlock(target);
target_mem32_write32(target, HC32L110_FLASH_CR, HC32L110_FLASH_CR_OP_ERASE_CHIP);
if (!hc32l110_check_flash_completion(target, 500))
return false;

hc32l110_slock_unlock_all(target);

// The Flash controller automatically erases the whole Flash after one write operation
target_mem32_write32(target, 0, 0);
const bool result = hc32l110_check_flash_completion(target, 4000);

hc32l110_slock_lock_all(target);
return result;
target_mem32_write32(target, 0x0U, 0U);
return hc32l110_check_flash_completion(target, 4000U, print_progess);
}
1 change: 0 additions & 1 deletion src/target/imxrt.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,6 @@ bool imxrt_probe(target_s *const target)
spi_flash_id_s flash_id;
imxrt_spi_read(target, SPI_FLASH_CMD_READ_JEDEC_ID, 0, &flash_id, sizeof(flash_id));

target->mass_erase = bmp_spi_mass_erase;
target->enter_flash_mode = imxrt_enter_flash_mode;
target->exit_flash_mode = imxrt_exit_flash_mode;

Expand Down
13 changes: 6 additions & 7 deletions src/target/kinetis.c
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ static bool kinetis_flash_done(target_flash_s *const f)
* device. This provides a fake target to allow a monitor command interface
*/

static bool kinetis_mdm_mass_erase(target_s *t);
static bool kinetis_mdm_mass_erase(target_s *t, platform_timeout_s *const print_progess);
static bool kinetis_mdm_cmd_ke04_mode(target_s *t, int argc, const char **argv);

const command_s kinetis_mdm_cmd_list[] = {
Expand Down Expand Up @@ -569,6 +569,7 @@ bool kinetis_mdm_probe(adiv5_access_port_s *ap)
return false;
}

t->enter_flash_mode = target_enter_flash_mode_stub;
t->mass_erase = kinetis_mdm_mass_erase;
adiv5_ap_ref(ap);
t->priv = ap;
Expand All @@ -593,13 +594,13 @@ static bool kinetis_mdm_cmd_ke04_mode(target_s *t, int argc, const char **argv)
return true;
}

static bool kinetis_mdm_mass_erase(target_s *t)
static bool kinetis_mdm_mass_erase(target_s *const t, platform_timeout_s *const print_progess)
{
adiv5_access_port_s *ap = t->priv;

/* Keep the MCU in reset as stated in KL25PxxM48SF0RM */
if (t->ke04_mode)
adiv5_ap_write(ap, MDM_CONTROL, MDM_CONTROL_SYS_RESET);
adiv5_ap_write(ap, MDM_CONTROL, MDM_CONTROL_SYS_RESET); /* FIXME: move this to enter_flash_mode? */

uint32_t status = adiv5_ap_read(ap, MDM_STATUS);
uint32_t control = adiv5_ap_read(ap, MDM_CONTROL);
Expand All @@ -625,18 +626,16 @@ static bool kinetis_mdm_mass_erase(target_s *t)
}

adiv5_ap_write(ap, MDM_CONTROL, MDM_CONTROL_MASS_ERASE);
platform_timeout_s timeout;
platform_timeout_set(&timeout, 500);

do {
status = adiv5_ap_read(ap, MDM_STATUS);
target_print_progress(&timeout);
target_print_progress(print_progess);
} while (!(status & MDM_STATUS_MASS_ERASE_ACK));
tc_printf(t, "Mass erase acknowledged\n");

do {
control = adiv5_ap_read(ap, MDM_CONTROL);
target_print_progress(&timeout);
target_print_progress(print_progess);
} while (!(control & MDM_CONTROL_MASS_ERASE));
tc_printf(t, "Mass erase complete\n");

Expand Down
8 changes: 0 additions & 8 deletions src/target/lmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@

static bool lmi_flash_erase(target_flash_s *flash, target_addr_t addr, size_t len);
static bool lmi_flash_write(target_flash_s *flash, target_addr_t dest, const void *src, size_t len);
static bool lmi_mass_erase(target_s *target);

static const uint16_t lmi_flash_write_stub[] = {
#include "flashstub/lmi.stub"
Expand Down Expand Up @@ -141,7 +140,6 @@ bool lm3s_probe(target_s *const target, const uint16_t did1)
return false;
}
target->driver = "Stellaris";
target->mass_erase = lmi_mass_erase;
return true;
}

Expand Down Expand Up @@ -177,7 +175,6 @@ bool tm4c_probe(target_s *const target, const uint16_t did1)
return false;
}
target->driver = "Tiva-C";
target->mass_erase = lmi_mass_erase;
cortex_ap(target)->dp->quirks |= ADIV5_DP_QUIRK_DUPED_AP;
return true;
}
Expand Down Expand Up @@ -236,8 +233,3 @@ static bool lmi_flash_write(target_flash_s *flash, target_addr_t dest, const voi

return cortexm_run_stub(target, SRAM_BASE, dest, STUB_BUFFER_BASE, len, 0) == 0;
}

static bool lmi_mass_erase(target_s *target)
{
return lmi_flash_erase(target->flash, target->flash->start, target->flash->length);
}
Loading
Loading