From 4addec0a21513753008494c24f6fcc5b82d2c88b Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Thu, 9 Jun 2016 18:20:07 -0400 Subject: [PATCH] lpc15xx support --- src/Makefile | 1 + src/cortexm.c | 1 + src/include/target.h | 1 + src/lpc15xx.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+) create mode 100644 src/lpc15xx.c diff --git a/src/Makefile b/src/Makefile index 6d9a990..f43ffff 100644 --- a/src/Makefile +++ b/src/Makefile @@ -37,6 +37,7 @@ SRC = \ lmi.c \ lpc_common.c \ lpc11xx.c \ + lpc15xx.c \ lpc43xx.c \ kinetis.c \ main.c \ diff --git a/src/cortexm.c b/src/cortexm.c index be371d1..570cdd9 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -282,6 +282,7 @@ bool cortexm_probe(ADIv5_AP_t *ap) PROBE(stm32l0_probe); /* STM32L0xx & STM32L1xx */ PROBE(stm32l4_probe); PROBE(lpc11xx_probe); + PROBE(lpc15xx_probe); PROBE(lpc43xx_probe); PROBE(sam3x_probe); PROBE(nrf51_probe); diff --git a/src/include/target.h b/src/include/target.h index 2fcb4f0..e0839a2 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -264,6 +264,7 @@ bool stm32l1_probe(target *t); bool stm32l4_probe(target *t); bool lmi_probe(target *t); bool lpc11xx_probe(target *t); +bool lpc15xx_probe(target *t); bool lpc43xx_probe(target *t); bool sam3x_probe(target *t); bool nrf51_probe(target *t); diff --git a/src/lpc15xx.c b/src/lpc15xx.c new file mode 100644 index 0000000..32b9ad6 --- /dev/null +++ b/src/lpc15xx.c @@ -0,0 +1,76 @@ +#include "general.h" +#include "target.h" +#include "cortexm.h" +#include "lpc_common.h" + +#define IAP_PGM_CHUNKSIZE 512 /* should fit in RAM on any device */ + +#define MIN_RAM_SIZE 1024 +#define RAM_USAGE_FOR_IAP_ROUTINES 32 /* IAP routines use 32 bytes at top of ram */ + +#define IAP_ENTRYPOINT 0x03000205 +#define IAP_RAM_BASE 0x02000000 + +#define LPC15XX_DEVICE_ID 0x400743F8 + +static int lpc15xx_flash_write(struct target_flash *f, + uint32_t dest, const void *src, size_t len); + +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); + lf->f.blocksize = erasesize; + lf->f.buf_size = IAP_PGM_CHUNKSIZE; + lf->f.write_buf = lpc15xx_flash_write; + lf->iap_entry = IAP_ENTRYPOINT; + lf->iap_ram = IAP_RAM_BASE; + lf->iap_msp = IAP_RAM_BASE + MIN_RAM_SIZE - RAM_USAGE_FOR_IAP_ROUTINES; +} + +bool +lpc15xx_probe(target *t) +{ + uint32_t idcode; + uint32_t ram_size = 0; + + /* read the device ID register */ + idcode = target_mem_read32(t, LPC15XX_DEVICE_ID); + switch (idcode) { + case 0x00001549: + case 0x00001519: + ram_size = 0x9000; + break; + case 0x00001548: + case 0x00001518: + ram_size = 0x5000; + break; + case 0x00001547: + case 0x00001517: + ram_size = 0x3000; + break; + } + if (ram_size) { + t->driver = "LPC15xx"; + target_add_ram(t, 0x02000000, ram_size); + lpc15xx_add_flash(t, 0x00000000, 0x40000, 0x1000); + return true; + } + + return false; +} + +static int lpc15xx_flash_write(struct target_flash *f, + uint32_t dest, const void *src, size_t len) +{ + if (dest == 0) { + /* Fill in the magic vector to allow booting the flash */ + uint32_t *w = (uint32_t *)src; + uint32_t sum = 0; + + for (unsigned i = 0; i < 7; i++) + sum += w[i]; + w[7] = ~sum + 1; + } + return lpc_flash_write(f, dest, src, len); +} +