Consistently use 'target *t' for target var.

This commit is contained in:
Gareth McMullin 2015-03-28 20:47:17 -07:00
parent 1e54139f4a
commit 9f271d5cd7
14 changed files with 488 additions and 516 deletions

View File

@ -37,12 +37,10 @@
static const char adiv5_driver_str[] = "ARM ADIv5 MEM-AP"; static const char adiv5_driver_str[] = "ARM ADIv5 MEM-AP";
static int ap_check_error(struct target_s *target); static int ap_check_error(target *t);
static void ap_mem_read(struct target_s *target, void *dest, uint32_t src, static void ap_mem_read(target *t, void *dest, uint32_t src, size_t len);
size_t len); static void ap_mem_write(target *t, uint32_t dest, const void *src, size_t len);
static void ap_mem_write(struct target_s *target, uint32_t dest,
const void *src, size_t len);
void adiv5_dp_ref(ADIv5_DP_t *dp) void adiv5_dp_ref(ADIv5_DP_t *dp)
{ {
@ -160,9 +158,9 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
} }
static int static int
ap_check_error(struct target_s *target) ap_check_error(target *t)
{ {
ADIv5_AP_t *ap = adiv5_target_ap(target); ADIv5_AP_t *ap = adiv5_target_ap(t);
return adiv5_dp_error(ap->dp); return adiv5_dp_error(ap->dp);
} }
@ -212,9 +210,9 @@ static void * extract(void *dest, uint32_t src, uint32_t val, enum align align)
} }
static void static void
ap_mem_read(struct target_s *target, void *dest, uint32_t src, size_t len) ap_mem_read(target *t, void *dest, uint32_t src, size_t len)
{ {
ADIv5_AP_t *ap = adiv5_target_ap(target); ADIv5_AP_t *ap = adiv5_target_ap(t);
uint32_t tmp; uint32_t tmp;
uint32_t osrc = src; uint32_t osrc = src;
enum align align = MIN(ALIGNOF(src), ALIGNOF(len)); enum align align = MIN(ALIGNOF(src), ALIGNOF(len));
@ -241,9 +239,9 @@ ap_mem_read(struct target_s *target, void *dest, uint32_t src, size_t len)
} }
static void static void
ap_mem_write(struct target_s *target, uint32_t dest, const void *src, size_t len) ap_mem_write(target *t, uint32_t dest, const void *src, size_t len)
{ {
ADIv5_AP_t *ap = adiv5_target_ap(target); ADIv5_AP_t *ap = adiv5_target_ap(t);
uint32_t odest = dest; uint32_t odest = dest;
enum align align = MIN(ALIGNOF(dest), ALIGNOF(len)); enum align align = MIN(ALIGNOF(dest), ALIGNOF(len));

View File

@ -94,13 +94,13 @@ uint32_t crc32_calc(uint32_t crc, uint8_t data)
return (crc << 8) ^ crc32_table[((crc >> 24) ^ data) & 255]; return (crc << 8) ^ crc32_table[((crc >> 24) ^ data) & 255];
} }
uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) uint32_t generic_crc32(target *t, uint32_t base, int len)
{ {
uint32_t crc = -1; uint32_t crc = -1;
uint8_t byte; uint8_t byte;
while (len--) { while (len--) {
byte = target_mem_read8(target, base); byte = target_mem_read8(t, base);
crc = crc32_calc(crc, byte); crc = crc32_calc(crc, byte);
base++; base++;
@ -109,7 +109,7 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len)
} }
#else #else
#include <libopencm3/stm32/crc.h> #include <libopencm3/stm32/crc.h>
uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) uint32_t generic_crc32(target *t, uint32_t base, int len)
{ {
uint32_t data; uint32_t data;
uint32_t crc; uint32_t crc;
@ -118,7 +118,7 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len)
CRC_CR |= CRC_CR_RESET; CRC_CR |= CRC_CR_RESET;
while (len > 3) { while (len > 3) {
data = target_mem_read32(target, base); data = target_mem_read32(t, base);
CRC_DR = __builtin_bswap32(data); CRC_DR = __builtin_bswap32(data);
base += 4; base += 4;
@ -128,7 +128,7 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len)
crc = CRC_DR; crc = CRC_DR;
while (len--) { while (len--) {
data = target_mem_read8(target, base++); data = target_mem_read8(t, base++);
crc ^= data << 24; crc ^= data << 24;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {

View File

@ -143,10 +143,10 @@
#define CORTEXM_DWT_FUNC_FUNC_WRITE (6 << 0) #define CORTEXM_DWT_FUNC_FUNC_WRITE (6 << 0)
#define CORTEXM_DWT_FUNC_FUNC_ACCESS (7 << 0) #define CORTEXM_DWT_FUNC_FUNC_ACCESS (7 << 0)
bool cortexm_attach(struct target_s *target); bool cortexm_attach(target *t);
void cortexm_detach(struct target_s *target); void cortexm_detach(target *t);
void cortexm_halt_resume(struct target_s *target, bool step); void cortexm_halt_resume(target *t, bool step);
int cortexm_run_stub(struct target_s *target, uint32_t loadaddr, int cortexm_run_stub(target *t, uint32_t loadaddr,
const uint16_t *stub, uint32_t stublen, const uint16_t *stub, uint32_t stublen,
uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3); uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3);
int cortexm_pc_write(target *t, const uint32_t val); int cortexm_pc_write(target *t, const uint32_t val);

View File

@ -22,6 +22,6 @@
#define __CRC32_H #define __CRC32_H
uint32_t crc32_calc(uint32_t crc, uint8_t data); uint32_t crc32_calc(uint32_t crc, uint8_t data);
uint32_t generic_crc32(struct target_s *target, uint32_t base, int len); uint32_t generic_crc32(target *t, uint32_t base, int len);
#endif #endif

View File

@ -54,8 +54,8 @@
#define KL25_PAGESIZE 0x400 #define KL25_PAGESIZE 0x400
static int kl25_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int kl25_flash_erase(target *t, uint32_t addr, size_t len);
static int kl25_flash_write(struct target_s *target, uint32_t dest, static int kl25_flash_write(target *t, uint32_t dest,
const uint8_t *src, size_t len); const uint8_t *src, size_t len);
static const char kl25_xml_memory_map[] = "<?xml version=\"1.0\"?>" static const char kl25_xml_memory_map[] = "<?xml version=\"1.0\"?>"
@ -70,7 +70,7 @@ static const char kl25_xml_memory_map[] = "<?xml version=\"1.0\"?>"
" <memory type=\"ram\" start=\"0x20000000\" length=\"0x3000\"/>" " <memory type=\"ram\" start=\"0x20000000\" length=\"0x3000\"/>"
"</memory-map>"; "</memory-map>";
bool kinetis_probe(struct target_s *t) bool kinetis_probe(target *t)
{ {
uint32_t sdid = target_mem_read32(t, SIM_SDID); uint32_t sdid = target_mem_read32(t, SIM_SDID);
switch (sdid >> 20) { switch (sdid >> 20) {
@ -85,7 +85,7 @@ bool kinetis_probe(struct target_s *t)
} }
static bool static bool
kl25_command(struct target_s *t, uint8_t cmd, uint32_t addr, const uint8_t data[8]) kl25_command(target *t, uint8_t cmd, uint32_t addr, const uint8_t data[8])
{ {
uint8_t fstat; uint8_t fstat;
@ -120,7 +120,7 @@ kl25_command(struct target_s *t, uint8_t cmd, uint32_t addr, const uint8_t data[
return true; return true;
} }
static int kl25_flash_erase(struct target_s *t, uint32_t addr, size_t len) static int kl25_flash_erase(target *t, uint32_t addr, size_t len)
{ {
addr &= ~(KL25_PAGESIZE - 1); addr &= ~(KL25_PAGESIZE - 1);
len = (len + KL25_PAGESIZE - 1) & ~(KL25_PAGESIZE - 1); len = (len + KL25_PAGESIZE - 1) & ~(KL25_PAGESIZE - 1);
@ -133,7 +133,7 @@ static int kl25_flash_erase(struct target_s *t, uint32_t addr, size_t len)
return 0; return 0;
} }
static int kl25_flash_write(struct target_s *t, uint32_t dest, static int kl25_flash_write(target *t, uint32_t dest,
const uint8_t *src, size_t len) const uint8_t *src, size_t len)
{ {
/* FIXME handle misaligned start and end of sections */ /* FIXME handle misaligned start and end of sections */

View File

@ -32,8 +32,8 @@
#include "target.h" #include "target.h"
#include "cortexm.h" #include "cortexm.h"
static int lmi_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int lmi_flash_erase(target *t, uint32_t addr, size_t len);
static int lmi_flash_write(struct target_s *target, uint32_t dest, static int lmi_flash_write(target *t, uint32_t dest,
const uint8_t *src, size_t len); const uint8_t *src, size_t len);
static const char lmi_driver_str[] = "TI Stellaris/Tiva"; static const char lmi_driver_str[] = "TI Stellaris/Tiva";
@ -99,30 +99,30 @@ static const uint16_t lmi_flash_write_stub[] = {
// ... // ...
}; };
bool lmi_probe(struct target_s *target) bool lmi_probe(target *t)
{ {
uint32_t did1 = target_mem_read32(target, 0x400FE004); uint32_t did1 = target_mem_read32(t, 0x400FE004);
switch (did1 >> 16) { switch (did1 >> 16) {
case 0x1049: /* LM3S3748 */ case 0x1049: /* LM3S3748 */
target->driver = lmi_driver_str; t->driver = lmi_driver_str;
target->xml_mem_map = lmi_xml_memory_map; t->xml_mem_map = lmi_xml_memory_map;
target->flash_erase = lmi_flash_erase; t->flash_erase = lmi_flash_erase;
target->flash_write = lmi_flash_write; t->flash_write = lmi_flash_write;
return true; return true;
case 0x10A1: /* TM4C123GH6PM */ case 0x10A1: /* TM4C123GH6PM */
target->driver = lmi_driver_str; t->driver = lmi_driver_str;
target->xml_mem_map = tm4c123gh6pm_xml_memory_map; t->xml_mem_map = tm4c123gh6pm_xml_memory_map;
target->flash_erase = lmi_flash_erase; t->flash_erase = lmi_flash_erase;
target->flash_write = lmi_flash_write; t->flash_write = lmi_flash_write;
return true; return true;
} }
return false; return false;
} }
int lmi_flash_erase(struct target_s *target, uint32_t addr, size_t len) int lmi_flash_erase(target *t, uint32_t addr, size_t len)
{ {
ADIv5_AP_t *ap = adiv5_target_ap(target); ADIv5_AP_t *ap = adiv5_target_ap(t);
uint32_t tmp; uint32_t tmp;
addr &= 0xFFFFFC00; addr &= 0xFFFFFC00;
@ -152,22 +152,21 @@ int lmi_flash_erase(struct target_s *target, uint32_t addr, size_t len)
return 0; return 0;
} }
int lmi_flash_write(struct target_s *target, uint32_t dest, int lmi_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len)
const uint8_t *src, size_t len)
{ {
uint32_t data[(len>>2)+2]; uint32_t data[(len>>2)+2];
data[0] = dest; data[0] = dest;
data[1] = len >> 2; data[1] = len >> 2;
memcpy(&data[2], src, len); memcpy(&data[2], src, len);
DEBUG("Sending stub\n"); DEBUG("Sending stub\n");
target_mem_write(target, 0x20000000, (void*)lmi_flash_write_stub, 0x30); target_mem_write(t, 0x20000000, (void*)lmi_flash_write_stub, 0x30);
DEBUG("Sending data\n"); DEBUG("Sending data\n");
target_mem_write(target, 0x20000030, data, len + 8); target_mem_write(t, 0x20000030, data, len + 8);
DEBUG("Running stub\n"); DEBUG("Running stub\n");
cortexm_pc_write(target, 0x20000000); cortexm_pc_write(t, 0x20000000);
target_halt_resume(target, 0); target_halt_resume(t, 0);
DEBUG("Waiting for halt\n"); DEBUG("Waiting for halt\n");
while(!target_halt_wait(target)); while(!target_halt_wait(t));
return 0; return 0;
} }

View File

@ -61,10 +61,10 @@ static struct flash_program flash_pgm;
static const char lpc8xx_driver[] = "lpc8xx"; static const char lpc8xx_driver[] = "lpc8xx";
static const char lpc11xx_driver[] = "lpc11xx"; static const char lpc11xx_driver[] = "lpc11xx";
static void lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len); static void lpc11x_iap_call(target *t, struct flash_param *param, unsigned param_len);
static int lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len); static int lpc11xx_flash_prepare(target *t, uint32_t addr, int len);
static int lpc11xx_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int lpc11xx_flash_erase(target *t, uint32_t addr, size_t len);
static int lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, static int lpc11xx_flash_write(target *t, uint32_t dest, const uint8_t *src,
size_t len); size_t len);
/* /*
@ -103,12 +103,12 @@ static const char lpc8xx_xml_memory_map[] = "<?xml version=\"1.0\"?>"
"</memory-map>"; "</memory-map>";
bool bool
lpc11xx_probe(struct target_s *target) lpc11xx_probe(target *t)
{ {
uint32_t idcode; uint32_t idcode;
/* read the device ID register */ /* read the device ID register */
idcode = target_mem_read32(target, 0x400483F4); idcode = target_mem_read32(t, 0x400483F4);
switch (idcode) { switch (idcode) {
@ -143,18 +143,18 @@ lpc11xx_probe(struct target_s *target)
case 0x2972402B: /* lpc11u23/301 */ case 0x2972402B: /* lpc11u23/301 */
case 0x2988402B: /* lpc11u24x/301 */ case 0x2988402B: /* lpc11u24x/301 */
case 0x2980002B: /* lpc11u24x/401 */ case 0x2980002B: /* lpc11u24x/401 */
target->driver = lpc11xx_driver; t->driver = lpc11xx_driver;
target->xml_mem_map = lpc11xx_xml_memory_map; t->xml_mem_map = lpc11xx_xml_memory_map;
target->flash_erase = lpc11xx_flash_erase; t->flash_erase = lpc11xx_flash_erase;
target->flash_write = lpc11xx_flash_write; t->flash_write = lpc11xx_flash_write;
return true; return true;
case 0x1812202b: /* LPC812M101FDH20 */ case 0x1812202b: /* LPC812M101FDH20 */
target->driver = lpc8xx_driver; t->driver = lpc8xx_driver;
target->xml_mem_map = lpc8xx_xml_memory_map; t->xml_mem_map = lpc8xx_xml_memory_map;
target->flash_erase = lpc11xx_flash_erase; t->flash_erase = lpc11xx_flash_erase;
target->flash_write = lpc11xx_flash_write; t->flash_write = lpc11xx_flash_write;
return true; return true;
} }
@ -163,55 +163,55 @@ lpc11xx_probe(struct target_s *target)
} }
static void static void
lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len) lpc11x_iap_call(target *t, struct flash_param *param, unsigned param_len)
{ {
uint32_t regs[target->regs_size / sizeof(uint32_t)]; uint32_t regs[t->regs_size / sizeof(uint32_t)];
/* fill out the remainder of the parameters and copy the structure to RAM */ /* fill out the remainder of the parameters and copy the structure to RAM */
param->opcodes[0] = 0xbe00; param->opcodes[0] = 0xbe00;
param->opcodes[1] = 0x0000; param->opcodes[1] = 0x0000;
target_mem_write(target, IAP_RAM_BASE, param, param_len); target_mem_write(t, IAP_RAM_BASE, param, param_len);
/* set up for the call to the IAP ROM */ /* set up for the call to the IAP ROM */
target_regs_read(target, regs); target_regs_read(t, regs);
regs[0] = IAP_RAM_BASE + offsetof(struct flash_param, command); regs[0] = IAP_RAM_BASE + offsetof(struct flash_param, command);
regs[1] = IAP_RAM_BASE + offsetof(struct flash_param, result); regs[1] = IAP_RAM_BASE + offsetof(struct flash_param, result);
// stack pointer - top of the smallest ram less 32 for IAP usage // stack pointer - top of the smallest ram less 32 for IAP usage
if (target->driver == lpc8xx_driver) if (t->driver == lpc8xx_driver)
regs[MSP] = IAP_RAM_BASE + MIN_RAM_SIZE_FOR_LPC8xx - RAM_USAGE_FOR_IAP_ROUTINES; regs[MSP] = IAP_RAM_BASE + MIN_RAM_SIZE_FOR_LPC8xx - RAM_USAGE_FOR_IAP_ROUTINES;
else else
regs[MSP] = IAP_RAM_BASE + MIN_RAM_SIZE_FOR_LPC1xxx - RAM_USAGE_FOR_IAP_ROUTINES; regs[MSP] = IAP_RAM_BASE + MIN_RAM_SIZE_FOR_LPC1xxx - RAM_USAGE_FOR_IAP_ROUTINES;
regs[14] = IAP_RAM_BASE | 1; regs[14] = IAP_RAM_BASE | 1;
regs[15] = IAP_ENTRYPOINT; regs[15] = IAP_ENTRYPOINT;
target_regs_write(target, regs); target_regs_write(t, regs);
/* start the target and wait for it to halt again */ /* start the target and wait for it to halt again */
target_halt_resume(target, 0); target_halt_resume(t, 0);
while (!target_halt_wait(target)); while (!target_halt_wait(t));
/* copy back just the parameters structure */ /* copy back just the parameters structure */
target_mem_read(target, param, IAP_RAM_BASE, sizeof(struct flash_param)); target_mem_read(t, param, IAP_RAM_BASE, sizeof(struct flash_param));
} }
static int flash_page_size(struct target_s *target) static int flash_page_size(target *t)
{ {
if (target->driver == lpc8xx_driver) if (t->driver == lpc8xx_driver)
return 1024; return 1024;
else else
return 4096; return 4096;
} }
static int static int
lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len) lpc11xx_flash_prepare(target *t, uint32_t addr, int len)
{ {
/* prepare the sector(s) to be erased */ /* prepare the sector(s) to be erased */
memset(&flash_pgm.p, 0, sizeof(flash_pgm.p)); memset(&flash_pgm.p, 0, sizeof(flash_pgm.p));
flash_pgm.p.command[0] = IAP_CMD_PREPARE; flash_pgm.p.command[0] = IAP_CMD_PREPARE;
flash_pgm.p.command[1] = addr / flash_page_size(target); flash_pgm.p.command[1] = addr / flash_page_size(t);
flash_pgm.p.command[2] = (addr + len - 1) / flash_page_size(target); flash_pgm.p.command[2] = (addr + len - 1) / flash_page_size(t);
lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); lpc11x_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p));
if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
return -1; return -1;
} }
@ -220,27 +220,27 @@ lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len)
} }
static int static int
lpc11xx_flash_erase(struct target_s *target, uint32_t addr, size_t len) lpc11xx_flash_erase(target *t, uint32_t addr, size_t len)
{ {
if (addr % flash_page_size(target)) if (addr % flash_page_size(t))
return -1; return -1;
/* prepare... */ /* prepare... */
if (lpc11xx_flash_prepare(target, addr, len)) if (lpc11xx_flash_prepare(t, addr, len))
return -1; return -1;
/* and now erase them */ /* and now erase them */
flash_pgm.p.command[0] = IAP_CMD_ERASE; flash_pgm.p.command[0] = IAP_CMD_ERASE;
flash_pgm.p.command[1] = addr / flash_page_size(target); flash_pgm.p.command[1] = addr / flash_page_size(t);
flash_pgm.p.command[2] = (addr + len - 1) / flash_page_size(target); flash_pgm.p.command[2] = (addr + len - 1) / flash_page_size(t);
flash_pgm.p.command[3] = 12000; /* XXX safe to assume this? */ flash_pgm.p.command[3] = 12000; /* XXX safe to assume this? */
lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); lpc11x_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p));
if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
return -1; return -1;
} }
flash_pgm.p.command[0] = IAP_CMD_BLANKCHECK; flash_pgm.p.command[0] = IAP_CMD_BLANKCHECK;
lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); lpc11x_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p));
if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
return -1; return -1;
} }
@ -249,7 +249,7 @@ lpc11xx_flash_erase(struct target_s *target, uint32_t addr, size_t len)
} }
static int static int
lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, size_t len) lpc11xx_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len)
{ {
unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE; unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE;
unsigned last_chunk = (dest + len - 1) / IAP_PGM_CHUNKSIZE; unsigned last_chunk = (dest + len - 1) / IAP_PGM_CHUNKSIZE;
@ -300,7 +300,7 @@ lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src,
} }
/* prepare... */ /* prepare... */
if (lpc11xx_flash_prepare(target, chunk * IAP_PGM_CHUNKSIZE, IAP_PGM_CHUNKSIZE)) if (lpc11xx_flash_prepare(t, chunk * IAP_PGM_CHUNKSIZE, IAP_PGM_CHUNKSIZE))
return -1; return -1;
/* set the destination address and program */ /* set the destination address and program */
@ -310,7 +310,7 @@ lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src,
flash_pgm.p.command[3] = IAP_PGM_CHUNKSIZE; flash_pgm.p.command[3] = IAP_PGM_CHUNKSIZE;
/* assuming we are running off IRC - safe lower bound */ /* assuming we are running off IRC - safe lower bound */
flash_pgm.p.command[4] = 12000; /* XXX safe to presume this? */ flash_pgm.p.command[4] = 12000; /* XXX safe to presume this? */
lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm)); lpc11x_iap_call(t, &flash_pgm.p, sizeof(flash_pgm));
if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
return -1; return -1;
} }

View File

@ -119,20 +119,20 @@ struct flash_program {
uint8_t data[IAP_PGM_CHUNKSIZE]; uint8_t data[IAP_PGM_CHUNKSIZE];
}; };
static bool lpc43xx_cmd_erase(target *target, int argc, const char *argv[]); static bool lpc43xx_cmd_erase(target *t, int argc, const char *argv[]);
static bool lpc43xx_cmd_reset(target *target, int argc, const char *argv[]); static bool lpc43xx_cmd_reset(target *t, int argc, const char *argv[]);
static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[]); static bool lpc43xx_cmd_mkboot(target *t, int argc, const char *argv[]);
static int lpc43xx_flash_init(struct target_s *target); static int lpc43xx_flash_init(target *t);
static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, static void lpc43xx_iap_call(target *t, struct flash_param *param,
unsigned param_len); unsigned param_len);
static int lpc43xx_flash_prepare(struct target_s *target, static int lpc43xx_flash_prepare(target *t,
uint32_t addr, int len); uint32_t addr, int len);
static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int lpc43xx_flash_erase(target *t, uint32_t addr, size_t len);
static int lpc43xx_flash_write(struct target_s *target, static int lpc43xx_flash_write(target *t,
uint32_t dest, const uint8_t *src, size_t len); uint32_t dest, const uint8_t *src, size_t len);
static void lpc43xx_set_internal_clock(struct target_s *target); static void lpc43xx_set_internal_clock(target *t);
static void lpc43xx_wdt_set_period(struct target_s *target); static void lpc43xx_wdt_set_period(target *t);
static void lpc43xx_wdt_pet(struct target_s *target); static void lpc43xx_wdt_pet(target *t);
const struct command_s lpc43xx_cmd_list[] = { const struct command_s lpc43xx_cmd_list[] = {
{"erase_mass", lpc43xx_cmd_erase, "Erase entire flash memory"}, {"erase_mass", lpc43xx_cmd_erase, "Erase entire flash memory"},
@ -166,45 +166,45 @@ static const char lpc4337_xml_memory_map[] = "<?xml version=\"1.0\"?>"
" <memory type=\"ram\" start=\"0x1B080000\" length=\"0xE4F80000\"/>" " <memory type=\"ram\" start=\"0x1B080000\" length=\"0xE4F80000\"/>"
"</memory-map>"; "</memory-map>";
bool lpc43xx_probe(struct target_s *target) bool lpc43xx_probe(target *t)
{ {
uint32_t chipid, cpuid; uint32_t chipid, cpuid;
chipid = target_mem_read32(target, LPC43XX_CHIPID); chipid = target_mem_read32(t, LPC43XX_CHIPID);
cpuid = target_mem_read32(target, ARM_CPUID); cpuid = target_mem_read32(t, ARM_CPUID);
switch(chipid) { switch(chipid) {
case 0x4906002B: /* Parts with on-chip flash */ case 0x4906002B: /* Parts with on-chip flash */
switch (cpuid & 0xFF00FFF0) { switch (cpuid & 0xFF00FFF0) {
case 0x4100C240: case 0x4100C240:
target->driver = "LPC43xx Cortex-M4"; t->driver = "LPC43xx Cortex-M4";
if (cpuid == 0x410FC241) if (cpuid == 0x410FC241)
{ {
/* LPC4337 */ /* LPC4337 */
target->xml_mem_map = lpc4337_xml_memory_map; t->xml_mem_map = lpc4337_xml_memory_map;
target->flash_erase = lpc43xx_flash_erase; t->flash_erase = lpc43xx_flash_erase;
target->flash_write = lpc43xx_flash_write; t->flash_write = lpc43xx_flash_write;
target_add_commands(target, lpc43xx_cmd_list, "LPC43xx"); target_add_commands(t, lpc43xx_cmd_list, "LPC43xx");
} }
break; break;
case 0x4100C200: case 0x4100C200:
target->driver = "LPC43xx Cortex-M0"; t->driver = "LPC43xx Cortex-M0";
break; break;
default: default:
target->driver = "LPC43xx <Unknown>"; t->driver = "LPC43xx <Unknown>";
} }
return true; return true;
case 0x5906002B: /* Flashless parts */ case 0x5906002B: /* Flashless parts */
case 0x6906002B: case 0x6906002B:
switch (cpuid & 0xFF00FFF0) { switch (cpuid & 0xFF00FFF0) {
case 0x4100C240: case 0x4100C240:
target->driver = "LPC43xx Cortex-M4"; t->driver = "LPC43xx Cortex-M4";
break; break;
case 0x4100C200: case 0x4100C200:
target->driver = "LPC43xx Cortex-M0"; t->driver = "LPC43xx Cortex-M0";
break; break;
default: default:
target->driver = "LPC43xx <Unknown>"; t->driver = "LPC43xx <Unknown>";
} }
return true; return true;
} }
@ -213,7 +213,7 @@ bool lpc43xx_probe(struct target_s *target)
} }
/* Reset all major systems _except_ debug */ /* Reset all major systems _except_ debug */
static bool lpc43xx_cmd_reset(target *target, int argc, const char *argv[]) static bool lpc43xx_cmd_reset(target *t, int argc, const char *argv[])
{ {
(void)argc; (void)argc;
(void)argv; (void)argv;
@ -224,12 +224,12 @@ static bool lpc43xx_cmd_reset(target *target, int argc, const char *argv[])
static const uint32_t reset_val = 0x05FA0004; static const uint32_t reset_val = 0x05FA0004;
/* System reset on target */ /* System reset on target */
target_mem_write(target, AIRCR, &reset_val, sizeof(reset_val)); target_mem_write(t, AIRCR, &reset_val, sizeof(reset_val));
return true; return true;
} }
static bool lpc43xx_cmd_erase(target *target, int argc, const char *argv[]) static bool lpc43xx_cmd_erase(target *t, int argc, const char *argv[])
{ {
(void)argc; (void)argc;
(void)argv; (void)argv;
@ -237,7 +237,7 @@ static bool lpc43xx_cmd_erase(target *target, int argc, const char *argv[])
uint32_t bank = 0; uint32_t bank = 0;
struct flash_program flash_pgm; struct flash_program flash_pgm;
lpc43xx_flash_init(target); lpc43xx_flash_init(t);
for (bank = 0; bank < FLASH_NUM_BANK; bank++) for (bank = 0; bank < FLASH_NUM_BANK; bank++)
{ {
@ -246,7 +246,7 @@ static bool lpc43xx_cmd_erase(target *target, int argc, const char *argv[])
flash_pgm.p.params.prepare.end_sector = FLASH_NUM_SECTOR-1; flash_pgm.p.params.prepare.end_sector = FLASH_NUM_SECTOR-1;
flash_pgm.p.params.prepare.flash_bank = bank; flash_pgm.p.params.prepare.flash_bank = bank;
flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS;
lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p));
if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
return false; return false;
} }
@ -257,7 +257,7 @@ static bool lpc43xx_cmd_erase(target *target, int argc, const char *argv[])
flash_pgm.p.params.erase.cpu_clk_khz = CPU_CLK_KHZ; flash_pgm.p.params.erase.cpu_clk_khz = CPU_CLK_KHZ;
flash_pgm.p.params.erase.flash_bank = bank; flash_pgm.p.params.erase.flash_bank = bank;
flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS;
lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p));
if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS)
{ {
return false; return false;
@ -269,20 +269,20 @@ static bool lpc43xx_cmd_erase(target *target, int argc, const char *argv[])
return true; return true;
} }
static int lpc43xx_flash_init(struct target_s *target) static int lpc43xx_flash_init(target *t)
{ {
/* Deal with WDT */ /* Deal with WDT */
lpc43xx_wdt_set_period(target); lpc43xx_wdt_set_period(t);
/* Force internal clock */ /* Force internal clock */
lpc43xx_set_internal_clock(target); lpc43xx_set_internal_clock(t);
struct flash_program flash_pgm; struct flash_program flash_pgm;
/* Initialize flash IAP */ /* Initialize flash IAP */
flash_pgm.p.command = IAP_CMD_INIT; flash_pgm.p.command = IAP_CMD_INIT;
flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS;
lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p));
if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS)
return -1; return -1;
@ -332,40 +332,40 @@ static int32_t sector_number(uint32_t addr)
} }
} }
static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len) static void lpc43xx_iap_call(target *t, struct flash_param *param, unsigned param_len)
{ {
uint32_t regs[target->regs_size / sizeof(uint32_t)]; uint32_t regs[t->regs_size / sizeof(uint32_t)];
uint32_t iap_entry; uint32_t iap_entry;
/* Pet WDT before each IAP call, if it is on */ /* Pet WDT before each IAP call, if it is on */
lpc43xx_wdt_pet(target); lpc43xx_wdt_pet(t);
target_mem_read(target, &iap_entry, IAP_ENTRYPOINT_LOCATION, sizeof(iap_entry)); target_mem_read(t, &iap_entry, IAP_ENTRYPOINT_LOCATION, sizeof(iap_entry));
/* fill out the remainder of the parameters and copy the structure to RAM */ /* fill out the remainder of the parameters and copy the structure to RAM */
param->opcode = ARM_THUMB_BREAKPOINT; /* breakpoint */ param->opcode = ARM_THUMB_BREAKPOINT; /* breakpoint */
param->pad0 = 0x0000; /* pad */ param->pad0 = 0x0000; /* pad */
target_mem_write(target, IAP_RAM_BASE, param, param_len); target_mem_write(t, IAP_RAM_BASE, param, param_len);
/* set up for the call to the IAP ROM */ /* set up for the call to the IAP ROM */
target_regs_read(target, regs); target_regs_read(t, regs);
regs[0] = IAP_RAM_BASE + offsetof(struct flash_param, command); regs[0] = IAP_RAM_BASE + offsetof(struct flash_param, command);
regs[1] = IAP_RAM_BASE + offsetof(struct flash_param, result); regs[1] = IAP_RAM_BASE + offsetof(struct flash_param, result);
regs[R_MSP] = IAP_RAM_BASE + IAP_RAM_SIZE; regs[R_MSP] = IAP_RAM_BASE + IAP_RAM_SIZE;
regs[R_LR] = IAP_RAM_BASE | 1; regs[R_LR] = IAP_RAM_BASE | 1;
regs[R_PC] = iap_entry; regs[R_PC] = iap_entry;
target_regs_write(target, regs); target_regs_write(t, regs);
/* start the target and wait for it to halt again */ /* start the target and wait for it to halt again */
target_halt_resume(target, 0); target_halt_resume(t, 0);
while (!target_halt_wait(target)); while (!target_halt_wait(t));
/* copy back just the parameters structure */ /* copy back just the parameters structure */
target_mem_read(target, param, IAP_RAM_BASE, sizeof(struct flash_param)); target_mem_read(t, param, IAP_RAM_BASE, sizeof(struct flash_param));
} }
static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len) static int lpc43xx_flash_prepare(target *t, uint32_t addr, int len)
{ {
struct flash_program flash_pgm; struct flash_program flash_pgm;
@ -376,7 +376,7 @@ static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len
flash_pgm.p.params.prepare.flash_bank = flash_bank(addr); flash_pgm.p.params.prepare.flash_bank = flash_bank(addr);
flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS;
lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p));
if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
return -1; return -1;
} }
@ -384,7 +384,7 @@ static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len
return 0; return 0;
} }
static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, size_t len) static int lpc43xx_flash_erase(target *t, uint32_t addr, size_t len)
{ {
struct flash_program flash_pgm; struct flash_program flash_pgm;
@ -393,11 +393,11 @@ static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, size_t le
return -1; return -1;
/* init */ /* init */
if (lpc43xx_flash_init(target)) if (lpc43xx_flash_init(t))
return -1; return -1;
/* prepare... */ /* prepare... */
if (lpc43xx_flash_prepare(target, addr, len)) if (lpc43xx_flash_prepare(t, addr, len))
return -1; return -1;
/* and now erase them */ /* and now erase them */
@ -407,7 +407,7 @@ static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, size_t le
flash_pgm.p.params.erase.cpu_clk_khz = CPU_CLK_KHZ; flash_pgm.p.params.erase.cpu_clk_khz = CPU_CLK_KHZ;
flash_pgm.p.params.erase.flash_bank = flash_bank(addr); flash_pgm.p.params.erase.flash_bank = flash_bank(addr);
flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS;
lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p));
if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
return -1; return -1;
} }
@ -418,7 +418,7 @@ static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, size_t le
flash_pgm.p.params.blank_check.end_sector = sector_number(addr+len); flash_pgm.p.params.blank_check.end_sector = sector_number(addr+len);
flash_pgm.p.params.blank_check.flash_bank = flash_bank(addr); flash_pgm.p.params.blank_check.flash_bank = flash_bank(addr);
flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS;
lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p));
if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
return -1; return -1;
} }
@ -426,13 +426,13 @@ static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, size_t le
return 0; return 0;
} }
static void lpc43xx_set_internal_clock(struct target_s *target) static void lpc43xx_set_internal_clock(target *t)
{ {
const uint32_t val2 = (1 << 11) | (1 << 24); const uint32_t val2 = (1 << 11) | (1 << 24);
target_mem_write(target, 0x40050000 + 0x06C, &val2, sizeof(val2)); target_mem_write(t, 0x40050000 + 0x06C, &val2, sizeof(val2));
} }
static int lpc43xx_flash_write(struct target_s *target, static int lpc43xx_flash_write(target *t,
uint32_t dest, const uint8_t *src, size_t len) uint32_t dest, const uint8_t *src, size_t len)
{ {
unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE; unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE;
@ -472,12 +472,12 @@ static int lpc43xx_flash_write(struct target_s *target,
} }
/* prepare... */ /* prepare... */
if (lpc43xx_flash_prepare(target, chunk * IAP_PGM_CHUNKSIZE, IAP_PGM_CHUNKSIZE)) { if (lpc43xx_flash_prepare(t, chunk * IAP_PGM_CHUNKSIZE, IAP_PGM_CHUNKSIZE)) {
return -1; return -1;
} }
/* copy buffer into target memory */ /* copy buffer into target memory */
target_mem_write(target, target_mem_write(t,
IAP_RAM_BASE + offsetof(struct flash_program, data), IAP_RAM_BASE + offsetof(struct flash_program, data),
flash_pgm.data, sizeof(flash_pgm.data)); flash_pgm.data, sizeof(flash_pgm.data));
@ -488,7 +488,7 @@ static int lpc43xx_flash_write(struct target_s *target,
flash_pgm.p.params.program.byte_count = IAP_PGM_CHUNKSIZE; flash_pgm.p.params.program.byte_count = IAP_PGM_CHUNKSIZE;
flash_pgm.p.params.program.cpu_clk_khz = CPU_CLK_KHZ; flash_pgm.p.params.program.cpu_clk_khz = CPU_CLK_KHZ;
flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS;
lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm)); lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm));
if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
return -1; return -1;
} }
@ -504,7 +504,7 @@ static int lpc43xx_flash_write(struct target_s *target,
* This is done indepently of writing to give the user a chance to verify flash * This is done indepently of writing to give the user a chance to verify flash
* before changing it. * before changing it.
*/ */
static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[]) static bool lpc43xx_cmd_mkboot(target *t, int argc, const char *argv[])
{ {
/* Usage: mkboot 0 or mkboot 1 */ /* Usage: mkboot 0 or mkboot 1 */
if (argc != 2) { if (argc != 2) {
@ -519,7 +519,7 @@ static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[])
return false; return false;
} }
lpc43xx_flash_init(target); lpc43xx_flash_init(t);
struct flash_program flash_pgm; struct flash_program flash_pgm;
/* special command to compute/write magic vector for signature */ /* special command to compute/write magic vector for signature */
@ -527,7 +527,7 @@ static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[])
flash_pgm.p.params.make_active.flash_bank = 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.params.make_active.cpu_clk_khz = CPU_CLK_KHZ;
flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS;
lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm)); lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm));
if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
gdb_outf("Set bootable failed.\n"); gdb_outf("Set bootable failed.\n");
return false; return false;
@ -537,11 +537,11 @@ static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[])
return true; return true;
} }
static void lpc43xx_wdt_set_period(struct target_s *target) static void lpc43xx_wdt_set_period(target *t)
{ {
uint32_t wdt_mode = 0; uint32_t wdt_mode = 0;
/* Check if WDT is on */ /* Check if WDT is on */
target_mem_read(target, &wdt_mode, LPC43XX_WDT_MODE, sizeof(wdt_mode)); target_mem_read(t, &wdt_mode, LPC43XX_WDT_MODE, sizeof(wdt_mode));
/* If WDT on, we can't disable it, but we may be able to set a long period */ /* If WDT on, we can't disable it, but we may be able to set a long period */
if (wdt_mode && !(wdt_mode & LPC43XX_WDT_PROTECT)) if (wdt_mode && !(wdt_mode & LPC43XX_WDT_PROTECT))
@ -549,15 +549,15 @@ static void lpc43xx_wdt_set_period(struct target_s *target)
const uint32_t wdt_period = LPC43XX_WDT_PERIOD_MAX; const uint32_t wdt_period = LPC43XX_WDT_PERIOD_MAX;
target_mem_write(target, LPC43XX_WDT_CNT, &wdt_period, sizeof(wdt_period)); target_mem_write(t, LPC43XX_WDT_CNT, &wdt_period, sizeof(wdt_period));
} }
} }
static void lpc43xx_wdt_pet(struct target_s *target) static void lpc43xx_wdt_pet(target *t)
{ {
uint32_t wdt_mode = 0; uint32_t wdt_mode = 0;
/* Check if WDT is on */ /* Check if WDT is on */
target_mem_read(target, &wdt_mode, LPC43XX_WDT_MODE, sizeof(wdt_mode)); target_mem_read(t, &wdt_mode, LPC43XX_WDT_MODE, sizeof(wdt_mode));
/* If WDT on, pet */ /* If WDT on, pet */
if (wdt_mode) if (wdt_mode)
@ -565,8 +565,7 @@ static void lpc43xx_wdt_pet(struct target_s *target)
const uint32_t feed1 = 0xAA;; const uint32_t feed1 = 0xAA;;
const uint32_t feed2 = 0x55;; const uint32_t feed2 = 0x55;;
target_mem_write(t, LPC43XX_WDT_FEED, &feed1, sizeof(feed1));
target_mem_write(target, LPC43XX_WDT_FEED, &feed1, sizeof(feed1)); target_mem_write(t, LPC43XX_WDT_FEED, &feed2, sizeof(feed2));
target_mem_write(target, LPC43XX_WDT_FEED, &feed2, sizeof(feed2));
} }
} }

View File

@ -28,8 +28,8 @@
#include "gdb_packet.h" #include "gdb_packet.h"
#include "cortexm.h" #include "cortexm.h"
static int nrf51_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int nrf51_flash_erase(target *t, uint32_t addr, size_t len);
static int nrf51_flash_write(struct target_s *target, uint32_t dest, static int nrf51_flash_write(target *t, uint32_t dest,
const uint8_t *src, size_t len); const uint8_t *src, size_t len);
static bool nrf51_cmd_erase_all(target *t); static bool nrf51_cmd_erase_all(target *t);
@ -135,11 +135,11 @@ static const uint16_t nrf51_flash_write_stub[] = {
}; };
bool nrf51_probe(struct target_s *target) bool nrf51_probe(target *t)
{ {
target->idcode = target_mem_read32(target, NRF51_FICR_CONFIGID) & 0xFFFF; t->idcode = target_mem_read32(t, NRF51_FICR_CONFIGID) & 0xFFFF;
switch (target->idcode) { switch (t->idcode) {
case 0x001D: case 0x001D:
case 0x002A: case 0x002A:
case 0x0044: case 0x0044:
@ -151,43 +151,43 @@ bool nrf51_probe(struct target_s *target)
case 0x004D: case 0x004D:
case 0x0026: case 0x0026:
case 0x004C: case 0x004C:
target->driver = "Nordic nRF51"; t->driver = "Nordic nRF51";
target->xml_mem_map = nrf51_xml_memory_map; t->xml_mem_map = nrf51_xml_memory_map;
target->flash_erase = nrf51_flash_erase; t->flash_erase = nrf51_flash_erase;
target->flash_write = nrf51_flash_write; t->flash_write = nrf51_flash_write;
target_add_commands(target, nrf51_cmd_list, "nRF51"); target_add_commands(t, nrf51_cmd_list, "nRF51");
return true; return true;
} }
return false; return false;
} }
static int nrf51_flash_erase(struct target_s *target, uint32_t addr, size_t len) static int nrf51_flash_erase(target *t, uint32_t addr, size_t len)
{ {
addr &= ~(NRF51_PAGE_SIZE - 1); addr &= ~(NRF51_PAGE_SIZE - 1);
len &= ~(NRF51_PAGE_SIZE - 1); len &= ~(NRF51_PAGE_SIZE - 1);
/* Enable erase */ /* Enable erase */
target_mem_write32(target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN); target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN);
/* Poll for NVMC_READY */ /* Poll for NVMC_READY */
while (target_mem_read32(target, NRF51_NVMC_READY) == 0) while (target_mem_read32(t, NRF51_NVMC_READY) == 0)
if(target_check_error(target)) if(target_check_error(t))
return -1; return -1;
while (len) { while (len) {
if (addr == NRF51_UICR) { // Special Case if (addr == NRF51_UICR) { // Special Case
/* Write to the ERASE_UICR register to erase */ /* Write to the ERASE_UICR register to erase */
target_mem_write32(target, NRF51_NVMC_ERASEUICR, 0x1); target_mem_write32(t, NRF51_NVMC_ERASEUICR, 0x1);
} else { // Standard Flash Page } else { // Standard Flash Page
/* Write address of first word in page to erase it */ /* Write address of first word in page to erase it */
target_mem_write32(target, NRF51_NVMC_ERASEPAGE, addr); target_mem_write32(t, NRF51_NVMC_ERASEPAGE, addr);
} }
/* Poll for NVMC_READY */ /* Poll for NVMC_READY */
while (target_mem_read32(target, NRF51_NVMC_READY) == 0) while (target_mem_read32(t, NRF51_NVMC_READY) == 0)
if(target_check_error(target)) if(target_check_error(t))
return -1; return -1;
addr += NRF51_PAGE_SIZE; addr += NRF51_PAGE_SIZE;
@ -195,17 +195,17 @@ static int nrf51_flash_erase(struct target_s *target, uint32_t addr, size_t len)
} }
/* Return to read-only */ /* Return to read-only */
target_mem_write32(target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN); target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN);
/* Poll for NVMC_READY */ /* Poll for NVMC_READY */
while (target_mem_read32(target, NRF51_NVMC_READY) == 0) while (target_mem_read32(t, NRF51_NVMC_READY) == 0)
if(target_check_error(target)) if(target_check_error(t))
return -1; return -1;
return 0; return 0;
} }
static int nrf51_flash_write(struct target_s *target, uint32_t dest, static int nrf51_flash_write(target *t, uint32_t dest,
const uint8_t *src, size_t len) const uint8_t *src, size_t len)
{ {
uint32_t offset = dest % 4; uint32_t offset = dest % 4;
@ -220,26 +220,26 @@ static int nrf51_flash_write(struct target_s *target, uint32_t dest,
memcpy((uint8_t *)&data[2] + offset, src, len); memcpy((uint8_t *)&data[2] + offset, src, len);
/* Enable write */ /* Enable write */
target_mem_write32(target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_WEN); target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_WEN);
/* Poll for NVMC_READY */ /* Poll for NVMC_READY */
while (target_mem_read32(target, NRF51_NVMC_READY) == 0) while (target_mem_read32(t, NRF51_NVMC_READY) == 0)
if(target_check_error(target)) if(target_check_error(t))
return -1; return -1;
/* Write stub and data to target ram and set PC */ /* Write stub and data to target ram and set PC */
target_mem_write(target, 0x20000000, nrf51_flash_write_stub, 0x28); target_mem_write(t, 0x20000000, nrf51_flash_write_stub, 0x28);
target_mem_write(target, 0x20000028, data, len + 8); target_mem_write(t, 0x20000028, data, len + 8);
cortexm_pc_write(target, 0x20000000); cortexm_pc_write(t, 0x20000000);
if(target_check_error(target)) if(target_check_error(t))
return -1; return -1;
/* Execute the stub */ /* Execute the stub */
target_halt_resume(target, 0); target_halt_resume(t, 0);
while(!target_halt_wait(target)); while(!target_halt_wait(t));
/* Return to read-only */ /* Return to read-only */
target_mem_write32(target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN); target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN);
return 0; return 0;
} }

View File

@ -28,8 +28,8 @@
#include "command.h" #include "command.h"
#include "gdb_packet.h" #include "gdb_packet.h"
static int sam3x_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int sam3x_flash_erase(target *t, uint32_t addr, size_t len);
static int sam3x_flash_write(struct target_s *target, uint32_t dest, static int sam3x_flash_write(target *t, uint32_t dest,
const uint8_t *src, size_t len); const uint8_t *src, size_t len);
static bool sam3x_cmd_gpnvm_get(target *t); static bool sam3x_cmd_gpnvm_get(target *t);
@ -146,59 +146,59 @@ static const char sam4s_xml_memory_map[] = "<?xml version=\"1.0\"?>"
#define SAM3_PAGE_SIZE 256 #define SAM3_PAGE_SIZE 256
#define SAM4_PAGE_SIZE 512 #define SAM4_PAGE_SIZE 512
bool sam3x_probe(struct target_s *target) bool sam3x_probe(target *t)
{ {
target->idcode = target_mem_read32(target, SAM3X_CHIPID_CIDR); t->idcode = target_mem_read32(t, SAM3X_CHIPID_CIDR);
/* FIXME: Check for all variants with similar flash interface */ /* FIXME: Check for all variants with similar flash interface */
switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { switch (t->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
case CHIPID_CIDR_ARCH_SAM3XxC | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3XxC | CHIPID_CIDR_EPROC_CM3:
case CHIPID_CIDR_ARCH_SAM3XxE | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3XxE | CHIPID_CIDR_EPROC_CM3:
case CHIPID_CIDR_ARCH_SAM3XxG | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3XxG | CHIPID_CIDR_EPROC_CM3:
target->driver = "Atmel SAM3X"; t->driver = "Atmel SAM3X";
target->xml_mem_map = sam3x_xml_memory_map; t->xml_mem_map = sam3x_xml_memory_map;
target->flash_erase = sam3x_flash_erase; t->flash_erase = sam3x_flash_erase;
target->flash_write = sam3x_flash_write; t->flash_write = sam3x_flash_write;
target_add_commands(target, sam3x_cmd_list, "SAM3X"); target_add_commands(t, sam3x_cmd_list, "SAM3X");
return true; return true;
} }
target->idcode = target_mem_read32(target, SAM3N_CHIPID_CIDR); t->idcode = target_mem_read32(t, SAM3N_CHIPID_CIDR);
switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { switch (t->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
case CHIPID_CIDR_ARCH_SAM3NxA | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3NxA | CHIPID_CIDR_EPROC_CM3:
case CHIPID_CIDR_ARCH_SAM3NxB | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3NxB | CHIPID_CIDR_EPROC_CM3:
case CHIPID_CIDR_ARCH_SAM3NxC | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3NxC | CHIPID_CIDR_EPROC_CM3:
target->driver = "Atmel SAM3N"; t->driver = "Atmel SAM3N";
target->xml_mem_map = sam3n_xml_memory_map; t->xml_mem_map = sam3n_xml_memory_map;
target->flash_erase = sam3x_flash_erase; t->flash_erase = sam3x_flash_erase;
target->flash_write = sam3x_flash_write; t->flash_write = sam3x_flash_write;
target_add_commands(target, sam3x_cmd_list, "SAM3N"); target_add_commands(t, sam3x_cmd_list, "SAM3N");
return true; return true;
} }
target->idcode = target_mem_read32(target, SAM3S_CHIPID_CIDR); t->idcode = target_mem_read32(t, SAM3S_CHIPID_CIDR);
switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { switch (t->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
case CHIPID_CIDR_ARCH_SAM3SxA | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3SxA | CHIPID_CIDR_EPROC_CM3:
case CHIPID_CIDR_ARCH_SAM3SxB | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3SxB | CHIPID_CIDR_EPROC_CM3:
case CHIPID_CIDR_ARCH_SAM3SxC | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3SxC | CHIPID_CIDR_EPROC_CM3:
target->driver = "Atmel SAM3S"; t->driver = "Atmel SAM3S";
target->xml_mem_map = sam3n_xml_memory_map; t->xml_mem_map = sam3n_xml_memory_map;
target->flash_erase = sam3x_flash_erase; t->flash_erase = sam3x_flash_erase;
target->flash_write = sam3x_flash_write; t->flash_write = sam3x_flash_write;
target_add_commands(target, sam3x_cmd_list, "SAM3S"); target_add_commands(t, sam3x_cmd_list, "SAM3S");
return true; return true;
} }
target->idcode = target_mem_read32(target, SAM4S_CHIPID_CIDR); t->idcode = target_mem_read32(t, SAM4S_CHIPID_CIDR);
switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { switch (t->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
case CHIPID_CIDR_ARCH_SAM4SxA | CHIPID_CIDR_EPROC_CM4: case CHIPID_CIDR_ARCH_SAM4SxA | CHIPID_CIDR_EPROC_CM4:
case CHIPID_CIDR_ARCH_SAM4SxB | CHIPID_CIDR_EPROC_CM4: case CHIPID_CIDR_ARCH_SAM4SxB | CHIPID_CIDR_EPROC_CM4:
case CHIPID_CIDR_ARCH_SAM4SxC | CHIPID_CIDR_EPROC_CM4: case CHIPID_CIDR_ARCH_SAM4SxC | CHIPID_CIDR_EPROC_CM4:
target->driver = "Atmel SAM4S"; t->driver = "Atmel SAM4S";
target->xml_mem_map = sam4s_xml_memory_map; t->xml_mem_map = sam4s_xml_memory_map;
target->flash_erase = sam3x_flash_erase; t->flash_erase = sam3x_flash_erase;
target->flash_write = sam3x_flash_write; t->flash_write = sam3x_flash_write;
target_add_commands(target, sam3x_cmd_list, "SAM4S"); target_add_commands(t, sam3x_cmd_list, "SAM4S");
return true; return true;
} }
@ -206,27 +206,27 @@ bool sam3x_probe(struct target_s *target)
} }
static int static int
sam3x_flash_cmd(struct target_s *target, uint32_t base, uint8_t cmd, uint16_t arg) sam3x_flash_cmd(target *t, uint32_t base, uint8_t cmd, uint16_t arg)
{ {
DEBUG("%s: base = 0x%08x cmd = 0x%02X, arg = 0x%06X\n", DEBUG("%s: base = 0x%08x cmd = 0x%02X, arg = 0x%06X\n",
__func__, base, cmd, arg); __func__, base, cmd, arg);
target_mem_write32(target, EEFC_FCR(base), target_mem_write32(t, EEFC_FCR(base),
EEFC_FCR_FKEY | cmd | ((uint32_t)arg << 8)); EEFC_FCR_FKEY | cmd | ((uint32_t)arg << 8));
while (!(target_mem_read32(target, EEFC_FSR(base)) & EEFC_FSR_FRDY)) while (!(target_mem_read32(t, EEFC_FSR(base)) & EEFC_FSR_FRDY))
if(target_check_error(target)) if(target_check_error(t))
return -1; return -1;
uint32_t sr = target_mem_read32(target, EEFC_FSR(base)); uint32_t sr = target_mem_read32(t, EEFC_FSR(base));
return sr & EEFC_FSR_ERROR; return sr & EEFC_FSR_ERROR;
} }
static uint32_t static uint32_t
sam3x_flash_base(struct target_s *target, uint32_t addr, uint32_t *offset) sam3x_flash_base(target *t, uint32_t addr, uint32_t *offset)
{ {
if (strcmp(target->driver, "Atmel SAM3X") == 0) { if (strcmp(t->driver, "Atmel SAM3X") == 0) {
uint32_t half = -1; uint32_t half = -1;
switch (target->idcode & CHIPID_CIDR_NVPSIZ_MASK) { switch (t->idcode & CHIPID_CIDR_NVPSIZ_MASK) {
case CHIPID_CIDR_NVPSIZ_128K: case CHIPID_CIDR_NVPSIZ_128K:
half = 0x00090000; half = 0x00090000;
break; break;
@ -248,9 +248,9 @@ sam3x_flash_base(struct target_s *target, uint32_t addr, uint32_t *offset)
} }
} }
if (strcmp(target->driver, "Atmel SAM4S") == 0) { if (strcmp(t->driver, "Atmel SAM4S") == 0) {
uint32_t half = -1; uint32_t half = -1;
switch (target->idcode & CHIPID_CIDR_NVPSIZ_MASK) { switch (t->idcode & CHIPID_CIDR_NVPSIZ_MASK) {
case CHIPID_CIDR_NVPSIZ_128K: case CHIPID_CIDR_NVPSIZ_128K:
case CHIPID_CIDR_NVPSIZ_256K: case CHIPID_CIDR_NVPSIZ_256K:
case CHIPID_CIDR_NVPSIZ_512K: case CHIPID_CIDR_NVPSIZ_512K:
@ -281,16 +281,16 @@ sam3x_flash_base(struct target_s *target, uint32_t addr, uint32_t *offset)
return SAM3N_EEFC_BASE; return SAM3N_EEFC_BASE;
} }
static int sam3x_flash_erase(struct target_s *target, uint32_t addr, size_t len) static int sam3x_flash_erase(target *t, uint32_t addr, size_t len)
{ {
uint32_t offset; uint32_t offset;
uint32_t base = sam3x_flash_base(target, addr, &offset); uint32_t base = sam3x_flash_base(t, addr, &offset);
/* The SAM4S is the only supported device with a page erase command. /* The SAM4S is the only supported device with a page erase command.
* Erasing is done in 8-page chunks. arg[15:2] contains the page * Erasing is done in 8-page chunks. arg[15:2] contains the page
* number and arg[1:0] contains 0x1, indicating 8-page chunks. * number and arg[1:0] contains 0x1, indicating 8-page chunks.
*/ */
if (strcmp(target->driver, "Atmel SAM4S") == 0) { if (strcmp(t->driver, "Atmel SAM4S") == 0) {
unsigned chunk = offset / SAM4_PAGE_SIZE; unsigned chunk = offset / SAM4_PAGE_SIZE;
/* Fail if the start address is not 8-page-aligned. */ /* Fail if the start address is not 8-page-aligned. */
@ -302,7 +302,7 @@ static int sam3x_flash_erase(struct target_s *target, uint32_t addr, size_t len)
*/ */
while (len > 0) { while (len > 0) {
int16_t arg = chunk | 0x1; int16_t arg = chunk | 0x1;
if(sam3x_flash_cmd(target, base, EEFC_FCR_FCMD_EPA, arg)) if(sam3x_flash_cmd(t, base, EEFC_FCR_FCMD_EPA, arg))
return -1; return -1;
len -= SAM4_PAGE_SIZE * 8; len -= SAM4_PAGE_SIZE * 8;
@ -322,10 +322,10 @@ static int sam3x_flash_erase(struct target_s *target, uint32_t addr, size_t len)
memset(buf, 0xff, sizeof(buf)); memset(buf, 0xff, sizeof(buf));
/* Only do this once, since it doesn't change. */ /* Only do this once, since it doesn't change. */
target_mem_write(target, addr, buf, SAM3_PAGE_SIZE); target_mem_write(t, addr, buf, SAM3_PAGE_SIZE);
while (len) { while (len) {
if(sam3x_flash_cmd(target, base, EEFC_FCR_FCMD_EWP, chunk)) if(sam3x_flash_cmd(t, base, EEFC_FCR_FCMD_EWP, chunk))
return -1; return -1;
len -= SAM3_PAGE_SIZE; len -= SAM3_PAGE_SIZE;
@ -336,17 +336,17 @@ static int sam3x_flash_erase(struct target_s *target, uint32_t addr, size_t len)
return 0; return 0;
} }
static int sam3x_flash_write(struct target_s *target, uint32_t dest, static int sam3x_flash_write(target *t, uint32_t dest,
const uint8_t *src, size_t len) const uint8_t *src, size_t len)
{ {
unsigned page_size; unsigned page_size;
if (strcmp(target->driver, "Atmel SAM4S") == 0) { if (strcmp(t->driver, "Atmel SAM4S") == 0) {
page_size = SAM4_PAGE_SIZE; page_size = SAM4_PAGE_SIZE;
} else { } else {
page_size = SAM3_PAGE_SIZE; page_size = SAM3_PAGE_SIZE;
} }
uint32_t offset; uint32_t offset;
uint32_t base = sam3x_flash_base(target, dest, &offset); uint32_t base = sam3x_flash_base(t, dest, &offset);
uint8_t buf[page_size]; uint8_t buf[page_size];
unsigned first_chunk = offset / page_size; unsigned first_chunk = offset / page_size;
unsigned last_chunk = (offset + len - 1) / page_size; unsigned last_chunk = (offset + len - 1) / page_size;
@ -380,8 +380,8 @@ static int sam3x_flash_write(struct target_s *target, uint32_t dest,
src += page_size; src += page_size;
} }
target_mem_write(target, dest, buf, page_size); target_mem_write(t, dest, buf, page_size);
if(sam3x_flash_cmd(target, base, EEFC_FCR_FCMD_WP, chunk)) if(sam3x_flash_cmd(t, base, EEFC_FCR_FCMD_WP, chunk))
return -1; return -1;
} }

View File

@ -40,8 +40,8 @@
#include "gdb_packet.h" #include "gdb_packet.h"
#include "cortexm.h" #include "cortexm.h"
static int samd_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int samd_flash_erase(target *t, uint32_t addr, size_t len);
static int samd_flash_write(struct target_s *target, uint32_t dest, static int samd_flash_write(target *t, uint32_t dest,
const uint8_t *src, size_t len); const uint8_t *src, size_t len);
static bool samd_cmd_erase_all(target *t); static bool samd_cmd_erase_all(target *t);
@ -162,28 +162,28 @@ static const char samd_xml_memory_map[] = "<?xml version=\"1.0\"?>"
/** /**
* Reads the SAM D20 Peripheral ID * Reads the SAM D20 Peripheral ID
*/ */
uint64_t samd_read_pid(struct target_s *target) uint64_t samd_read_pid(target *t)
{ {
uint64_t pid = 0; uint64_t pid = 0;
uint8_t i, j; uint8_t i, j;
/* Five PID registers to read LSB first */ /* Five PID registers to read LSB first */
for (i = 0, j = 0; i < 5; i++, j += 8) for (i = 0, j = 0; i < 5; i++, j += 8)
pid |= (target_mem_read32(target, SAMD_DSU_PID(i)) & 0xFF) << j; pid |= (target_mem_read32(t, SAMD_DSU_PID(i)) & 0xFF) << j;
return pid; return pid;
} }
/** /**
* Reads the SAM D20 Component ID * Reads the SAM D20 Component ID
*/ */
uint32_t samd_read_cid(struct target_s *target) uint32_t samd_read_cid(target *t)
{ {
uint64_t cid = 0; uint64_t cid = 0;
uint8_t i, j; uint8_t i, j;
/* Four CID registers to read LSB first */ /* Four CID registers to read LSB first */
for (i = 0, j = 0; i < 4; i++, j += 8) for (i = 0, j = 0; i < 4; i++, j += 8)
cid |= (target_mem_read32(target, SAMD_DSU_CID(i)) & 0xFF) << j; cid |= (target_mem_read32(t, SAMD_DSU_CID(i)) & 0xFF) << j;
return cid; return cid;
} }
@ -193,7 +193,7 @@ uint32_t samd_read_cid(struct target_s *target)
* removes the target from extended reset where required. * removes the target from extended reset where required.
*/ */
static void static void
samd_reset(struct target_s *target) samd_reset(target *t)
{ {
/** /**
* SRST is not asserted here as it appears to reset the adiv5 * SRST is not asserted here as it appears to reset the adiv5
@ -212,31 +212,30 @@ samd_reset(struct target_s *target)
*/ */
/* Read DHCSR here to clear S_RESET_ST bit before reset */ /* Read DHCSR here to clear S_RESET_ST bit before reset */
target_mem_read32(target, CORTEXM_DHCSR); target_mem_read32(t, CORTEXM_DHCSR);
/* Request system reset from NVIC: SRST doesn't work correctly */ /* Request system reset from NVIC: SRST doesn't work correctly */
/* This could be VECTRESET: 0x05FA0001 (reset only core) /* This could be VECTRESET: 0x05FA0001 (reset only core)
* or SYSRESETREQ: 0x05FA0004 (system reset) * or SYSRESETREQ: 0x05FA0004 (system reset)
*/ */
target_mem_write32(target, CORTEXM_AIRCR, target_mem_write32(t, CORTEXM_AIRCR,
CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ); CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ);
/* Exit extended reset */ /* Exit extended reset */
if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) & if (target_mem_read32(t, SAMD_DSU_CTRLSTAT) &
SAMD_STATUSA_CRSTEXT) { SAMD_STATUSA_CRSTEXT) {
/* Write bit to clear from extended reset */ /* Write bit to clear from extended reset */
target_mem_write32(target, SAMD_DSU_CTRLSTAT, target_mem_write32(t, SAMD_DSU_CTRLSTAT, SAMD_STATUSA_CRSTEXT);
SAMD_STATUSA_CRSTEXT);
} }
/* Poll for release from reset */ /* Poll for release from reset */
while (target_mem_read32(target, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST); while (target_mem_read32(t, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST);
/* Reset DFSR flags */ /* Reset DFSR flags */
target_mem_write32(target, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); target_mem_write32(t, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL);
/* Clear any target errors */ /* Clear any target errors */
target_check_error(target); target_check_error(t);
} }
/** /**
@ -246,16 +245,16 @@ samd_reset(struct target_s *target)
* Only required for SAM D20 _Revision B_ Silicon * Only required for SAM D20 _Revision B_ Silicon
*/ */
static void static void
samd20_revB_detach(struct target_s *target) samd20_revB_detach(target *t)
{ {
cortexm_detach(target); cortexm_detach(t);
/* ---- Additional ---- */ /* ---- Additional ---- */
/* Exit extended reset */ /* Exit extended reset */
if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) & if (target_mem_read32(t, SAMD_DSU_CTRLSTAT) &
SAMD_STATUSA_CRSTEXT) { SAMD_STATUSA_CRSTEXT) {
/* Write bit to clear from extended reset */ /* Write bit to clear from extended reset */
target_mem_write32(target, SAMD_DSU_CTRLSTAT, target_mem_write32(t, SAMD_DSU_CTRLSTAT,
SAMD_STATUSA_CRSTEXT); SAMD_STATUSA_CRSTEXT);
} }
} }
@ -267,16 +266,15 @@ samd20_revB_detach(struct target_s *target)
* Only required for SAM D20 _Revision B_ Silicon * Only required for SAM D20 _Revision B_ Silicon
*/ */
static void static void
samd20_revB_halt_resume(struct target_s *target, bool step) samd20_revB_halt_resume(target *t, bool step)
{ {
cortexm_halt_resume(target, step); cortexm_halt_resume(t, step);
/* ---- Additional ---- */ /* ---- Additional ---- */
/* Exit extended reset */ /* Exit extended reset */
if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) & if (target_mem_read32(t, SAMD_DSU_CTRLSTAT) & SAMD_STATUSA_CRSTEXT) {
SAMD_STATUSA_CRSTEXT) {
/* Write bit to clear from extended reset */ /* Write bit to clear from extended reset */
target_mem_write32(target, SAMD_DSU_CTRLSTAT, target_mem_write32(t, SAMD_DSU_CTRLSTAT,
SAMD_STATUSA_CRSTEXT); SAMD_STATUSA_CRSTEXT);
} }
} }
@ -290,7 +288,7 @@ samd20_revB_halt_resume(struct target_s *target, bool step)
* rescue the device. * rescue the device.
*/ */
static bool static bool
samd_protected_attach(struct target_s *target) samd_protected_attach(target *t)
{ {
/** /**
* TODO: Notify the user that we're not really attached and * TODO: Notify the user that we're not really attached and
@ -299,7 +297,7 @@ samd_protected_attach(struct target_s *target)
*/ */
/* Patch back in the normal cortexm attach for next time */ /* Patch back in the normal cortexm attach for next time */
target->attach = cortexm_attach; t->attach = cortexm_attach;
/* Allow attach this time */ /* Allow attach this time */
return true; return true;
@ -365,10 +363,10 @@ struct samd_descr samd_parse_device_id(uint32_t did)
char variant_string[40]; char variant_string[40];
bool samd_probe(struct target_s *target) bool samd_probe(target *t)
{ {
uint32_t cid = samd_read_cid(target); uint32_t cid = samd_read_cid(t);
uint32_t pid = samd_read_pid(target); uint32_t pid = samd_read_pid(t);
/* Check the ARM Coresight Component and Perhiperal IDs */ /* Check the ARM Coresight Component and Perhiperal IDs */
if ((cid != SAMD_CID_VALUE) || if ((cid != SAMD_CID_VALUE) ||
@ -376,14 +374,13 @@ bool samd_probe(struct target_s *target)
return false; return false;
/* Read the Device ID */ /* Read the Device ID */
uint32_t did = target_mem_read32(target, SAMD_DSU_DID); uint32_t did = target_mem_read32(t, SAMD_DSU_DID);
/* If the Device ID matches */ /* If the Device ID matches */
if ((did & SAMD_DID_MASK) != SAMD_DID_CONST_VALUE) if ((did & SAMD_DID_MASK) != SAMD_DID_CONST_VALUE)
return false; return false;
uint32_t ctrlstat = target_mem_read32(target, uint32_t ctrlstat = target_mem_read32(t, SAMD_DSU_CTRLSTAT);
SAMD_DSU_CTRLSTAT);
struct samd_descr samd = samd_parse_device_id(did); struct samd_descr samd = samd_parse_device_id(did);
/* Protected? */ /* Protected? */
@ -403,8 +400,8 @@ bool samd_probe(struct target_s *target)
} }
/* Setup Target */ /* Setup Target */
target->driver = variant_string; t->driver = variant_string;
target->reset = samd_reset; t->reset = samd_reset;
if (samd.series == 20 && samd.revision == 'B') { if (samd.series == 20 && samd.revision == 'B') {
/** /**
@ -412,8 +409,8 @@ bool samd_probe(struct target_s *target)
* extended reset. Appears to be * extended reset. Appears to be
* related to Errata 35.4.1 ref 12015 * related to Errata 35.4.1 ref 12015
*/ */
target->detach = samd20_revB_detach; t->detach = samd20_revB_detach;
target->halt_resume = samd20_revB_halt_resume; t->halt_resume = samd20_revB_halt_resume;
} }
if (protected) { if (protected) {
/** /**
@ -423,23 +420,23 @@ bool samd_probe(struct target_s *target)
* attach on a temporary basis so they * attach on a temporary basis so they
* can rescue the device. * can rescue the device.
*/ */
target->attach = samd_protected_attach; t->attach = samd_protected_attach;
} }
target->xml_mem_map = samd_xml_memory_map; t->xml_mem_map = samd_xml_memory_map;
target->flash_erase = samd_flash_erase; t->flash_erase = samd_flash_erase;
target->flash_write = samd_flash_write; t->flash_write = samd_flash_write;
target_add_commands(target, samd_cmd_list, "SAMD"); target_add_commands(t, samd_cmd_list, "SAMD");
/* If we're not in reset here */ /* If we're not in reset here */
if (!connect_assert_srst) { if (!connect_assert_srst) {
/* We'll have to release the target from /* We'll have to release the target from
* extended reset to make attach possible */ * extended reset to make attach possible */
if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) & if (target_mem_read32(t, SAMD_DSU_CTRLSTAT) &
SAMD_STATUSA_CRSTEXT) { SAMD_STATUSA_CRSTEXT) {
/* Write bit to clear from extended reset */ /* Write bit to clear from extended reset */
target_mem_write32(target, SAMD_DSU_CTRLSTAT, target_mem_write32(t, SAMD_DSU_CTRLSTAT,
SAMD_STATUSA_CRSTEXT); SAMD_STATUSA_CRSTEXT);
} }
} }
@ -450,23 +447,23 @@ bool samd_probe(struct target_s *target)
/** /**
* Temporary (until next reset) flash memory locking / unlocking * Temporary (until next reset) flash memory locking / unlocking
*/ */
static void samd_lock_current_address(struct target_s *target) static void samd_lock_current_address(target *t)
{ {
/* Issue the unlock command */ /* Issue the unlock command */
target_mem_write32(target, SAMD_NVMC_CTRLA, target_mem_write32(t, SAMD_NVMC_CTRLA,
SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_LOCK); SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_LOCK);
} }
static void samd_unlock_current_address(struct target_s *target) static void samd_unlock_current_address(target *t)
{ {
/* Issue the unlock command */ /* Issue the unlock command */
target_mem_write32(target, SAMD_NVMC_CTRLA, target_mem_write32(t, SAMD_NVMC_CTRLA,
SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_UNLOCK); SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_UNLOCK);
} }
/** /**
* Erase flash row by row * Erase flash row by row
*/ */
static int samd_flash_erase(struct target_s *target, uint32_t addr, size_t len) static int samd_flash_erase(target *t, uint32_t addr, size_t len)
{ {
addr &= ~(SAMD_ROW_SIZE - 1); addr &= ~(SAMD_ROW_SIZE - 1);
len &= ~(SAMD_ROW_SIZE - 1); len &= ~(SAMD_ROW_SIZE - 1);
@ -474,21 +471,21 @@ static int samd_flash_erase(struct target_s *target, uint32_t addr, size_t len)
while (len) { while (len) {
/* Write address of first word in row to erase it */ /* Write address of first word in row to erase it */
/* Must be shifted right for 16-bit address, see Datasheet §20.8.8 Address */ /* Must be shifted right for 16-bit address, see Datasheet §20.8.8 Address */
target_mem_write32(target, SAMD_NVMC_ADDRESS, addr >> 1); target_mem_write32(t, SAMD_NVMC_ADDRESS, addr >> 1);
/* Unlock */ /* Unlock */
samd_unlock_current_address(target); samd_unlock_current_address(t);
/* Issue the erase command */ /* Issue the erase command */
target_mem_write32(target, SAMD_NVMC_CTRLA, target_mem_write32(t, SAMD_NVMC_CTRLA,
SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEROW); SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEROW);
/* Poll for NVM Ready */ /* Poll for NVM Ready */
while ((target_mem_read32(target, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0)
if (target_check_error(target)) if (target_check_error(t))
return -1; return -1;
/* Lock */ /* Lock */
samd_lock_current_address(target); samd_lock_current_address(t);
addr += SAMD_ROW_SIZE; addr += SAMD_ROW_SIZE;
len -= SAMD_ROW_SIZE; len -= SAMD_ROW_SIZE;
@ -500,7 +497,7 @@ static int samd_flash_erase(struct target_s *target, uint32_t addr, size_t len)
/** /**
* Write flash page by page * Write flash page by page
*/ */
static int samd_flash_write(struct target_s *target, uint32_t dest, static int samd_flash_write(target *t, uint32_t dest,
const uint8_t *src, size_t len) const uint8_t *src, size_t len)
{ {
/* Find the size of our 32-bit data buffer */ /* Find the size of our 32-bit data buffer */
@ -529,26 +526,26 @@ static int samd_flash_write(struct target_s *target, uint32_t dest,
length = MIN(end + 4, next_page) - addr; length = MIN(end + 4, next_page) - addr;
/* Write within a single page. This may be part or all of the page */ /* Write within a single page. This may be part or all of the page */
target_mem_write(target, addr, &data[i], length); target_mem_write(t, addr, &data[i], length);
addr += length; i += (length >> 2); addr += length; i += (length >> 2);
/* If MANW=0 (default) we may have triggered an automatic /* If MANW=0 (default) we may have triggered an automatic
* write. Ignore this */ * write. Ignore this */
/* Unlock */ /* Unlock */
samd_unlock_current_address(target); samd_unlock_current_address(t);
/* Issue the write page command */ /* Issue the write page command */
target_mem_write32(target, SAMD_NVMC_CTRLA, target_mem_write32(t, SAMD_NVMC_CTRLA,
SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEPAGE); SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEPAGE);
/* Poll for NVM Ready */ /* Poll for NVM Ready */
while ((target_mem_read32(target, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0)
if (target_check_error(target)) if (target_check_error(t))
return -1; return -1;
/* Lock */ /* Lock */
samd_lock_current_address(target); samd_lock_current_address(t);
} }
return 0; return 0;

View File

@ -46,11 +46,11 @@ const struct command_s stm32f1_cmd_list[] = {
}; };
static int stm32md_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int stm32md_flash_erase(target *t, uint32_t addr, size_t len);
static int stm32hd_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int stm32hd_flash_erase(target *t, uint32_t addr, size_t len);
static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, size_t len, static int stm32f1_flash_erase(target *t, uint32_t addr, size_t len,
uint32_t pagesize); uint32_t pagesize);
static int stm32f1_flash_write(struct target_s *target, uint32_t dest, static int stm32f1_flash_write(target *t, uint32_t dest,
const uint8_t *src, size_t len); const uint8_t *src, size_t len);
static const char stm32f1_driver_str[] = "STM32, Medium density."; static const char stm32f1_driver_str[] = "STM32, Medium density.";
@ -127,66 +127,66 @@ static const uint16_t stm32f1_flash_write_stub[] = {
#define SRAM_BASE 0x20000000 #define SRAM_BASE 0x20000000
#define STUB_BUFFER_BASE ALIGN(SRAM_BASE + sizeof(stm32f1_flash_write_stub), 4) #define STUB_BUFFER_BASE ALIGN(SRAM_BASE + sizeof(stm32f1_flash_write_stub), 4)
bool stm32f1_probe(struct target_s *target) bool stm32f1_probe(target *t)
{ {
target->idcode = target_mem_read32(target, DBGMCU_IDCODE) & 0xfff; t->idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xfff;
switch(target->idcode) { switch(t->idcode) {
case 0x410: /* Medium density */ case 0x410: /* Medium density */
case 0x412: /* Low denisty */ case 0x412: /* Low denisty */
case 0x420: /* Value Line, Low-/Medium density */ case 0x420: /* Value Line, Low-/Medium density */
target->driver = stm32f1_driver_str; t->driver = stm32f1_driver_str;
target->xml_mem_map = stm32f1_xml_memory_map; t->xml_mem_map = stm32f1_xml_memory_map;
target->flash_erase = stm32md_flash_erase; t->flash_erase = stm32md_flash_erase;
target->flash_write = stm32f1_flash_write; t->flash_write = stm32f1_flash_write;
target_add_commands(target, stm32f1_cmd_list, "STM32 LD/MD"); target_add_commands(t, stm32f1_cmd_list, "STM32 LD/MD");
return true; return true;
case 0x414: /* High density */ case 0x414: /* High density */
case 0x418: /* Connectivity Line */ case 0x418: /* Connectivity Line */
case 0x428: /* Value Line, High Density */ case 0x428: /* Value Line, High Density */
target->driver = stm32hd_driver_str; t->driver = stm32hd_driver_str;
target->xml_mem_map = stm32hd_xml_memory_map; t->xml_mem_map = stm32hd_xml_memory_map;
target->flash_erase = stm32hd_flash_erase; t->flash_erase = stm32hd_flash_erase;
target->flash_write = stm32f1_flash_write; t->flash_write = stm32f1_flash_write;
target_add_commands(target, stm32f1_cmd_list, "STM32 HD/CL"); target_add_commands(t, stm32f1_cmd_list, "STM32 HD/CL");
return true; return true;
case 0x422: /* STM32F30x */ case 0x422: /* STM32F30x */
case 0x432: /* STM32F37x */ case 0x432: /* STM32F37x */
target->driver = stm32f3_driver_str; t->driver = stm32f3_driver_str;
target->xml_mem_map = stm32hd_xml_memory_map; t->xml_mem_map = stm32hd_xml_memory_map;
target->flash_erase = stm32hd_flash_erase; t->flash_erase = stm32hd_flash_erase;
target->flash_write = stm32f1_flash_write; t->flash_write = stm32f1_flash_write;
target_add_commands(target, stm32f1_cmd_list, "STM32F3"); target_add_commands(t, stm32f1_cmd_list, "STM32F3");
return true; return true;
} }
target->idcode = target_mem_read32(target, DBGMCU_IDCODE_F0) & 0xfff; t->idcode = target_mem_read32(t, DBGMCU_IDCODE_F0) & 0xfff;
switch(target->idcode) { switch(t->idcode) {
case 0x444: /* STM32F03 RM0091 Rev.7 */ case 0x444: /* STM32F03 RM0091 Rev.7 */
case 0x445: /* STM32F04 RM0091 Rev.7 */ case 0x445: /* STM32F04 RM0091 Rev.7 */
case 0x440: /* STM32F05 RM0091 Rev.7 */ case 0x440: /* STM32F05 RM0091 Rev.7 */
case 0x448: /* STM32F07 RM0091 Rev.7 */ case 0x448: /* STM32F07 RM0091 Rev.7 */
case 0x442: /* STM32F09 RM0091 Rev.7 */ case 0x442: /* STM32F09 RM0091 Rev.7 */
switch(target->idcode) { switch(t->idcode) {
case 0x444: /* STM32F03 */ case 0x444: /* STM32F03 */
target->driver = stm32f03_driver_str; t->driver = stm32f03_driver_str;
break; break;
case 0x445: /* STM32F04 */ case 0x445: /* STM32F04 */
target->driver = stm32f04_driver_str; t->driver = stm32f04_driver_str;
break; break;
case 0x440: /* STM32F05 */ case 0x440: /* STM32F05 */
target->driver = stm32f05_driver_str; t->driver = stm32f05_driver_str;
break; break;
case 0x448: /* STM32F07 */ case 0x448: /* STM32F07 */
target->driver = stm32f07_driver_str; t->driver = stm32f07_driver_str;
break; break;
case 0x442: /* STM32F09 */ case 0x442: /* STM32F09 */
target->driver = stm32f09_driver_str; t->driver = stm32f09_driver_str;
break; break;
} }
target->xml_mem_map = stm32f1_xml_memory_map; t->xml_mem_map = stm32f1_xml_memory_map;
target->flash_erase = stm32md_flash_erase; t->flash_erase = stm32md_flash_erase;
target->flash_write = stm32f1_flash_write; t->flash_write = stm32f1_flash_write;
target_add_commands(target, stm32f1_cmd_list, "STM32F0"); target_add_commands(t, stm32f1_cmd_list, "STM32F0");
return true; return true;
} }
@ -199,7 +199,7 @@ static void stm32f1_flash_unlock(target *t)
target_mem_write32(t, FLASH_KEYR, KEY2); target_mem_write32(t, FLASH_KEYR, KEY2);
} }
static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, static int stm32f1_flash_erase(target *t, uint32_t addr,
size_t len, uint32_t pagesize) size_t len, uint32_t pagesize)
{ {
uint16_t sr; uint16_t sr;
@ -207,19 +207,19 @@ static int stm32f1_flash_erase(struct target_s *target, uint32_t addr,
addr &= ~(pagesize - 1); addr &= ~(pagesize - 1);
len = (len + pagesize - 1) & ~(pagesize - 1); len = (len + pagesize - 1) & ~(pagesize - 1);
stm32f1_flash_unlock(target); stm32f1_flash_unlock(t);
while(len) { while(len) {
/* Flash page erase instruction */ /* Flash page erase instruction */
target_mem_write32(target, FLASH_CR, FLASH_CR_PER); target_mem_write32(t, FLASH_CR, FLASH_CR_PER);
/* write address to FMA */ /* write address to FMA */
target_mem_write32(target, FLASH_AR, addr); target_mem_write32(t, FLASH_AR, addr);
/* Flash page erase start instruction */ /* Flash page erase start instruction */
target_mem_write32(target, FLASH_CR, FLASH_CR_STRT | FLASH_CR_PER); target_mem_write32(t, FLASH_CR, FLASH_CR_STRT | FLASH_CR_PER);
/* Read FLASH_SR to poll for BSY bit */ /* Read FLASH_SR to poll for BSY bit */
while (target_mem_read32(target, FLASH_SR) & FLASH_SR_BSY) while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY)
if(target_check_error(target)) if(target_check_error(t))
return -1; return -1;
len -= pagesize; len -= pagesize;
@ -227,24 +227,24 @@ static int stm32f1_flash_erase(struct target_s *target, uint32_t addr,
} }
/* Check for error */ /* Check for error */
sr = target_mem_read32(target, FLASH_SR); sr = target_mem_read32(t, FLASH_SR);
if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP)) if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP))
return -1; return -1;
return 0; return 0;
} }
static int stm32hd_flash_erase(struct target_s *target, uint32_t addr, size_t len) static int stm32hd_flash_erase(target *t, uint32_t addr, size_t len)
{ {
return stm32f1_flash_erase(target, addr, len, 0x800); return stm32f1_flash_erase(t, addr, len, 0x800);
} }
static int stm32md_flash_erase(struct target_s *target, uint32_t addr, size_t len) static int stm32md_flash_erase(target *t, uint32_t addr, size_t len)
{ {
return stm32f1_flash_erase(target, addr, len, 0x400); return stm32f1_flash_erase(t, addr, len, 0x400);
} }
static int stm32f1_flash_write(struct target_s *target, uint32_t dest, static int stm32f1_flash_write(target *t, uint32_t dest,
const uint8_t *src, size_t len) const uint8_t *src, size_t len)
{ {
uint32_t offset = dest % 4; uint32_t offset = dest % 4;
@ -256,8 +256,8 @@ static int stm32f1_flash_write(struct target_s *target, uint32_t dest,
memcpy((uint8_t *)data + offset, src, len); memcpy((uint8_t *)data + offset, src, len);
/* Write stub and data to target ram and set PC */ /* Write stub and data to target ram and set PC */
target_mem_write(target, STUB_BUFFER_BASE, (void*)data, sizeof(data)); target_mem_write(t, STUB_BUFFER_BASE, (void*)data, sizeof(data));
return cortexm_run_stub(target, SRAM_BASE, stm32f1_flash_write_stub, return cortexm_run_stub(t, SRAM_BASE, stm32f1_flash_write_stub,
sizeof(stm32f1_flash_write_stub), sizeof(stm32f1_flash_write_stub),
dest - offset, STUB_BUFFER_BASE, sizeof(data), dest - offset, STUB_BUFFER_BASE, sizeof(data),
0); 0);

View File

@ -47,8 +47,8 @@ const struct command_s stm32f4_cmd_list[] = {
}; };
static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int stm32f4_flash_erase(target *t, uint32_t addr, size_t len);
static int stm32f4_flash_write(struct target_s *target, uint32_t dest, static int stm32f4_flash_write(target *t, uint32_t dest,
const uint8_t *src, size_t len); const uint8_t *src, size_t len);
static const char stm32f4_driver_str[] = "STM32F4xx"; static const char stm32f4_driver_str[] = "STM32F4xx";
@ -127,11 +127,11 @@ static const uint16_t stm32f4_flash_write_stub[] = {
#define SRAM_BASE 0x20000000 #define SRAM_BASE 0x20000000
#define STUB_BUFFER_BASE ALIGN(SRAM_BASE + sizeof(stm32f4_flash_write_stub), 4) #define STUB_BUFFER_BASE ALIGN(SRAM_BASE + sizeof(stm32f4_flash_write_stub), 4)
bool stm32f4_probe(struct target_s *target) bool stm32f4_probe(target *t)
{ {
uint32_t idcode; uint32_t idcode;
idcode = target_mem_read32(target, DBGMCU_IDCODE); idcode = target_mem_read32(t, DBGMCU_IDCODE);
switch(idcode & 0xFFF) { switch(idcode & 0xFFF) {
case 0x411: /* Documented to be 0x413! This is what I read... */ case 0x411: /* Documented to be 0x413! This is what I read... */
case 0x413: /* F407VGT6 */ case 0x413: /* F407VGT6 */
@ -139,11 +139,11 @@ bool stm32f4_probe(struct target_s *target)
case 0x423: /* F401 B/C RM0368 Rev.3 */ case 0x423: /* F401 B/C RM0368 Rev.3 */
case 0x431: /* F411 RM0383 Rev.4 */ case 0x431: /* F411 RM0383 Rev.4 */
case 0x433: /* F401 D/E RM0368 Rev.3 */ case 0x433: /* F401 D/E RM0368 Rev.3 */
target->xml_mem_map = stm32f4_xml_memory_map; t->xml_mem_map = stm32f4_xml_memory_map;
target->driver = stm32f4_driver_str; t->driver = stm32f4_driver_str;
target->flash_erase = stm32f4_flash_erase; t->flash_erase = stm32f4_flash_erase;
target->flash_write = stm32f4_flash_write; t->flash_write = stm32f4_flash_write;
target_add_commands(target, stm32f4_cmd_list, "STM32F4"); target_add_commands(t, stm32f4_cmd_list, "STM32F4");
return true; return true;
} }
return false; return false;
@ -158,7 +158,7 @@ static void stm32f4_flash_unlock(target *t)
} }
} }
static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t len) static int stm32f4_flash_erase(target *t, uint32_t addr, size_t len)
{ {
uint16_t sr; uint16_t sr;
uint32_t cr; uint32_t cr;
@ -166,7 +166,7 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t le
addr &= 0x07FFC000; addr &= 0x07FFC000;
stm32f4_flash_unlock(target); stm32f4_flash_unlock(t);
while(len) { while(len) {
if (addr < 0x10000) { /* Sector 0..3 */ if (addr < 0x10000) { /* Sector 0..3 */
@ -183,13 +183,13 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t le
} }
cr |= FLASH_CR_EOPIE | FLASH_CR_ERRIE | FLASH_CR_SER; cr |= FLASH_CR_EOPIE | FLASH_CR_ERRIE | FLASH_CR_SER;
/* Flash page erase instruction */ /* Flash page erase instruction */
target_mem_write32(target, FLASH_CR, cr); target_mem_write32(t, FLASH_CR, cr);
/* write address to FMA */ /* write address to FMA */
target_mem_write32(target, FLASH_CR, cr | FLASH_CR_STRT); target_mem_write32(t, FLASH_CR, cr | FLASH_CR_STRT);
/* Read FLASH_SR to poll for BSY bit */ /* Read FLASH_SR to poll for BSY bit */
while(target_mem_read32(target, FLASH_SR) & FLASH_SR_BSY) while(target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY)
if(target_check_error(target)) if(target_check_error(t))
return -1; return -1;
len -= pagesize; len -= pagesize;
@ -197,14 +197,14 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t le
} }
/* Check for error */ /* Check for error */
sr = target_mem_read32(target, FLASH_SR); sr = target_mem_read32(t, FLASH_SR);
if(sr & SR_ERROR_MASK) if(sr & SR_ERROR_MASK)
return -1; return -1;
return 0; return 0;
} }
static int stm32f4_flash_write(struct target_s *target, uint32_t dest, static int stm32f4_flash_write(target *t, uint32_t dest,
const uint8_t *src, size_t len) const uint8_t *src, size_t len)
{ {
uint32_t offset = dest % 4; uint32_t offset = dest % 4;
@ -216,8 +216,8 @@ static int stm32f4_flash_write(struct target_s *target, uint32_t dest,
memcpy((uint8_t *)data + offset, src, len); memcpy((uint8_t *)data + offset, src, len);
/* Write buffer to target ram call stub */ /* Write buffer to target ram call stub */
target_mem_write(target, STUB_BUFFER_BASE, data, sizeof(data)); target_mem_write(t, STUB_BUFFER_BASE, data, sizeof(data));
return cortexm_run_stub(target, SRAM_BASE, stm32f4_flash_write_stub, return cortexm_run_stub(t, SRAM_BASE, stm32f4_flash_write_stub,
sizeof(stm32f4_flash_write_stub), sizeof(stm32f4_flash_write_stub),
dest - offset, STUB_BUFFER_BASE, sizeof(data), dest - offset, STUB_BUFFER_BASE, sizeof(data),
0); 0);

View File

@ -123,37 +123,25 @@
static int inhibit_stubs; /* Local option to force non-stub flash IO */ static int inhibit_stubs; /* Local option to force non-stub flash IO */
static int stm32lx_nvm_erase(struct target_s* target, static int stm32lx_nvm_erase(target *t, uint32_t addr, size_t len);
uint32_t addr, size_t len); static int stm32lx_nvm_write(target *t, uint32_t dest, const uint8_t* src,
static int stm32lx_nvm_write(struct target_s* target,
uint32_t destination,
const uint8_t* source,
size_t size); size_t size);
static int stm32lx_nvm_prog_erase(struct target_s* target, static int stm32lx_nvm_prog_erase(target *t, uint32_t addr, size_t len);
uint32_t addr, size_t len); static int stm32lx_nvm_prog_write(target *t, uint32_t dest, const uint8_t* src,
static int stm32lx_nvm_prog_write(struct target_s* target,
uint32_t destination,
const uint8_t* source,
size_t size); size_t size);
static int stm32lx_nvm_prog_erase_stubbed(struct target_s* target, static int stm32lx_nvm_prog_erase_stubbed(target *t, uint32_t addr, size_t len);
uint32_t addr, size_t len); static int stm32lx_nvm_prog_write_stubbed(target *t, uint32_t dest,
static int stm32lx_nvm_prog_write_stubbed(struct target_s* target, const uint8_t* src, size_t size);
uint32_t destination,
const uint8_t* source,
size_t size);
static int stm32lx_nvm_data_erase(struct target_s* target, static int stm32lx_nvm_data_erase(target *t, uint32_t addr, size_t len);
uint32_t addr, size_t len); static int stm32lx_nvm_data_write(target *t, uint32_t dest,
static int stm32lx_nvm_data_write(struct target_s* target, const uint8_t* src, size_t size);
uint32_t destination,
const uint8_t* source,
size_t size);
static bool stm32lx_cmd_option (target* t, int argc, char** argv); static bool stm32lx_cmd_option(target* t, int argc, char** argv);
static bool stm32lx_cmd_eeprom (target* t, int argc, char** argv); static bool stm32lx_cmd_eeprom(target* t, int argc, char** argv);
static bool stm32lx_cmd_stubs (target* t, int argc, char** argv); static bool stm32lx_cmd_stubs(target* t, int argc, char** argv);
static const struct command_s stm32lx_cmd_list[] = { static const struct command_s stm32lx_cmd_list[] = {
{ "stubs", (cmd_handler) stm32lx_cmd_stubs, { "stubs", (cmd_handler) stm32lx_cmd_stubs,
@ -216,9 +204,9 @@ static const uint16_t stm32l0_nvm_prog_erase_stub [] = {
#include "../flashstub/stm32l05x-nvm-prog-erase.stub" #include "../flashstub/stm32l05x-nvm-prog-erase.stub"
}; };
static uint32_t stm32lx_nvm_prog_page_size(struct target_s* target) static uint32_t stm32lx_nvm_prog_page_size(target *t)
{ {
switch (target->idcode) { switch (t->idcode) {
case 0x417: /* STM32L0xx */ case 0x417: /* STM32L0xx */
return STM32L0_NVM_PROG_PAGE_SIZE; return STM32L0_NVM_PROG_PAGE_SIZE;
default: /* STM32L1xx */ default: /* STM32L1xx */
@ -226,9 +214,9 @@ static uint32_t stm32lx_nvm_prog_page_size(struct target_s* target)
} }
} }
static bool stm32lx_is_stm32l1(struct target_s* target) static bool stm32lx_is_stm32l1(target *t)
{ {
switch (target->idcode) { switch (t->idcode) {
case 0x417: /* STM32L0xx */ case 0x417: /* STM32L0xx */
return false; return false;
default: /* STM32L1xx */ default: /* STM32L1xx */
@ -236,9 +224,9 @@ static bool stm32lx_is_stm32l1(struct target_s* target)
} }
} }
static uint32_t stm32lx_nvm_eeprom_size(struct target_s* target) static uint32_t stm32lx_nvm_eeprom_size(target *t)
{ {
switch (target->idcode) { switch (t->idcode) {
case 0x417: /* STM32L0xx */ case 0x417: /* STM32L0xx */
return STM32L0_NVM_EEPROM_SIZE; return STM32L0_NVM_EEPROM_SIZE;
default: /* STM32L1xx */ default: /* STM32L1xx */
@ -246,9 +234,9 @@ static uint32_t stm32lx_nvm_eeprom_size(struct target_s* target)
} }
} }
static uint32_t stm32lx_nvm_phys(struct target_s* target) static uint32_t stm32lx_nvm_phys(target *t)
{ {
switch (target->idcode) { switch (t->idcode) {
case 0x417: /* STM32L0xx */ case 0x417: /* STM32L0xx */
return STM32L0_NVM_PHYS; return STM32L0_NVM_PHYS;
default: /* STM32L1xx */ default: /* STM32L1xx */
@ -256,9 +244,9 @@ static uint32_t stm32lx_nvm_phys(struct target_s* target)
} }
} }
static uint32_t stm32lx_nvm_data_page_size(struct target_s* target) static uint32_t stm32lx_nvm_data_page_size(target *t)
{ {
switch (target->idcode) { switch (t->idcode) {
case 0x417: /* STM32L0xx */ case 0x417: /* STM32L0xx */
return STM32L0_NVM_DATA_PAGE_SIZE; return STM32L0_NVM_DATA_PAGE_SIZE;
default: /* STM32L1xx */ default: /* STM32L1xx */
@ -266,9 +254,9 @@ static uint32_t stm32lx_nvm_data_page_size(struct target_s* target)
} }
} }
static uint32_t stm32lx_nvm_option_size(struct target_s* target) static uint32_t stm32lx_nvm_option_size(target *t)
{ {
switch (target->idcode) { switch (t->idcode) {
case 0x417: /* STM32L0xx */ case 0x417: /* STM32L0xx */
return STM32L0_NVM_OPT_SIZE; return STM32L0_NVM_OPT_SIZE;
default: /* STM32L1xx */ default: /* STM32L1xx */
@ -279,40 +267,38 @@ static uint32_t stm32lx_nvm_option_size(struct target_s* target)
/** Query MCU memory for an indication as to whether or not the /** Query MCU memory for an indication as to whether or not the
currently attached target is served by this module. We detect the currently attached target is served by this module. We detect the
STM32L0xx parts as well as the STM32L1xx's. */ STM32L0xx parts as well as the STM32L1xx's. */
bool stm32l0_probe(struct target_s* target) bool stm32l0_probe(target *t)
{ {
uint32_t idcode; uint32_t idcode;
idcode = target_mem_read32(target, idcode = target_mem_read32(t, STM32L1_DBGMCU_IDCODE_PHYS) & 0xfff;
STM32L1_DBGMCU_IDCODE_PHYS) & 0xfff;
switch (idcode) { switch (idcode) {
case 0x416: /* CAT. 1 device */ case 0x416: /* CAT. 1 device */
case 0x429: /* CAT. 2 device */ case 0x429: /* CAT. 2 device */
case 0x427: /* CAT. 3 device */ case 0x427: /* CAT. 3 device */
case 0x436: /* CAT. 4 device */ case 0x436: /* CAT. 4 device */
case 0x437: /* CAT. 5 device */ case 0x437: /* CAT. 5 device */
target->idcode = idcode; t->idcode = idcode;
target->driver = stm32l1_driver_str; t->driver = stm32l1_driver_str;
target->xml_mem_map = stm32l1_xml_memory_map; t->xml_mem_map = stm32l1_xml_memory_map;
target->flash_erase = stm32lx_nvm_erase; t->flash_erase = stm32lx_nvm_erase;
target->flash_write = stm32lx_nvm_write; t->flash_write = stm32lx_nvm_write;
target_add_commands(target, stm32lx_cmd_list, "STM32L1x"); target_add_commands(t, stm32lx_cmd_list, "STM32L1x");
return true; return true;
} }
idcode = target_mem_read32(target, idcode = target_mem_read32(t, STM32L0_DBGMCU_IDCODE_PHYS) & 0xfff;
STM32L0_DBGMCU_IDCODE_PHYS) & 0xfff;
switch (idcode) { switch (idcode) {
default: default:
break; break;
case 0x417: /* STM32L0x[123] & probably others */ case 0x417: /* STM32L0x[123] & probably others */
target->idcode = idcode; t->idcode = idcode;
target->driver = stm32l0_driver_str; t->driver = stm32l0_driver_str;
target->xml_mem_map = stm32l0_xml_memory_map; t->xml_mem_map = stm32l0_xml_memory_map;
target->flash_erase = stm32lx_nvm_erase; t->flash_erase = stm32lx_nvm_erase;
target->flash_write = stm32lx_nvm_write; t->flash_write = stm32lx_nvm_write;
target_add_commands(target, stm32lx_cmd_list, "STM32L0x"); target_add_commands(t, stm32lx_cmd_list, "STM32L0x");
return true; return true;
} }
@ -364,17 +350,17 @@ static bool stm32lx_nvm_opt_unlock(target *t, uint32_t nvm)
/** Erase a region of flash using a stub function. This only works /** Erase a region of flash using a stub function. This only works
when the MCU hasn't entered a fault state(see NOTES). The flash when the MCU hasn't entered a fault state(see NOTES). The flash
array is erased for all pages from addr to addr+len inclusive. */ array is erased for all pages from addr to addr+len inclusive. */
static int stm32lx_nvm_prog_erase_stubbed(struct target_s* target, static int stm32lx_nvm_prog_erase_stubbed(target *t,
uint32_t addr, size_t size) uint32_t addr, size_t size)
{ {
struct stm32lx_nvm_stub_info info; struct stm32lx_nvm_stub_info info;
const uint32_t nvm = stm32lx_nvm_phys(target); const uint32_t nvm = stm32lx_nvm_phys(t);
info.nvm = nvm; info.nvm = nvm;
info.page_size = stm32lx_nvm_prog_page_size(target); info.page_size = stm32lx_nvm_prog_page_size(t);
/* Load the stub */ /* Load the stub */
target_mem_write(target, STM32Lx_STUB_PHYS, target_mem_write(t, STM32Lx_STUB_PHYS,
&stm32l0_nvm_prog_erase_stub[0], &stm32l0_nvm_prog_erase_stub[0],
sizeof(stm32l0_nvm_prog_erase_stub)); sizeof(stm32l0_nvm_prog_erase_stub));
@ -383,21 +369,20 @@ static int stm32lx_nvm_prog_erase_stubbed(struct target_s* target,
info.size = size; info.size = size;
/* Copy parameters */ /* Copy parameters */
target_mem_write(target, STM32Lx_STUB_INFO_PHYS, target_mem_write(t, STM32Lx_STUB_INFO_PHYS, &info, sizeof(info));
&info, sizeof(info));
/* Execute stub */ /* Execute stub */
cortexm_pc_write(target, STM32Lx_STUB_PHYS); cortexm_pc_write(t, STM32Lx_STUB_PHYS);
if (target_check_error(target)) if (target_check_error(t))
return -1; return -1;
target_halt_resume(target, 0); target_halt_resume(t, 0);
while (!target_halt_wait(target)) while (!target_halt_wait(t))
; ;
{
if (target_mem_read32(target, STM32Lx_NVM_SR(nvm)) if (target_mem_read32(t, STM32Lx_NVM_SR(nvm))
& STM32Lx_NVM_SR_ERR_M) & STM32Lx_NVM_SR_ERR_M)
return -1; return -1;
}
return 0; return 0;
} }
@ -407,14 +392,14 @@ static int stm32lx_nvm_prog_erase_stubbed(struct target_s* target,
when the MCU hasn't entered a fault state. Once the MCU faults, when the MCU hasn't entered a fault state. Once the MCU faults,
this function will not succeed because the MCU will fault before this function will not succeed because the MCU will fault before
executing a single instruction in the stub. */ executing a single instruction in the stub. */
static int stm32lx_nvm_prog_write_stubbed(struct target_s* target, static int stm32lx_nvm_prog_write_stubbed(target *t,
uint32_t destination, uint32_t destination,
const uint8_t* source, const uint8_t* source,
size_t size) size_t size)
{ {
struct stm32lx_nvm_stub_info info; struct stm32lx_nvm_stub_info info;
const uint32_t nvm = stm32lx_nvm_phys(target); const uint32_t nvm = stm32lx_nvm_phys(t);
const size_t page_size = stm32lx_nvm_prog_page_size(target); const size_t page_size = stm32lx_nvm_prog_page_size(t);
/* We can only handle word aligned writes and even /* We can only handle word aligned writes and even
word-multiple ranges. The stm32lx's cannot perform word-multiple ranges. The stm32lx's cannot perform
@ -427,7 +412,7 @@ static int stm32lx_nvm_prog_write_stubbed(struct target_s* target,
info.page_size = page_size; info.page_size = page_size;
/* Load the stub */ /* Load the stub */
target_mem_write(target, STM32Lx_STUB_PHYS, target_mem_write(t, STM32Lx_STUB_PHYS,
&stm32l0_nvm_prog_write_stub[0], &stm32l0_nvm_prog_write_stub[0],
sizeof(stm32l0_nvm_prog_write_stub)); sizeof(stm32l0_nvm_prog_write_stub));
@ -451,7 +436,7 @@ static int stm32lx_nvm_prog_write_stubbed(struct target_s* target,
info.size = cb; info.size = cb;
/* Copy data to write to flash */ /* Copy data to write to flash */
target_mem_write(target, info.source, source, info.size); target_mem_write(t, info.source, source, info.size);
/* Move pointers early */ /* Move pointers early */
destination += cb; destination += cb;
@ -459,18 +444,18 @@ static int stm32lx_nvm_prog_write_stubbed(struct target_s* target,
size -= cb; size -= cb;
/* Copy parameters */ /* Copy parameters */
target_mem_write(target, STM32Lx_STUB_INFO_PHYS, target_mem_write(t, STM32Lx_STUB_INFO_PHYS,
&info, sizeof(info)); &info, sizeof(info));
/* Execute stub */ /* Execute stub */
cortexm_pc_write(target, STM32Lx_STUB_PHYS); cortexm_pc_write(t, STM32Lx_STUB_PHYS);
if (target_check_error(target)) if (target_check_error(t))
return -1; return -1;
target_halt_resume(target, 0); target_halt_resume(t, 0);
while (!target_halt_wait(target)) while (!target_halt_wait(t))
; ;
if (target_mem_read32(target, STM32Lx_NVM_SR(nvm)) if (target_mem_read32(t, STM32Lx_NVM_SR(nvm))
& STM32Lx_NVM_SR_ERR_M) & STM32Lx_NVM_SR_ERR_M)
return -1; return -1;
} }
@ -482,19 +467,19 @@ static int stm32lx_nvm_prog_write_stubbed(struct target_s* target,
/** Erase a region of NVM for STM32Lx. This is the lead function and /** Erase a region of NVM for STM32Lx. This is the lead function and
it will invoke an implementation, stubbed or not depending on the it will invoke an implementation, stubbed or not depending on the
options and the range of addresses. */ options and the range of addresses. */
static int stm32lx_nvm_erase(struct target_s* target, uint32_t addr, size_t size) static int stm32lx_nvm_erase(target *t, uint32_t addr, size_t size)
{ {
if (addr >= STM32Lx_NVM_EEPROM_PHYS) if (addr >= STM32Lx_NVM_EEPROM_PHYS)
return stm32lx_nvm_data_erase(target, addr, size); return stm32lx_nvm_data_erase(t, addr, size);
/* Use stub if not inhibited, the MCU is in a non-exceptonal state /* Use stub if not inhibited, the MCU is in a non-exceptonal state
and there is stub. */ and there is stub. */
volatile uint32_t regs[20]; volatile uint32_t regs[20];
target_regs_read(target, &regs); target_regs_read(t, &regs);
if (inhibit_stubs || (regs[16] & 0xf)) if (inhibit_stubs || (regs[16] & 0xf))
return stm32lx_nvm_prog_erase(target, addr, size); return stm32lx_nvm_prog_erase(t, addr, size);
return stm32lx_nvm_prog_erase_stubbed(target, addr, size); return stm32lx_nvm_prog_erase_stubbed(t, addr, size);
} }
@ -503,13 +488,13 @@ static int stm32lx_nvm_erase(struct target_s* target, uint32_t addr, size_t size
the options and the range of addresses. Data (EEPROM) writes the options and the range of addresses. Data (EEPROM) writes
don't have to care about alignment, but the program flash does. don't have to care about alignment, but the program flash does.
There is a fixup for unaligned program flash writes. */ There is a fixup for unaligned program flash writes. */
static int stm32lx_nvm_write(struct target_s* target, static int stm32lx_nvm_write(target *t,
uint32_t destination, uint32_t destination,
const uint8_t* source, const uint8_t* source,
size_t size) size_t size)
{ {
if (destination >= STM32Lx_NVM_EEPROM_PHYS) if (destination >= STM32Lx_NVM_EEPROM_PHYS)
return stm32lx_nvm_data_write(target, destination, source, return stm32lx_nvm_data_write(t, destination, source,
size); size);
/* Unaligned destinations. To make this feature simple to /* Unaligned destinations. To make this feature simple to
@ -532,12 +517,12 @@ static int stm32lx_nvm_write(struct target_s* target,
/* Skip stub if the MCU is in a questionable state, or if the /* Skip stub if the MCU is in a questionable state, or if the
user asks us to avoid stubs. */ user asks us to avoid stubs. */
volatile uint32_t regs[20]; volatile uint32_t regs[20];
target_regs_read(target, &regs); target_regs_read(t, &regs);
if (inhibit_stubs || (regs[16] & 0xf)) if (inhibit_stubs || (regs[16] & 0xf))
return stm32lx_nvm_prog_write(target, destination, source, return stm32lx_nvm_prog_write(t, destination, source,
size); size);
return stm32lx_nvm_prog_write_stubbed(target, destination, source, return stm32lx_nvm_prog_write_stubbed(t, destination, source,
size); size);
} }
@ -546,49 +531,46 @@ static int stm32lx_nvm_write(struct target_s* target,
interface. This is slower than stubbed versions(see NOTES). The interface. This is slower than stubbed versions(see NOTES). The
flash array is erased for all pages from addr to addr+len flash array is erased for all pages from addr to addr+len
inclusive. NVM register file address chosen from target. */ inclusive. NVM register file address chosen from target. */
static int stm32lx_nvm_prog_erase(struct target_s* target, static int stm32lx_nvm_prog_erase(target *t, uint32_t addr, size_t len)
uint32_t addr, size_t len)
{ {
const size_t page_size = stm32lx_nvm_prog_page_size(target); const size_t page_size = stm32lx_nvm_prog_page_size(t);
const uint32_t nvm = stm32lx_nvm_phys(target); const uint32_t nvm = stm32lx_nvm_phys(t);
/* Word align */ /* Word align */
len += (addr & 3); len += (addr & 3);
addr &= ~3; addr &= ~3;
if (!stm32lx_nvm_prog_data_unlock(target, nvm)) if (!stm32lx_nvm_prog_data_unlock(t, nvm))
return -1; return -1;
/* Flash page erase instruction */ /* Flash page erase instruction */
target_mem_write32(target, STM32Lx_NVM_PECR(nvm), target_mem_write32(t, STM32Lx_NVM_PECR(nvm),
STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_PROG); STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_PROG);
{ uint32_t pecr = target_mem_read32(t, STM32Lx_NVM_PECR(nvm));
uint32_t pecr = target_mem_read32(target, STM32Lx_NVM_PECR(nvm)); if ((pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE))
if ((pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) != (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE))
!= (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) return -1;
return -1;
}
/* Clear errors. Note that this only works when we wait for the NVM /* Clear errors. Note that this only works when we wait for the NVM
block to complete the last operation. */ block to complete the last operation. */
target_mem_write32(target, STM32Lx_NVM_SR(nvm), STM32Lx_NVM_SR_ERR_M); target_mem_write32(t, STM32Lx_NVM_SR(nvm), STM32Lx_NVM_SR_ERR_M);
while (len > 0) { while (len > 0) {
/* Write first word of page to 0 */ /* Write first word of page to 0 */
target_mem_write32(target, addr, 0); target_mem_write32(t, addr, 0);
len -= page_size; len -= page_size;
addr += page_size; addr += page_size;
} }
/* Disable further programming by locking PECR */ /* Disable further programming by locking PECR */
stm32lx_nvm_lock(target, nvm); stm32lx_nvm_lock(t, nvm);
/* Wait for completion or an error */ /* Wait for completion or an error */
while (1) { while (1) {
uint32_t sr = target_mem_read32(target, STM32Lx_NVM_SR(nvm)); uint32_t sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm));
if (target_check_error(target)) if (target_check_error(t))
return -1; return -1;
if (sr & STM32Lx_NVM_SR_BSY) if (sr & STM32Lx_NVM_SR_BSY)
continue; continue;
@ -604,13 +586,13 @@ static int stm32lx_nvm_prog_erase(struct target_s* target,
/** Write to program flash using operations through the debug /** Write to program flash using operations through the debug
interface. This is slower than the stubbed write(see NOTES). interface. This is slower than the stubbed write(see NOTES).
NVM register file address chosen from target. */ NVM register file address chosen from target. */
static int stm32lx_nvm_prog_write(struct target_s* target, static int stm32lx_nvm_prog_write(target *t,
uint32_t destination, uint32_t destination,
const uint8_t* source_8, const uint8_t* source_8,
size_t size) size_t size)
{ {
const uint32_t nvm = stm32lx_nvm_phys(target); const uint32_t nvm = stm32lx_nvm_phys(t);
const bool is_stm32l1 = stm32lx_is_stm32l1(target); const bool is_stm32l1 = stm32lx_is_stm32l1(t);
/* We can only handle word aligned writes and even /* We can only handle word aligned writes and even
word-multiple ranges. The stm32lx's cannot perform word-multiple ranges. The stm32lx's cannot perform
@ -619,19 +601,19 @@ static int stm32lx_nvm_prog_write(struct target_s* target,
if ((destination & 3) || (size & 3)) if ((destination & 3) || (size & 3))
return -1; return -1;
if (!stm32lx_nvm_prog_data_unlock(target, nvm)) if (!stm32lx_nvm_prog_data_unlock(t, nvm))
return -1; return -1;
const size_t half_page_size = stm32lx_nvm_prog_page_size(target)/2; const size_t half_page_size = stm32lx_nvm_prog_page_size(t)/2;
uint32_t* source = (uint32_t*) source_8; uint32_t* source = (uint32_t*) source_8;
while (size > 0) { while (size > 0) {
/* Wait for BSY to clear because we cannot write the PECR until /* Wait for BSY to clear because we cannot write the PECR until
the previous operation completes on STM32Lxxx. */ the previous operation completes on STM32Lxxx. */
while (target_mem_read32(target, STM32Lx_NVM_SR(nvm)) while (target_mem_read32(t, STM32Lx_NVM_SR(nvm))
& STM32Lx_NVM_SR_BSY) & STM32Lx_NVM_SR_BSY)
if (target_check_error(target)) { if (target_check_error(t)) {
return -1; return -1;
} }
@ -639,7 +621,7 @@ static int stm32lx_nvm_prog_write(struct target_s* target,
// than a half page to write // than a half page to write
if (size < half_page_size if (size < half_page_size
|| (destination & (half_page_size - 1))) { || (destination & (half_page_size - 1))) {
target_mem_write32(target, STM32Lx_NVM_PECR(nvm), target_mem_write32(t, STM32Lx_NVM_PECR(nvm),
is_stm32l1 is_stm32l1
? 0 ? 0
: STM32Lx_NVM_PECR_PROG); : STM32Lx_NVM_PECR_PROG);
@ -650,31 +632,31 @@ static int stm32lx_nvm_prog_write(struct target_s* target,
c = size; c = size;
size -= c; size -= c;
target_mem_write(target, destination, source, c); target_mem_write(t, destination, source, c);
source += c/4; source += c/4;
destination += c; destination += c;
} }
// Or we are writing a half-page(s) // Or we are writing a half-page(s)
else { else {
target_mem_write32(target, STM32Lx_NVM_PECR(nvm), target_mem_write32(t, STM32Lx_NVM_PECR(nvm),
STM32Lx_NVM_PECR_PROG STM32Lx_NVM_PECR_PROG
| STM32Lx_NVM_PECR_FPRG); | STM32Lx_NVM_PECR_FPRG);
size_t c = size & ~(half_page_size - 1); size_t c = size & ~(half_page_size - 1);
size -= c; size -= c;
target_mem_write(target, destination, source, c); target_mem_write(t, destination, source, c);
source += c/4; source += c/4;
destination += c; destination += c;
} }
} }
/* Disable further programming by locking PECR */ /* Disable further programming by locking PECR */
stm32lx_nvm_lock(target, nvm); stm32lx_nvm_lock(t, nvm);
/* Wait for completion or an error */ /* Wait for completion or an error */
while (1) { while (1) {
uint32_t sr = target_mem_read32(target, STM32Lx_NVM_SR(nvm)); uint32_t sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm));
if (target_check_error(target)) { if (target_check_error(t)) {
return -1; return -1;
} }
if (sr & STM32Lx_NVM_SR_BSY) if (sr & STM32Lx_NVM_SR_BSY)
@ -693,45 +675,43 @@ static int stm32lx_nvm_prog_write(struct target_s* target,
interface . The flash is erased for all pages from addr to interface . The flash is erased for all pages from addr to
addr+len, inclusive, on a word boundary. NVM register file addr+len, inclusive, on a word boundary. NVM register file
address chosen from target. */ address chosen from target. */
static int stm32lx_nvm_data_erase(struct target_s* target, static int stm32lx_nvm_data_erase(target *t,
uint32_t addr, size_t len) uint32_t addr, size_t len)
{ {
const size_t page_size = stm32lx_nvm_data_page_size(target); const size_t page_size = stm32lx_nvm_data_page_size(t);
const uint32_t nvm = stm32lx_nvm_phys(target); const uint32_t nvm = stm32lx_nvm_phys(t);
/* Word align */ /* Word align */
len += (addr & 3); len += (addr & 3);
addr &= ~3; addr &= ~3;
if (!stm32lx_nvm_prog_data_unlock(target, nvm)) if (!stm32lx_nvm_prog_data_unlock(t, nvm))
return -1; return -1;
/* Flash data erase instruction */ /* Flash data erase instruction */
target_mem_write32(target, STM32Lx_NVM_PECR(nvm), target_mem_write32(t, STM32Lx_NVM_PECR(nvm),
STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA); STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA);
{ uint32_t pecr = target_mem_read32(t, STM32Lx_NVM_PECR(nvm));
uint32_t pecr = target_mem_read32(target, STM32Lx_NVM_PECR(nvm)); if ((pecr & (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA))
if ((pecr & (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA)) != (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA))
!= (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA)) return -1;
return -1;
}
while (len > 0) { while (len > 0) {
/* Write first word of page to 0 */ /* Write first word of page to 0 */
target_mem_write32(target, addr, 0); target_mem_write32(t, addr, 0);
len -= page_size; len -= page_size;
addr += page_size; addr += page_size;
} }
/* Disable further programming by locking PECR */ /* Disable further programming by locking PECR */
stm32lx_nvm_lock(target, nvm); stm32lx_nvm_lock(t, nvm);
/* Wait for completion or an error */ /* Wait for completion or an error */
while (1) { while (1) {
uint32_t sr = target_mem_read32(target, STM32Lx_NVM_SR(nvm)); uint32_t sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm));
if (target_check_error(target)) if (target_check_error(t))
return -1; return -1;
if (sr & STM32Lx_NVM_SR_BSY) if (sr & STM32Lx_NVM_SR_BSY)
continue; continue;
@ -748,39 +728,38 @@ static int stm32lx_nvm_data_erase(struct target_s* target,
NVM register file address chosen from target. Unaligned NVM register file address chosen from target. Unaligned
destination writes are supported (though unaligned sources are destination writes are supported (though unaligned sources are
not). */ not). */
static int stm32lx_nvm_data_write(struct target_s* target, static int stm32lx_nvm_data_write(target *t,
uint32_t destination, uint32_t destination,
const uint8_t* source_8, const uint8_t* source_8,
size_t size) size_t size)
{ {
const uint32_t nvm = stm32lx_nvm_phys(target); const uint32_t nvm = stm32lx_nvm_phys(t);
const bool is_stm32l1 = stm32lx_is_stm32l1(target); const bool is_stm32l1 = stm32lx_is_stm32l1(t);
uint32_t* source = (uint32_t*) source_8; uint32_t* source = (uint32_t*) source_8;
if (!stm32lx_nvm_prog_data_unlock(target, nvm)) if (!stm32lx_nvm_prog_data_unlock(t, nvm))
return -1; return -1;
target_mem_write32(t, STM32Lx_NVM_PECR(nvm),
target_mem_write32(target, STM32Lx_NVM_PECR(nvm),
is_stm32l1 ? 0 : STM32Lx_NVM_PECR_DATA); is_stm32l1 ? 0 : STM32Lx_NVM_PECR_DATA);
while (size) { while (size) {
size -= 4; size -= 4;
uint32_t v = *source++; uint32_t v = *source++;
target_mem_write32(target, destination, v); target_mem_write32(t, destination, v);
destination += 4; destination += 4;
if (target_check_error(target)) if (target_check_error(t))
return -1; return -1;
} }
/* Disable further programming by locking PECR */ /* Disable further programming by locking PECR */
stm32lx_nvm_lock(target, nvm); stm32lx_nvm_lock(t, nvm);
/* Wait for completion or an error */ /* Wait for completion or an error */
while (1) { while (1) {
uint32_t sr = target_mem_read32(target, STM32Lx_NVM_SR(nvm)); uint32_t sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm));
if (target_check_error(target)) if (target_check_error(t))
return -1; return -1;
if (sr & STM32Lx_NVM_SR_BSY) if (sr & STM32Lx_NVM_SR_BSY)
continue; continue;