diff --git a/src/target/lpc546xx.c b/src/target/lpc546xx.c index 3b395d4..5a7e896 100644 --- a/src/target/lpc546xx.c +++ b/src/target/lpc546xx.c @@ -40,6 +40,11 @@ #define LPC546XX_WDT_PERIOD_MAX 0xFFFFFF #define LPC546XX_WDT_PROTECT (1 << 4) +#define LPC546XX_MAINCLKSELA 0x40000280 +#define LPC546XX_MAINCLKSELB 0x40000284 +#define LPC546XX_AHBCLKDIV 0x40000380 +#define LPC546XX_FLASHCFG 0x40000400 + #define IAP_RAM_SIZE LPC546XX_ETBAHB_SRAM_SIZE #define IAP_RAM_BASE LPC546XX_ETBAHB_SRAM_BASE @@ -280,13 +285,19 @@ static int lpc546xx_flash_init(target *t) { /* Reset the chip. It's unfortunate but we need to make sure the ROM bootloader is no longer mapped to 0x0 or flash blank check won't work after - erasing that sector. Resetting will also set the main clock back to default - 12MHZ FRO; that value is required for some IAP routines. */ + erasing that sector. Additionally, the ROM itself may increase the + main clock frequency during its own operation, so we need to force + it back to the 12MHz FRO to guarantee correct flash timing for + the IAP API */ lpc546xx_reset_attach(t); /* Deal with WDT */ lpc546xx_wdt_set_period(t); + target_mem_write32(t, LPC546XX_MAINCLKSELA, 0); // 12MHz FRO + target_mem_write32(t, LPC546XX_MAINCLKSELB, 0); // use MAINCLKSELA + target_mem_write32(t, LPC546XX_AHBCLKDIV, 0); // Divide by 1 + target_mem_write32(t, LPC546XX_FLASHCFG, 0x1a); // recommended default return 0; } diff --git a/src/target/lpc_common.c b/src/target/lpc_common.c index fac7bf9..f348672 100644 --- a/src/target/lpc_common.c +++ b/src/target/lpc_common.c @@ -110,6 +110,7 @@ enum iap_status lpc_iap_call(struct lpc_flash *f, void *result, enum iap_cmd cmd struct flash_param param = { .opcode = ARM_THUMB_BREAKPOINT, .command = cmd, + .status = 0xdeadbeef, // to help us see if the IAP didn't execute }; /* Pet WDT before each IAP call, if it is on */