Add LPC command to read out unique ID from target.

This commit modifies lpc_iap_call() to work with IAP commands that
return additional data. If the "result" argument is non-null, 16
bytes of data (the maximum returned by any IAP command) are copied
to the specified address.
This commit is contained in:
David Lawrence 2017-04-12 11:15:50 -04:00
parent 21434d6fbb
commit d3979a57b6
5 changed files with 65 additions and 14 deletions

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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, &param, 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;

View File

@ -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);