Merge pull request #203 from dlaw/master
Add LPC11xx command to read out unique ID from target. Restore Ram and registers after call.
This commit is contained in:
commit
f89542c79f
|
@ -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:
|
||||
|
@ -117,6 +138,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 */
|
||||
|
@ -125,6 +147,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 0x00008441:
|
||||
case 0x00008442:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 = {
|
||||
|
@ -65,6 +66,14 @@ enum iap_status lpc_iap_call(struct lpc_flash *f, enum iap_cmd cmd, ...)
|
|||
if (f->wdt_kick)
|
||||
f->wdt_kick(t);
|
||||
|
||||
/* save IAP RAM to restore after IAP call */
|
||||
struct flash_param backup_param;
|
||||
target_mem_read(t, &backup_param, f->iap_ram, sizeof(backup_param));
|
||||
|
||||
/* save registers to restore after IAP call */
|
||||
uint32_t backup_regs[t->regs_size / sizeof(uint32_t)];
|
||||
target_regs_read(t, backup_regs);
|
||||
|
||||
/* fill out the remainder of the parameters */
|
||||
va_list ap;
|
||||
va_start(ap, cmd);
|
||||
|
@ -79,7 +88,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 +100,16 @@ 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;
|
||||
|
||||
/* restore the original data in RAM and registers */
|
||||
target_mem_write(t, f->iap_ram, &backup_param, sizeof(param));
|
||||
target_regs_write(t, backup_regs);
|
||||
|
||||
/* 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 +123,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 +143,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 +151,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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue