diff --git a/src/target/lpc11xx.c b/src/target/lpc11xx.c index 30143ba..47226ca 100644 --- a/src/target/lpc11xx.c +++ b/src/target/lpc11xx.c @@ -35,6 +35,26 @@ #define LPC11XX_DEVICE_ID 0x400483F4 #define LPC8XX_DEVICE_ID 0x400483F8 +static bool lpc11xx_read_uid(target *t, int argc, const char *argv[]) +{ + (void)argc; + (void)argv; + struct lpc_flash *f = (struct lpc_flash *)t->flash; + uint8_t uid[16]; + if (lpc_iap_call(f, uid, IAP_CMD_READUID)) + return false; + tc_printf(t, "UID: 0x"); + for (uint32_t i = 0; i < sizeof(uid); ++i) + tc_printf(t, "%02x", uid[i]); + tc_printf(t, "\n"); + return true; +} + +const struct command_s lpc11xx_cmd_list[] = { + {"readuid", lpc11xx_read_uid, "Read out the 16-byte UID."}, + {NULL, NULL, NULL} +}; + void lpc11xx_add_flash(target *t, uint32_t addr, size_t len, size_t erasesize) { struct lpc_flash *lf = lpc_add_flash(t, addr, len); @@ -89,6 +109,7 @@ lpc11xx_probe(target *t) t->driver = "LPC11xx"; target_add_ram(t, 0x10000000, 0x2000); lpc11xx_add_flash(t, 0x00000000, 0x20000, 0x1000); + target_add_commands(t, lpc11xx_cmd_list, "LPC11xx"); return true; case 0x0A24902B: @@ -109,6 +130,7 @@ lpc11xx_probe(target *t) t->driver = "LPC81x"; target_add_ram(t, 0x10000000, 0x1000); lpc11xx_add_flash(t, 0x00000000, 0x4000, 0x400); + target_add_commands(t, lpc11xx_cmd_list, "LPC81x"); return true; case 0x00008221: /* LPC822M101JHI33 */ case 0x00008222: /* LPC822M101JDH20 */ @@ -117,6 +139,7 @@ lpc11xx_probe(target *t) t->driver = "LPC82x"; target_add_ram(t, 0x10000000, 0x2000); lpc11xx_add_flash(t, 0x00000000, 0x8000, 0x400); + target_add_commands(t, lpc11xx_cmd_list, "LPC82x"); return true; case 0x0003D440: /* LPC11U34/311 */ case 0x0001cc40: /* LPC11U34/421 */ diff --git a/src/target/lpc15xx.c b/src/target/lpc15xx.c index 7b86d42..6607409 100644 --- a/src/target/lpc15xx.c +++ b/src/target/lpc15xx.c @@ -35,6 +35,26 @@ #define LPC15XX_DEVICE_ID 0x400743F8 +static bool lpc15xx_read_uid(target *t, int argc, const char *argv[]) +{ + (void)argc; + (void)argv; + struct lpc_flash *f = (struct lpc_flash *)t->flash; + uint8_t uid[16]; + if (lpc_iap_call(f, uid, IAP_CMD_READUID)) + return false; + tc_printf(t, "UID: 0x"); + for (uint32_t i = 0; i < sizeof(uid); ++i) + tc_printf(t, "%02x", uid[i]); + tc_printf(t, "\n"); + return true; +} + +const struct command_s lpc15xx_cmd_list[] = { + {"readuid", lpc15xx_read_uid, "Read out the 16-byte UID."}, + {NULL, NULL, NULL} +}; + void lpc15xx_add_flash(target *t, uint32_t addr, size_t len, size_t erasesize) { struct lpc_flash *lf = lpc_add_flash(t, addr, len); @@ -72,6 +92,7 @@ lpc15xx_probe(target *t) t->driver = "LPC15xx"; target_add_ram(t, 0x02000000, ram_size); lpc15xx_add_flash(t, 0x00000000, 0x40000, 0x1000); + target_add_commands(t, lpc15xx_cmd_list, "LPC15xx"); return true; } diff --git a/src/target/lpc43xx.c b/src/target/lpc43xx.c index f08c4f8..a1fb214 100644 --- a/src/target/lpc43xx.c +++ b/src/target/lpc43xx.c @@ -164,11 +164,11 @@ static bool lpc43xx_cmd_erase(target *t, int argc, const char *argv[]) for (int bank = 0; bank < FLASH_NUM_BANK; bank++) { struct lpc_flash *f = (struct lpc_flash *)t->flash; - if (lpc_iap_call(f, IAP_CMD_PREPARE, + if (lpc_iap_call(f, NULL, IAP_CMD_PREPARE, 0, FLASH_NUM_SECTOR-1, bank)) return false; - if (lpc_iap_call(f, IAP_CMD_ERASE, + if (lpc_iap_call(f, NULL, IAP_CMD_ERASE, 0, FLASH_NUM_SECTOR-1, CPU_CLK_KHZ, bank)) return false; } @@ -188,7 +188,7 @@ static int lpc43xx_flash_init(target *t) /* Initialize flash IAP */ struct lpc_flash *f = (struct lpc_flash *)t->flash; - if (lpc_iap_call(f, IAP_CMD_INIT)) + if (lpc_iap_call(f, NULL, IAP_CMD_INIT)) return -1; return 0; @@ -234,7 +234,7 @@ static bool lpc43xx_cmd_mkboot(target *t, int argc, const char *argv[]) /* special command to compute/write magic vector for signature */ struct lpc_flash *f = (struct lpc_flash *)t->flash; - if (lpc_iap_call(f, IAP_CMD_SET_ACTIVE_BANK, bank, CPU_CLK_KHZ)) { + if (lpc_iap_call(f, NULL, IAP_CMD_SET_ACTIVE_BANK, bank, CPU_CLK_KHZ)) { tc_printf(t, "Set bootable failed.\n"); return false; } diff --git a/src/target/lpc_common.c b/src/target/lpc_common.c index fa486ef..c733138 100644 --- a/src/target/lpc_common.c +++ b/src/target/lpc_common.c @@ -29,7 +29,8 @@ struct flash_param { uint16_t pad0; uint32_t command; uint32_t words[4]; - uint32_t result; + uint32_t status; + uint32_t result[4]; } __attribute__((aligned(4))); @@ -53,7 +54,7 @@ struct lpc_flash *lpc_add_flash(target *t, target_addr addr, size_t length) return lf; } -enum iap_status lpc_iap_call(struct lpc_flash *f, enum iap_cmd cmd, ...) +enum iap_status lpc_iap_call(struct lpc_flash *f, void *result, enum iap_cmd cmd, ...) { target *t = f->f.t; struct flash_param param = { @@ -79,7 +80,7 @@ enum iap_status lpc_iap_call(struct lpc_flash *f, enum iap_cmd cmd, ...) uint32_t regs[t->regs_size / sizeof(uint32_t)]; target_regs_read(t, regs); regs[0] = f->iap_ram + offsetof(struct flash_param, command); - regs[1] = f->iap_ram + offsetof(struct flash_param, result); + regs[1] = f->iap_ram + offsetof(struct flash_param, status); regs[REG_MSP] = f->iap_msp; regs[REG_LR] = f->iap_ram | 1; regs[REG_PC] = f->iap_entry; @@ -91,7 +92,12 @@ enum iap_status lpc_iap_call(struct lpc_flash *f, enum iap_cmd cmd, ...) /* copy back just the parameters structure */ target_mem_read(t, ¶m, f->iap_ram, sizeof(param)); - return param.result; + + /* if the user expected a result, set the result (16 bytes). */ + if (result != NULL) + memcpy(result, param.result, sizeof(param.result)); + + return param.status; } static uint8_t lpc_sector_for_addr(struct lpc_flash *f, uint32_t addr) @@ -105,15 +111,15 @@ int lpc_flash_erase(struct target_flash *tf, target_addr addr, size_t len) uint32_t start = lpc_sector_for_addr(f, addr); uint32_t end = lpc_sector_for_addr(f, addr + len - 1); - if (lpc_iap_call(f, IAP_CMD_PREPARE, start, end, f->bank)) + if (lpc_iap_call(f, NULL, IAP_CMD_PREPARE, start, end, f->bank)) return -1; /* and now erase them */ - if (lpc_iap_call(f, IAP_CMD_ERASE, start, end, CPU_CLK_KHZ, f->bank)) + if (lpc_iap_call(f, NULL, IAP_CMD_ERASE, start, end, CPU_CLK_KHZ, f->bank)) return -2; /* check erase ok */ - if (lpc_iap_call(f, IAP_CMD_BLANKCHECK, start, end, f->bank)) + if (lpc_iap_call(f, NULL, IAP_CMD_BLANKCHECK, start, end, f->bank)) return -3; return 0; @@ -125,7 +131,7 @@ int lpc_flash_write(struct target_flash *tf, struct lpc_flash *f = (struct lpc_flash *)tf; /* prepare... */ uint32_t sector = lpc_sector_for_addr(f, dest); - if (lpc_iap_call(f, IAP_CMD_PREPARE, sector, sector, f->bank)) + if (lpc_iap_call(f, NULL, IAP_CMD_PREPARE, sector, sector, f->bank)) return -1; /* Write payload to target ram */ @@ -133,7 +139,7 @@ int lpc_flash_write(struct target_flash *tf, target_mem_write(f->f.t, bufaddr, src, len); /* set the destination address and program */ - if (lpc_iap_call(f, IAP_CMD_PROGRAM, dest, bufaddr, len, CPU_CLK_KHZ)) + if (lpc_iap_call(f, NULL, IAP_CMD_PROGRAM, dest, bufaddr, len, CPU_CLK_KHZ)) return -2; return 0; diff --git a/src/target/lpc_common.h b/src/target/lpc_common.h index 5b13226..3130e96 100644 --- a/src/target/lpc_common.h +++ b/src/target/lpc_common.h @@ -27,6 +27,7 @@ enum iap_cmd { IAP_CMD_ERASE = 52, IAP_CMD_BLANKCHECK = 53, IAP_CMD_PARTID = 54, + IAP_CMD_READUID = 58, IAP_CMD_SET_ACTIVE_BANK = 60, }; @@ -60,7 +61,7 @@ struct lpc_flash { }; struct lpc_flash *lpc_add_flash(target *t, target_addr addr, size_t length); -enum iap_status lpc_iap_call(struct lpc_flash *f, enum iap_cmd cmd, ...); +enum iap_status lpc_iap_call(struct lpc_flash *f, void *result, enum iap_cmd cmd, ...); int lpc_flash_erase(struct target_flash *f, target_addr addr, size_t len); int lpc_flash_write(struct target_flash *f, target_addr dest, const void *src, size_t len);