From 29c7846612f90acb7ced1f6a1d49d9062609ec2b Mon Sep 17 00:00:00 2001 From: Allen Ibara Date: Fri, 10 Jan 2014 10:26:45 -0800 Subject: [PATCH 1/7] LPC43XX: Make sure to align target struct to word alignment --- src/lpc43xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lpc43xx.c b/src/lpc43xx.c index 0a8745d..1a437e3 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -106,7 +106,7 @@ struct flash_param { } make_active; } params; uint32_t result[5]; /* result data */ -}; +} __attribute__((aligned(4))); struct flash_program { struct flash_param p; From 813622b1b6146371a3a9ff50bc62727ecd1f6b26 Mon Sep 17 00:00:00 2001 From: Allen Ibara Date: Fri, 10 Jan 2014 10:48:59 -0800 Subject: [PATCH 2/7] LPC43XX: Add mkboot target command; dont make banks bootable by default. This used to be done transparently in the write step, however that breaks the 'verify' command. This is also more flexible for cases where you want to write a flash bank without ever intending it to be bootable. --- src/lpc43xx.c | 65 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 14 deletions(-) diff --git a/src/lpc43xx.c b/src/lpc43xx.c index 1a437e3..49f8068 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -114,6 +114,7 @@ struct flash_program { }; static bool lpc43xx_cmd_erase(target *t); +static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[]); static int lpc43xx_flash_init(struct target_s *target); static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len); static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len); @@ -122,6 +123,7 @@ static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uin const struct command_s lpc43xx_cmd_list[] = { {"erase_mass", (cmd_handler)lpc43xx_cmd_erase, "Erase entire flash memory"}, + {"mkboot", lpc43xx_cmd_mkboot, "Make flash bank bootable"}, {NULL, NULL, NULL} }; @@ -467,21 +469,56 @@ static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uin if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { return -1; } - - /* special command to compute/write magic vector for signature */ - if (chunk == first_chunk) - { - flash_pgm.p.command = IAP_CMD_SET_ACTIVE_BANK; - flash_pgm.p.params.make_active.flash_bank = flash_bank(dest); - flash_pgm.p.params.make_active.cpu_clk_khz = CPU_CLK_KHZ; - flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; - lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm)); - if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { - return -1; - } - } - } return 0; } + +/* + * Call Boot ROM code to make a flash bank bootable by computing and writing the + * correct signature into the exception table near the start of the bank. + * + * This is done indepently of writing to give the user a chance to verify flash + * before changing it. + */ +static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[]) +{ + /* Usage: mkboot 0 or mkboot 1 */ + if (argc == 2) + { + const long int bank = strtol(argv[1], NULL, 0); + + if (bank == 0 || bank == 1) + { + lpc43xx_flash_init(target); + struct flash_program flash_pgm; + + /* special command to compute/write magic vector for signature */ + flash_pgm.p.command = IAP_CMD_SET_ACTIVE_BANK; + flash_pgm.p.params.make_active.flash_bank = bank; + flash_pgm.p.params.make_active.cpu_clk_khz = CPU_CLK_KHZ; + flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; + lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm)); + if (flash_pgm.p.result[0] == IAP_STATUS_CMD_SUCCESS) { + gdb_outf("Set bootable OK.\n"); + return true; + } + else + { + gdb_outf("Set bootable failed.\n"); + } + } + else + { + gdb_outf("Unexpected bank number, should be 0 or 1.\n"); + } + } + else + { + gdb_outf("Expected bank argument 0 or 1.\n"); + } + + + return false; +} + From 911af3b8363247d132abb9a11559104b0402ae56 Mon Sep 17 00:00:00 2001 From: Allen Ibara Date: Fri, 10 Jan 2014 10:54:56 -0800 Subject: [PATCH 3/7] LPC43XX: Add reset command to do a system reset (but not the debug). --- src/lpc43xx.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/lpc43xx.c b/src/lpc43xx.c index 49f8068..a578e67 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -114,6 +114,7 @@ struct flash_program { }; static bool lpc43xx_cmd_erase(target *t); +static bool lpc43xx_cmd_reset(target *target, int argc, const char *argv[]); static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[]); static int lpc43xx_flash_init(struct target_s *target); static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len); @@ -123,6 +124,7 @@ static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uin const struct command_s lpc43xx_cmd_list[] = { {"erase_mass", (cmd_handler)lpc43xx_cmd_erase, "Erase entire flash memory"}, + {"reset", lpc43xx_cmd_reset, "Reset target"}, {"mkboot", lpc43xx_cmd_mkboot, "Make flash bank bootable"}, {NULL, NULL, NULL} }; @@ -198,6 +200,20 @@ bool lpc43xx_probe(struct target_s *target) return false; } +/* Reset all major systems _except_ debug */ +static bool lpc43xx_cmd_reset(target *target, int __attribute__((unused)) argc, const char __attribute__((unused)) *argv[]) +{ + /* Cortex-M4 Application Interrupt and Reset Control Register */ + static const uint32_t AIRCR = 0xE000ED0C; + /* Magic value key */ + static const uint32_t reset_val = 0x05FA0004; + + /* System reset on target */ + target_mem_write_words(target, AIRCR, &reset_val, sizeof(reset_val)); + + return true; +} + static bool lpc43xx_cmd_erase(target *target) { uint32_t bank = 0; From df9c19f071b970b1a33c5ce1a99de706433e1113 Mon Sep 17 00:00:00 2001 From: Allen Ibara Date: Fri, 10 Jan 2014 10:56:19 -0800 Subject: [PATCH 4/7] LPC43XX: Remove type cast for erase function --- src/lpc43xx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lpc43xx.c b/src/lpc43xx.c index a578e67..758c2f1 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -113,7 +113,7 @@ struct flash_program { uint8_t data[IAP_PGM_CHUNKSIZE]; }; -static bool lpc43xx_cmd_erase(target *t); +static bool lpc43xx_cmd_erase(target *target, int argc, const char *argv[]); static bool lpc43xx_cmd_reset(target *target, int argc, const char *argv[]); static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[]); static int lpc43xx_flash_init(struct target_s *target); @@ -123,7 +123,7 @@ static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, int len); static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len); const struct command_s lpc43xx_cmd_list[] = { - {"erase_mass", (cmd_handler)lpc43xx_cmd_erase, "Erase entire flash memory"}, + {"erase_mass", lpc43xx_cmd_erase, "Erase entire flash memory"}, {"reset", lpc43xx_cmd_reset, "Reset target"}, {"mkboot", lpc43xx_cmd_mkboot, "Make flash bank bootable"}, {NULL, NULL, NULL} @@ -214,7 +214,7 @@ static bool lpc43xx_cmd_reset(target *target, int __attribute__((unused)) argc, return true; } -static bool lpc43xx_cmd_erase(target *target) +static bool lpc43xx_cmd_erase(target *target, int __attribute__((unused)) argc, const char __attribute__((unused)) *argv[]) { uint32_t bank = 0; struct flash_program flash_pgm; From 487252150fbeb9c0265ad7e9a6aa4057e09b4246 Mon Sep 17 00:00:00 2001 From: Allen Ibara Date: Fri, 10 Jan 2014 10:59:44 -0800 Subject: [PATCH 5/7] LPC: Cleanup regs_size (in bytes). Also use sizeof() to make it clear why we multiple and divide by 4. --- src/arm7tdmi.c | 2 +- src/lpc11xx.c | 2 +- src/lpc43xx.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/arm7tdmi.c b/src/arm7tdmi.c index ad38ab3..26c5233 100644 --- a/src/arm7tdmi.c +++ b/src/arm7tdmi.c @@ -131,7 +131,7 @@ void arm7tdmi_jtag_handler(jtag_dev_t *dev) t->mem_write_words = (void *)do_nothing; t->mem_read_bytes = (void *)do_nothing; t->mem_write_bytes = (void *)do_nothing; - t->regs_size = 16 * 4; + t->regs_size = 16 * sizeof(uint32_t); t->regs_read = (void *)arm7_regs_read; t->regs_write = (void *)arm7_regs_write; t->pc_write = (void *)do_nothing; diff --git a/src/lpc11xx.c b/src/lpc11xx.c index 9adbe2b..01afd87 100644 --- a/src/lpc11xx.c +++ b/src/lpc11xx.c @@ -116,7 +116,7 @@ lpc11xx_probe(struct target_s *target) static void lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len) { - uint32_t regs[target->regs_size / 4]; + uint32_t regs[target->regs_size / sizeof(uint32_t)]; /* fill out the remainder of the parameters and copy the structure to RAM */ param->opcodes[0] = 0xbe00; diff --git a/src/lpc43xx.c b/src/lpc43xx.c index 758c2f1..fbd3941 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -331,7 +331,7 @@ static int32_t sector_number(uint32_t addr) static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len) { - uint32_t regs[target->regs_size / 4]; + uint32_t regs[target->regs_size / sizeof(uint32_t)]; uint32_t iap_entry; target_mem_read_words(target, &iap_entry, IAP_ENTRYPOINT_LOCATION, sizeof(iap_entry)); From 2b798fa8fc7b06de6053f09ad4394ee1454a5d82 Mon Sep 17 00:00:00 2001 From: Allen Ibara Date: Fri, 10 Jan 2014 11:10:57 -0800 Subject: [PATCH 6/7] LPC43XX: Make the chunk_offset logic more explicit. --- src/lpc43xx.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/lpc43xx.c b/src/lpc43xx.c index fbd3941..6954404 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -431,12 +431,20 @@ static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uin { unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE; unsigned last_chunk = (dest + len - 1) / IAP_PGM_CHUNKSIZE; - unsigned chunk_offset = dest % IAP_PGM_CHUNKSIZE; + unsigned chunk_offset; unsigned chunk; struct flash_program flash_pgm; for (chunk = first_chunk; chunk <= last_chunk; chunk++) { + if (chunk == first_chunk) + { + chunk_offset = dest % IAP_PGM_CHUNKSIZE; + } + else + { + chunk_offset = 0; + } /* first and last chunk may require special handling */ if ((chunk == first_chunk) || (chunk == last_chunk)) { @@ -454,7 +462,6 @@ static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uin /* update to suit */ len -= copylen; src += copylen; - chunk_offset = 0; } else { /* interior chunk, must be aligned and full-sized */ From 01244fc84dca3d63483a292945a8a1a28098d4d7 Mon Sep 17 00:00:00 2001 From: Allen Ibara Date: Fri, 10 Jan 2014 11:53:46 -0800 Subject: [PATCH 7/7] LPC43XX: Force target to use internal clock. Without this, flash write timing might be incorrect. --- src/lpc43xx.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/lpc43xx.c b/src/lpc43xx.c index 6954404..b3a48a9 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -121,6 +121,7 @@ static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len); static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, int len); static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len); +static void lpc43xx_set_internal_clock(struct target_s *target); const struct command_s lpc43xx_cmd_list[] = { {"erase_mass", lpc43xx_cmd_erase, "Erase entire flash memory"}, @@ -255,6 +256,9 @@ static int lpc43xx_flash_init(struct target_s *target) { struct flash_program flash_pgm; + /* Force internal clock */ + lpc43xx_set_internal_clock(target); + /* Initialize flash IAP */ flash_pgm.p.command = IAP_CMD_INIT; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; @@ -427,6 +431,12 @@ lpc43xx_flash_erase(struct target_s *target, uint32_t addr, int len) return 0; } +static void lpc43xx_set_internal_clock(struct target_s *target) +{ + const uint32_t val2 = (1 << 11) | (1 << 24); + target_mem_write_words(target, 0x40050000 + 0x06C, &val2, sizeof(val2)); +} + static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len) { unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE;