aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile6
-rw-r--r--src/adiv5_jtagdp.c18
-rw-r--r--src/adiv5_swdp.c28
-rw-r--r--src/arm7tdmi.c6
-rw-r--r--src/command.c43
-rw-r--r--src/cortexm.c198
-rw-r--r--src/gdb_main.c39
-rw-r--r--src/gdb_packet.c16
-rw-r--r--src/hex_utils.c6
-rw-r--r--src/include/adiv5.h6
-rw-r--r--src/include/jtagtap.h8
-rw-r--r--src/include/target.h20
-rw-r--r--src/jtagtap_generic.c8
-rw-r--r--src/lmi.c6
-rw-r--r--src/lpc11xx.c (renamed from src/nxp_tgt.c)29
-rw-r--r--src/lpc43xx.c462
-rw-r--r--src/main.c2
-rw-r--r--src/platforms/f4discovery/Makefile.inc2
-rw-r--r--src/platforms/f4discovery/platform.c2
-rw-r--r--src/platforms/f4discovery/platform.h8
-rw-r--r--src/platforms/libftdi/jtagtap.c14
-rw-r--r--src/platforms/libftdi/platform.c24
-rw-r--r--src/platforms/libftdi/swdptap.c10
-rw-r--r--src/platforms/native/platform.c37
-rw-r--r--src/platforms/native/platform.h25
-rw-r--r--src/platforms/stlink/platform.c33
-rw-r--r--src/platforms/stlink/platform.h22
-rw-r--r--src/platforms/stlink/usbdfu.c14
-rw-r--r--src/platforms/stm32/cdcacm.c8
-rw-r--r--src/platforms/stm32/dfu_f1.c6
-rw-r--r--src/platforms/stm32/dfu_f4.c14
-rw-r--r--src/platforms/stm32/dfucore.c35
-rw-r--r--src/platforms/stm32/jtagtap.c15
-rw-r--r--src/platforms/stm32/swdptap.c8
-rw-r--r--src/platforms/swlink/platform.c6
-rw-r--r--src/platforms/swlink/platform.h10
-rw-r--r--src/sam3x.c144
-rw-r--r--src/stm32f1.c58
-rw-r--r--src/stm32f4.c11
-rw-r--r--src/stm32l1.c92
-rw-r--r--src/target.c1
41 files changed, 1172 insertions, 328 deletions
diff --git a/src/Makefile b/src/Makefile
index d9f3e9e..d8d8b00 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -25,9 +25,9 @@ SRC = \
jtag_scan.c \
jtagtap.c \
lmi.c \
+ lpc11xx.c \
lpc43xx.c \
main.c \
- nxp_tgt.c \
platform.c \
sam3x.c \
stm32f1.c \
@@ -46,8 +46,8 @@ blackmagic: $(OBJ)
.PHONY: clean host_clean
clean: host_clean
- $(RM) *.o *.d *~ blackmagic $(HOSTFILES)
- $(RM) platforms/*/*.o platforms/*/*.d mapfile
+ -$(RM) *.o *.d *~ blackmagic $(HOSTFILES)
+ -$(RM) platforms/*/*.o platforms/*/*.d mapfile
-include *.d
diff --git a/src/adiv5_jtagdp.c b/src/adiv5_jtagdp.c
index 68bcddd..4306101 100644
--- a/src/adiv5_jtagdp.c
+++ b/src/adiv5_jtagdp.c
@@ -18,7 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* This file implements the JTAG-DP specific functions of the
+/* This file implements the JTAG-DP specific functions of the
* ARM Debug Interface v5 Architecure Specification, ARM doc IHI0031A.
*/
@@ -43,7 +43,7 @@ static uint32_t adiv5_jtagdp_read(ADIv5_DP_t *dp, uint8_t addr);
static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp);
-static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW,
+static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW,
uint8_t addr, uint32_t value);
@@ -70,19 +70,19 @@ static void adiv5_jtagdp_write(ADIv5_DP_t *dp, uint8_t addr, uint32_t value)
static uint32_t adiv5_jtagdp_read(ADIv5_DP_t *dp, uint8_t addr)
{
adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ, addr, 0);
- return adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ,
+ return adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ,
ADIV5_DP_RDBUFF, 0);
}
static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp)
{
- adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ,
+ adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ,
ADIV5_DP_CTRLSTAT, 0);
- return adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_WRITE,
+ return adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_WRITE,
ADIV5_DP_CTRLSTAT, 0xF0000032) & 0x32;
}
-static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW,
+static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW,
uint8_t addr, uint32_t value)
{
uint64_t request, response;
@@ -92,10 +92,14 @@ static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t R
jtag_dev_write_ir(dp->dev, APnDP?IR_APACC:IR_DPACC);
+ int tries = 1000;
do {
jtag_dev_shift_dr(dp->dev, (uint8_t*)&response, (uint8_t*)&request, 35);
ack = response & 0x07;
- } while(ack == JTAGDP_ACK_WAIT);
+ } while(--tries && (ack == JTAGDP_ACK_WAIT));
+
+ if (dp->allow_timeout && (ack == JTAGDP_ACK_WAIT))
+ return 0;
if((ack != JTAGDP_ACK_OK)) {
/* Fatal error if invalid ACK response */
diff --git a/src/adiv5_swdp.c b/src/adiv5_swdp.c
index 06d5446..7896d8b 100644
--- a/src/adiv5_swdp.c
+++ b/src/adiv5_swdp.c
@@ -18,7 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* This file implements the SW-DP specific functions of the
+/* This file implements the SW-DP specific functions of the
* ARM Debug Interface v5 Architecure Specification, ARM doc IHI0031A.
*/
@@ -27,6 +27,7 @@
#include "adiv5.h"
#include "swdptap.h"
+#include "jtagtap.h"
#include "command.h"
@@ -41,7 +42,7 @@ static uint32_t adiv5_swdp_read(ADIv5_DP_t *dp, uint8_t addr);
static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp);
-static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW,
+static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW,
uint8_t addr, uint32_t value);
@@ -53,6 +54,8 @@ int adiv5_swdp_scan(void)
ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
swdptap_init();
+ if(connect_assert_srst)
+ jtagtap_srst(true); /* will be deasserted after attach */
/* Read the SW-DP IDCODE register to syncronise */
/* This could be done with adiv_swdp_low_access(), but this doesn't
* allow the ack to be checked here. */
@@ -70,6 +73,7 @@ int adiv5_swdp_scan(void)
dp->error = adiv5_swdp_error;
dp->low_access = adiv5_swdp_low_access;
+ adiv5_swdp_error(dp);
adiv5_dp_init(dp);
if(!target_list) morse("NO TARGETS.", 1);
@@ -92,16 +96,18 @@ static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp)
{
uint32_t err, clr = 0;
- err = adiv5_swdp_read(dp, ADIV5_DP_CTRLSTAT) &
+ err = adiv5_swdp_read(dp, ADIV5_DP_CTRLSTAT) &
(ADIV5_DP_CTRLSTAT_STICKYORUN | ADIV5_DP_CTRLSTAT_STICKYCMP |
- ADIV5_DP_CTRLSTAT_STICKYERR);
+ ADIV5_DP_CTRLSTAT_STICKYERR | ADIV5_DP_CTRLSTAT_WDATAERR);
- if(err & ADIV5_DP_CTRLSTAT_STICKYORUN)
+ if(err & ADIV5_DP_CTRLSTAT_STICKYORUN)
clr |= ADIV5_DP_ABORT_ORUNERRCLR;
- if(err & ADIV5_DP_CTRLSTAT_STICKYCMP)
+ if(err & ADIV5_DP_CTRLSTAT_STICKYCMP)
clr |= ADIV5_DP_ABORT_STKCMPCLR;
- if(err & ADIV5_DP_CTRLSTAT_STICKYERR)
+ if(err & ADIV5_DP_CTRLSTAT_STICKYERR)
clr |= ADIV5_DP_ABORT_STKERRCLR;
+ if(err & ADIV5_DP_CTRLSTAT_WDATAERR)
+ clr |= ADIV5_DP_ABORT_WDERRCLR;
adiv5_swdp_write(dp, ADIV5_DP_ABORT, clr);
dp->fault = 0;
@@ -109,7 +115,7 @@ static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp)
return err;
}
-static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW,
+static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW,
uint8_t addr, uint32_t value)
{
uint8_t request = 0x81;
@@ -126,10 +132,14 @@ static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW
if((addr == 4) || (addr == 8))
request ^= 0x20;
+ size_t tries = 1000;
do {
swdptap_seq_out(request, 8);
ack = swdptap_seq_in(3);
- } while(ack == SWDP_ACK_WAIT);
+ } while(--tries && ack == SWDP_ACK_WAIT);
+
+ if (dp->allow_timeout && (ack == SWDP_ACK_WAIT))
+ return 0;
if(ack == SWDP_ACK_FAULT) {
dp->fault = 1;
diff --git a/src/arm7tdmi.c b/src/arm7tdmi.c
index 805f995..ad38ab3 100644
--- a/src/arm7tdmi.c
+++ b/src/arm7tdmi.c
@@ -139,7 +139,7 @@ void arm7tdmi_jtag_handler(jtag_dev_t *dev)
t->halt_request = arm7_halt_request;
t->halt_wait = arm7_halt_wait;
t->halt_resume = arm7_halt_resume;
-
+
/* TODO: Breakpoint and watchpoint functions. */
/* TODO: Fault unwinder. */
/* TODO: Memory map / Flash programming. */
@@ -152,7 +152,7 @@ static void arm7_select_scanchain(struct target_arm7_s *target, uint8_t chain)
jtag_dev_write_ir(target->jtag, ARM7_IR_INTEST);
}
-static void arm7_eice_write(struct target_arm7_s *target,
+static void arm7_eice_write(struct target_arm7_s *target,
uint8_t addr, uint32_t value)
{
uint64_t val = ((uint64_t)addr << 32) | value | ARM7_EICE_WRITE;
@@ -256,7 +256,7 @@ static void arm7_halt_resume(struct target_s *target, bool step)
/* Release DBGRQ */
arm7_eice_write(t, ARM7_EICE_DEBUG_CTRL, 0);
- /* This sequence restores PC if no other instructions issued in
+ /* This sequence restores PC if no other instructions issued in
* debug mode...
* 0 E1A00000; MOV R0, R0
* 1 E1A00000; MOV R0, R0
diff --git a/src/command.c b/src/command.c
index e1ed837..8378576 100644
--- a/src/command.c
+++ b/src/command.c
@@ -46,6 +46,7 @@ static bool cmd_jtag_scan(target *t, int argc, char **argv);
static bool cmd_swdp_scan(void);
static bool cmd_targets(target *t);
static bool cmd_morse(void);
+static bool cmd_connect_srst(target *t, int argc, const char **argv);
#ifdef PLATFORM_HAS_TRACESWO
static bool cmd_traceswo(void);
#endif
@@ -57,6 +58,7 @@ const struct command_s cmd_list[] = {
{"swdp_scan", (cmd_handler)cmd_swdp_scan, "Scan SW-DP for devices" },
{"targets", (cmd_handler)cmd_targets, "Display list of available targets" },
{"morse", (cmd_handler)cmd_morse, "Display morse error message" },
+ {"connect_srst", (cmd_handler)cmd_connect_srst, "Configure connect under SRST: (enable|disable)" },
#ifdef PLATFORM_HAS_TRACESWO
{"traceswo", (cmd_handler)cmd_traceswo, "Start trace capture" },
#endif
@@ -72,19 +74,19 @@ int command_process(target *t, char *cmd)
const char **argv;
/* Initial estimate for argc */
- for(char *s = cmd; *s; s++)
+ for(char *s = cmd; *s; s++)
if((*s == ' ') || (*s == '\t')) argc++;
argv = alloca(sizeof(const char *) * argc);
/* Tokenize cmd to find argv */
- for(argc = 0, argv[argc] = strtok(cmd, " \t");
+ for(argc = 0, argv[argc] = strtok(cmd, " \t");
argv[argc]; argv[++argc] = strtok(NULL, " \t"));
/* Look for match and call handler */
for(c = cmd_list; c->cmd; c++) {
/* Accept a partial match as GDB does.
- * So 'mon ver' will match 'monitor version'
+ * So 'mon ver' will match 'monitor version'
*/
if(!strncmp(argv[0], c->cmd, strlen(argv[0])))
return !c->handler(t, argc, argv);
@@ -94,7 +96,7 @@ int command_process(target *t, char *cmd)
return -1;
for (tc = t->commands; tc; tc = tc->next)
- for(c = tc->cmds; c->cmd; c++)
+ for(c = tc->cmds; c->cmd; c++)
if(!strncmp(argv[0], c->cmd, strlen(argv[0])))
return !c->handler(t, argc, argv);
@@ -117,7 +119,7 @@ bool cmd_help(target *t)
const struct command_s *c;
gdb_out("General commands:\n");
- for(c = cmd_list; c->cmd; c++)
+ for(c = cmd_list; c->cmd; c++)
gdb_outf("\t%s -- %s\n", c->cmd, c->help);
if (!t)
@@ -125,7 +127,7 @@ bool cmd_help(target *t)
for (tc = t->commands; tc; tc = tc->next) {
gdb_outf("%s specific commands:\n", tc->specific_name);
- for(c = tc->cmds; c->cmd; c++)
+ for(c = tc->cmds; c->cmd; c++)
gdb_outf("\t%s -- %s\n", c->cmd, c->help);
}
@@ -152,15 +154,15 @@ static bool cmd_jtag_scan(target *t, int argc, char **argv)
if(devs < 0) {
gdb_out("JTAG device scan failed!\n");
return false;
- }
+ }
if(devs == 0) {
gdb_out("JTAG scan found no devices!\n");
return false;
- }
+ }
gdb_outf("Device IR Len IDCODE Description\n");
for(int i = 0; i < jtag_dev_count; i++)
- gdb_outf("%d\t%d\t0x%08lX %s\n", i,
- jtag_devs[i].ir_len, jtag_devs[i].idcode,
+ gdb_outf("%d\t%d\t0x%08lX %s\n", i,
+ jtag_devs[i].ir_len, jtag_devs[i].idcode,
jtag_devs[i].descr);
gdb_out("\n");
cmd_targets(NULL);
@@ -174,13 +176,13 @@ bool cmd_swdp_scan(void)
if(adiv5_swdp_scan() < 0) {
gdb_out("SW-DP scan failed!\n");
return false;
- }
+ }
//gdb_outf("SW-DP detected IDCODE: 0x%08X\n", adiv5_dp_list->idcode);
cmd_targets(NULL);
return true;
-
+
}
bool cmd_targets(target *cur_target)
@@ -192,11 +194,11 @@ bool cmd_targets(target *cur_target)
gdb_out("No usable targets found.\n");
return false;
}
-
+
gdb_out("Available Targets:\n");
gdb_out("No. Att Driver\n");
for(t = target_list, i = 1; t; t = t->next, i++)
- gdb_outf("%2d %c %s\n", i, t==cur_target?'*':' ',
+ gdb_outf("%2d %c %s\n", i, t==cur_target?'*':' ',
t->driver);
return true;
@@ -204,11 +206,22 @@ bool cmd_targets(target *cur_target)
bool cmd_morse(void)
{
- if(morse_msg)
+ if(morse_msg)
gdb_outf("%s\n", morse_msg);
return true;
}
+static bool cmd_connect_srst(target *t, int argc, const char **argv)
+{
+ (void)t;
+ if (argc == 1)
+ gdb_outf("Assert SRST during connect: %s\n",
+ connect_assert_srst ? "enabled" : "disabled");
+ else
+ connect_assert_srst = !strcmp(argv[1], "enable");
+ return true;
+}
+
#ifdef PLATFORM_HAS_TRACESWO
static bool cmd_traceswo(void)
{
diff --git a/src/cortexm.c b/src/cortexm.c
index 9ec96d6..1fc5978 100644
--- a/src/cortexm.c
+++ b/src/cortexm.c
@@ -28,6 +28,7 @@
* Issues:
* There are way too many magic numbers used here.
*/
+#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -204,6 +205,9 @@ static int cortexm_check_hw_wp(struct target_s *target, uint32_t *addr);
#define CORTEXM_MAX_WATCHPOINTS 4 /* architecture says up to 15, no implementation has > 4 */
#define CORTEXM_MAX_BREAKPOINTS 6 /* architecture says up to 127, no implementation has > 6 */
+static int cortexm_hostio_request(target *t);
+static void cortexm_hostio_reply(target *t, int32_t retcode, uint32_t errcode);
+
struct cortexm_priv {
bool stepping;
bool on_bkpt;
@@ -219,6 +223,10 @@ struct cortexm_priv {
unsigned hw_breakpoint_max;
/* Copy of DEMCR for vector-catch */
uint32_t demcr;
+ /* Semihosting state */
+ uint32_t syscall;
+ uint32_t errno;
+ uint32_t byte_count;
};
/* Register number tables */
@@ -335,6 +343,8 @@ cortexm_probe(struct target_s *target)
target->halt_resume = cortexm_halt_resume;
target->regs_size = sizeof(regnum_cortex_m);
+ target->hostio_reply = cortexm_hostio_reply;
+
target_add_commands(target, cortexm_cmd_list, cortexm_driver_str);
/* Probe for FP extension */
@@ -385,7 +395,7 @@ cortexm_attach(struct target_s *target)
target_halt_request(target);
tries = 10;
- while(!target_halt_wait(target) && --tries)
+ while(!connect_assert_srst && !target_halt_wait(target) && --tries)
platform_delay(2);
if(!tries)
return false;
@@ -429,6 +439,9 @@ cortexm_attach(struct target_s *target)
target->clear_hw_wp = cortexm_clear_hw_wp;
target->check_hw_wp = cortexm_check_hw_wp;
+ if(connect_assert_srst)
+ jtagtap_srst(false);
+
return true;
}
@@ -546,7 +559,8 @@ cortexm_reset(struct target_s *target)
{
ADIv5_AP_t *ap = adiv5_target_ap(target);
- jtagtap_srst();
+ jtagtap_srst(true);
+ jtagtap_srst(false);
/* Read DHCSR here to clear S_RESET_ST bit before reset */
adiv5_ap_mem_read(ap, CORTEXM_DHCSR);
@@ -570,6 +584,7 @@ cortexm_halt_request(struct target_s *target)
{
ADIv5_AP_t *ap = adiv5_target_ap(target);
+ ap->dp->allow_timeout = false;
adiv5_ap_mem_write(ap, CORTEXM_DHCSR,
CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_HALT | CORTEXM_DHCSR_C_DEBUGEN);
}
@@ -582,6 +597,8 @@ cortexm_halt_wait(struct target_s *target)
if (!(adiv5_ap_mem_read(ap, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_HALT))
return 0;
+ ap->dp->allow_timeout = false;
+
/* We've halted. Let's find out why. */
uint32_t dfsr = adiv5_ap_mem_read(ap, CORTEXM_DFSR);
adiv5_ap_mem_write(ap, CORTEXM_DFSR, dfsr); /* write back to reset */
@@ -591,6 +608,23 @@ cortexm_halt_wait(struct target_s *target)
/* Remember if we stopped on a breakpoint */
priv->on_bkpt = dfsr & (CORTEXM_DFSR_BKPT);
+ if (priv->on_bkpt) {
+ /* If we've hit a programmed breakpoint, check for semihosting
+ * call. */
+ uint32_t pc = cortexm_pc_read(target);
+ uint16_t bkpt_instr;
+ target_mem_read_bytes(target, (uint8_t *)&bkpt_instr, pc, 2);
+ if (bkpt_instr == 0xBEAB) {
+ int n = cortexm_hostio_request(target);
+ if (n > 0) {
+ target_halt_resume(target, priv->stepping);
+ return 0;
+ } else if (n < 0) {
+ return -1;
+ }
+ }
+ }
+
if (dfsr & (CORTEXM_DFSR_BKPT | CORTEXM_DFSR_DWTTRAP))
return SIGTRAP;
@@ -623,6 +657,7 @@ cortexm_halt_resume(struct target_s *target, bool step)
}
adiv5_ap_mem_write(ap, CORTEXM_DHCSR, dhcsr);
+ ap->dp->allow_timeout = true;
}
static int cortexm_fault_unwind(struct target_s *target)
@@ -636,7 +671,7 @@ static int cortexm_fault_unwind(struct target_s *target)
* for a configurable fault to avoid catching core resets */
if((hfsr & CORTEXM_HFSR_FORCED) || cfsr) {
/* Unwind exception */
- uint32_t regs[target->regs_size];
+ uint32_t regs[target->regs_size / 4];
uint32_t stack[8];
uint32_t retcode, framesize;
/* Read registers for post-exception stack pointer */
@@ -857,3 +892,160 @@ static bool cortexm_vector_catch(target *t, int argc, char *argv[])
return true;
}
+
+/* Semihosting support */
+/* ARM Semihosting syscall numbers, from ARM doc DUI0471C, Chapter 8 */
+#define SYS_CLOSE 0x02
+#define SYS_CLOCK 0x10
+#define SYS_ELAPSED 0x30
+#define SYS_ERRNO 0x13
+#define SYS_FLEN 0x0C
+#define SYS_GET_CMDLINE 0x15
+#define SYS_HEAPINFO 0x16
+#define SYS_ISERROR 0x08
+#define SYS_ISTTY 0x09
+#define SYS_OPEN 0x01
+#define SYS_READ 0x06
+#define SYS_READC 0x07
+#define SYS_REMOVE 0x0E
+#define SYS_RENAME 0x0F
+#define SYS_SEEK 0x0A
+#define SYS_SYSTEM 0x12
+#define SYS_TICKFREQ 0x31
+#define SYS_TIME 0x11
+#define SYS_TMPNAM 0x0D
+#define SYS_WRITE 0x05
+#define SYS_WRITEC 0x03
+#define SYS_WRITE0 0x04
+
+#define FILEIO_O_RDONLY 0
+#define FILEIO_O_WRONLY 1
+#define FILEIO_O_RDWR 2
+#define FILEIO_O_APPEND 0x008
+#define FILEIO_O_CREAT 0x200
+#define FILEIO_O_TRUNC 0x400
+
+#define FILEIO_SEEK_SET 0
+#define FILEIO_SEEK_CUR 1
+#define FILEIO_SEEK_END 2
+
+static int cortexm_hostio_request(target *t)
+{
+ ADIv5_AP_t *ap = adiv5_target_ap(t);
+ struct cortexm_priv *priv = ap->priv;
+ uint32_t arm_regs[t->regs_size];
+ uint32_t params[4];
+
+ target_regs_read(t, arm_regs);
+ target_mem_read_words(t, params, arm_regs[1], sizeof(params));
+ priv->syscall = arm_regs[0];
+
+ DEBUG("syscall 0x%x (%x %x %x %x)\n", priv->syscall,
+ params[0], params[1], params[2], params[3]);
+ switch (priv->syscall) {
+ case SYS_OPEN:{ /* open */
+ /* Translate stupid fopen modes to open flags.
+ * See DUI0471C, Table 8-3 */
+ const uint32_t flags[] = {
+ FILEIO_O_RDONLY, /* r, rb */
+ FILEIO_O_RDWR, /* r+, r+b */
+ FILEIO_O_WRONLY | FILEIO_O_CREAT | FILEIO_O_TRUNC,/*w*/
+ FILEIO_O_RDWR | FILEIO_O_CREAT | FILEIO_O_TRUNC,/*w+*/
+ FILEIO_O_WRONLY | FILEIO_O_CREAT | FILEIO_O_APPEND,/*a*/
+ FILEIO_O_RDWR | FILEIO_O_CREAT | FILEIO_O_APPEND,/*a+*/
+ };
+ uint32_t pflag = flags[params[1] >> 1];
+ char filename[4];
+
+ target_mem_read_bytes(t, filename, params[0], sizeof(filename));
+ /* handle requests for console i/o */
+ if (!strcmp(filename, ":tt")) {
+ if (pflag == FILEIO_O_RDONLY)
+ arm_regs[0] = STDIN_FILENO;
+ else if (pflag & FILEIO_O_TRUNC)
+ arm_regs[0] = STDOUT_FILENO;
+ else
+ arm_regs[0] = STDERR_FILENO;
+ arm_regs[0]++;
+ target_regs_write(t, arm_regs);
+ return 1;
+ }
+
+ gdb_putpacket_f("Fopen,%08X/%X,%08X,%08X",
+ params[0], params[2] + 1,
+ pflag, 0644);
+ break;
+ }
+ case SYS_CLOSE: /* close */
+ gdb_putpacket_f("Fclose,%08X", params[0] - 1);
+ break;
+ case SYS_READ: /* read */
+ priv->byte_count = params[2];
+ gdb_putpacket_f("Fread,%08X,%08X,%08X",
+ params[0] - 1, params[1], params[2]);
+ break;
+ case SYS_WRITE: /* write */
+ priv->byte_count = params[2];
+ gdb_putpacket_f("Fwrite,%08X,%08X,%08X",
+ params[0] - 1, params[1], params[2]);
+ break;
+ case SYS_WRITEC: /* writec */
+ gdb_putpacket_f("Fwrite,2,%08X,1", arm_regs[1]);
+ break;
+ case SYS_ISTTY: /* isatty */
+ gdb_putpacket_f("Fisatty,%08X", params[0] - 1);
+ break;
+ case SYS_SEEK: /* lseek */
+ gdb_putpacket_f("Flseek,%08X,%08X,%08X",
+ params[0] - 1, params[1], FILEIO_SEEK_SET);
+ break;
+ case SYS_RENAME:/* rename */
+ gdb_putpacket_f("Frename,%08X/%X,%08X/%X",
+ params[0] - 1, params[1] + 1,
+ params[2], params[3] + 1);
+ break;
+ case SYS_REMOVE:/* unlink */
+ gdb_putpacket_f("Funlink,%08X/%X", params[0] - 1,
+ params[1] + 1);
+ break;
+ case SYS_SYSTEM:/* system */
+ gdb_putpacket_f("Fsystem,%08X/%X", params[0] - 1,
+ params[1] + 1);
+ break;
+
+ case SYS_FLEN: /* Not supported, fake success */
+ priv->errno = 0;
+ return 1;
+
+ case SYS_ERRNO: /* Return last errno from GDB */
+ arm_regs[0] = priv->errno;
+ target_regs_write(t, arm_regs);
+ return 1;
+
+ case SYS_TIME: /* gettimeofday */
+ /* FIXME How do we use gdb's gettimeofday? */
+ default:
+ return 0;
+ }
+
+ return -1;
+}
+
+static void cortexm_hostio_reply(target *t, int32_t retcode, uint32_t errcode)
+{
+ ADIv5_AP_t *ap = adiv5_target_ap(t);
+ struct cortexm_priv *priv = ap->priv;
+ uint32_t arm_regs[t->regs_size];
+
+ DEBUG("syscall return ret=%d errno=%d\n", retcode, errcode);
+ target_regs_read(t, arm_regs);
+ if (((priv->syscall == SYS_READ) || (priv->syscall == SYS_WRITE)) &&
+ (retcode > 0))
+ retcode = priv->byte_count - retcode;
+ if ((priv->syscall == SYS_OPEN) && (retcode != -1))
+ retcode++;
+ arm_regs[0] = retcode;
+ target_regs_write(t, arm_regs);
+ priv->errno = errcode;
+}
+
diff --git a/src/gdb_main.c b/src/gdb_main.c
index 6be6d0f..bd27d48 100644
--- a/src/gdb_main.c
+++ b/src/gdb_main.c
@@ -75,6 +75,7 @@ gdb_main(void)
{
int size;
bool single_step = false;
+ char last_activity = 0;
DEBUG("Entring GDB protocol main loop\n");
/* GDB protocol main loop */
@@ -82,12 +83,13 @@ gdb_main(void)
SET_IDLE_STATE(1);
size = gdb_getpacket(pbuf, BUF_SIZE);
SET_IDLE_STATE(0);
+ continue_activity:
switch(pbuf[0]) {
/* Implementation of these is mandatory! */
case 'g': { /* 'g': Read general registers */
ERROR_IF_NO_TARGET();
- uint32_t arm_regs[cur_target->regs_size];
- target_regs_read(cur_target, (void*)arm_regs);
+ uint8_t arm_regs[cur_target->regs_size];
+ target_regs_read(cur_target, arm_regs);
gdb_putpacket(hexify(pbuf, (void*)arm_regs, cur_target->regs_size), cur_target->regs_size * 2);
break;
}
@@ -109,8 +111,8 @@ gdb_main(void)
}
case 'G': { /* 'G XX': Write general registers */
ERROR_IF_NO_TARGET();
- uint32_t arm_regs[cur_target->regs_size];
- unhexify((void*)arm_regs, &pbuf[1], cur_target->regs_size);
+ uint8_t arm_regs[cur_target->regs_size];
+ unhexify(arm_regs, &pbuf[1], cur_target->regs_size);
target_regs_write(cur_target, arm_regs);
gdb_putpacketz("OK");
break;
@@ -158,14 +160,21 @@ gdb_main(void)
break;
}
+ last_activity = pbuf[0];
/* Wait for target halt */
while(!(sig = target_halt_wait(cur_target))) {
unsigned char c = gdb_if_getchar_to(0);
if((c == '\x03') || (c == '\x04')) {
target_halt_request(cur_target);
+ last_activity = 's';
}
}
SET_RUN_STATE(0);
+
+ /* Negative signal indicates we're in a syscall */
+ if (sig < 0)
+ break;
+
/* Report reason for halt */
if(target_check_hw_wp(cur_target, &watch_addr)) {
/* Watchpoint hit */
@@ -175,6 +184,28 @@ gdb_main(void)
}
break;
}
+ case 'F': { /* Semihosting call finished */
+ int retcode, errcode, items;
+ char c, *p;
+ if (pbuf[1] == '-')
+ p = &pbuf[2];
+ else
+ p = &pbuf[1];
+ items = sscanf(p, "%x,%x,%c", &retcode, &errcode, &c);
+ if (pbuf[1] == '-')
+ retcode = -retcode;
+
+ target_hostio_reply(cur_target, retcode, errcode);
+
+ /* if break is requested */
+ if (items == 3 && c == 'C') {
+ gdb_putpacketz("T02");
+ break;
+ }
+
+ pbuf[0] = last_activity;
+ goto continue_activity;
+ }
/* Optional GDB packet support */
case '!': /* Enable Extended GDB Protocol. */
diff --git a/src/gdb_packet.c b/src/gdb_packet.c
index 958572c..d43be42 100644
--- a/src/gdb_packet.c
+++ b/src/gdb_packet.c
@@ -34,7 +34,7 @@
#include "gdb_packet.h"
#include "hex_utils.h"
-int
+int
gdb_getpacket(unsigned char *packet, int size)
{
unsigned char c;
@@ -54,9 +54,9 @@ gdb_getpacket(unsigned char *packet, int size)
if(i == size) break; /* Oh shit */
if(c == '$') { /* Restart capture */
- i = 0;
- csum = 0;
- continue;
+ i = 0;
+ csum = 0;
+ continue;
}
if(c == '}') { /* escaped char */
c = gdb_if_getchar();
@@ -70,7 +70,7 @@ gdb_getpacket(unsigned char *packet, int size)
recv_csum[0] = gdb_if_getchar();
recv_csum[1] = gdb_if_getchar();
recv_csum[2] = 0;
-
+
/* return packet if checksum matches */
if(csum == strtol(recv_csum, NULL, 16)) break;
@@ -84,7 +84,7 @@ gdb_getpacket(unsigned char *packet, int size)
DEBUG("%s : ", __func__);
for(int j = 0; j < i; j++) {
c = packet[j];
- if ((c >= 32) && (c < 127))
+ if ((c >= 32) && (c < 127))
DEBUG("%c", c);
else
DEBUG("\\x%02X", c);
@@ -101,7 +101,7 @@ void gdb_putpacket(unsigned char *packet, int size)
unsigned char c;
char xmit_csum[3];
int tries = 0;
-
+
do {
#ifdef DEBUG_GDBPACKET
DEBUG("%s : ", __func__);
@@ -111,7 +111,7 @@ void gdb_putpacket(unsigned char *packet, int size)
for(i = 0; i < size; i++) {
c = packet[i];
#ifdef DEBUG_GDBPACKET
- if ((c >= 32) && (c < 127))
+ if ((c >= 32) && (c < 127))
DEBUG("%c", c);
else
DEBUG("\\x%02X", c);
diff --git a/src/hex_utils.c b/src/hex_utils.c
index 6629f10..e477281 100644
--- a/src/hex_utils.c
+++ b/src/hex_utils.c
@@ -18,7 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* Convenience function to convert to/from ascii strings of hex digits.
+/* Convenience function to convert to/from ascii strings of hex digits.
*/
#include <stdio.h>
@@ -44,9 +44,9 @@ char * hexify(char *hex, const unsigned char *buf, int size)
static uint8_t unhex_digit(char hex)
{
uint8_t tmp = hex - '0';
- if(tmp > 9)
+ if(tmp > 9)
tmp -= 'A' - '0' - 10;
- if(tmp > 16)
+ if(tmp > 16)
tmp -= 'a' - 'A';
return tmp;
}
diff --git a/src/include/adiv5.h b/src/include/adiv5.h
index d2d4be0..64b6a28 100644
--- a/src/include/adiv5.h
+++ b/src/include/adiv5.h
@@ -106,12 +106,14 @@ typedef struct ADIv5_DP_s {
uint32_t idcode;
+ bool allow_timeout;
+
void (*dp_write)(struct ADIv5_DP_s *dp, uint8_t addr, uint32_t value);
uint32_t (*dp_read)(struct ADIv5_DP_s *dp, uint8_t addr);
uint32_t (*error)(struct ADIv5_DP_s *dp);
- uint32_t (*low_access)(struct ADIv5_DP_s *dp, uint8_t APnDP, uint8_t RnW,
+ uint32_t (*low_access)(struct ADIv5_DP_s *dp, uint8_t APnDP, uint8_t RnW,
uint8_t addr, uint32_t value);
union {
@@ -135,7 +137,7 @@ static inline uint32_t adiv5_dp_error(ADIv5_DP_t *dp)
return dp->error(dp);
}
-static inline uint32_t adiv5_dp_low_access(struct ADIv5_DP_s *dp, uint8_t APnDP,
+static inline uint32_t adiv5_dp_low_access(struct ADIv5_DP_s *dp, uint8_t APnDP,
uint8_t RnW, uint8_t addr, uint32_t value)
{
return dp->low_access(dp, APnDP, RnW, addr, value);
diff --git a/src/include/jtagtap.h b/src/include/jtagtap.h
index 9fe3e0d..fd13f2b 100644
--- a/src/include/jtagtap.h
+++ b/src/include/jtagtap.h
@@ -29,7 +29,7 @@ int jtagtap_init(void);
void jtagtap_reset(void);
-void jtagtap_srst(void);
+void jtagtap_srst(bool assert);
uint8_t jtagtap_next(const uint8_t TMS, const uint8_t TDI);
/* tap_next executes one state transision in the JTAG TAP state machine:
@@ -44,9 +44,9 @@ void jtagtap_tms_seq(uint32_t MS, int ticks);
void jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks);
void jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks);
/* Shift out a sequence on MS and DI, capture data to DO.
- * - This is not endian safe: First byte will always be first shifted out.
- * - DO may be NULL to ignore captured data.
- * - DO may be point to the same address as DI.
+ * - This is not endian safe: First byte will always be first shifted out.
+ * - DO may be NULL to ignore captured data.
+ * - DO may be point to the same address as DI.
*/
/* generic soft reset: 1, 1, 1, 1, 1, 0 */
diff --git a/src/include/target.h b/src/include/target.h
index 31501f6..574a0eb 100644
--- a/src/include/target.h
+++ b/src/include/target.h
@@ -34,7 +34,7 @@ typedef struct target_s target;
* targets, or because of a communication failure. The target data may
* be assumed to be intact, but the communication medium may not be available,
* so access methods shouldn't be called.
- *
+ *
* The callback is installed by target_attach() and only removed by attaching
* with a different callback. It remains intact after target_detach().
*/
@@ -116,6 +116,10 @@ target *target_attach(target *t, target_destroy_callback destroy_cb);
#define target_flash_write(target, dest, src, len) \
(target)->flash_write((target), (dest), (src), (len))
+/* Host I/O */
+#define target_hostio_reply(target, recode, errcode) \
+ (target)->hostio_reply((target), (retcode), (errcode))
+
struct target_s {
/* Notify controlling debugger if target is lost */
@@ -127,14 +131,14 @@ struct target_s {
int (*check_error)(struct target_s *target);
/* Memory access functions */
- int (*mem_read_words)(struct target_s *target, uint32_t *dest, uint32_t src,
+ int (*mem_read_words)(struct target_s *target, uint32_t *dest, uint32_t src,
int len);
- int (*mem_write_words)(struct target_s *target, uint32_t dest,
+ int (*mem_write_words)(struct target_s *target, uint32_t dest,
const uint32_t *src, int len);
- int (*mem_read_bytes)(struct target_s *target, uint8_t *dest, uint32_t src,
+ int (*mem_read_bytes)(struct target_s *target, uint8_t *dest, uint32_t src,
int len);
- int (*mem_write_bytes)(struct target_s *target, uint32_t dest,
+ int (*mem_write_bytes)(struct target_s *target, uint32_t dest,
const uint8_t *src, int len);
/* Register access functions */
@@ -168,9 +172,12 @@ struct target_s {
/* Flash memory access functions */
const char *xml_mem_map;
int (*flash_erase)(struct target_s *target, uint32_t addr, int len);
- int (*flash_write)(struct target_s *target, uint32_t dest,
+ int (*flash_write)(struct target_s *target, uint32_t dest,
const uint8_t *src, int len);
+ /* Host I/O support */
+ void (*hostio_reply)(target *t, int32_t retcode, uint32_t errcode);
+
const char *driver;
struct target_command_s *commands;
@@ -188,6 +195,7 @@ struct target_command_s {
};
extern target *target_list;
+extern bool connect_assert_srst;
target *target_new(unsigned size);
void target_list_free(void);
diff --git a/src/jtagtap_generic.c b/src/jtagtap_generic.c
index a2e723b..63c8e44 100644
--- a/src/jtagtap_generic.c
+++ b/src/jtagtap_generic.c
@@ -28,14 +28,14 @@ jtagtap_tms_seq(uint32_t MS, int ticks)
{
while(ticks--) {
jtagtap_next(MS & 1, 1);
- MS >>= 1;
+ MS >>= 1;
}
}
#endif
#ifdef PROVIDE_GENERIC_JTAGTAP_TDI_TDO_SEQ
-void
+void
jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks)
{
uint8_t index = 1;
@@ -55,7 +55,7 @@ jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int
#ifdef PROVIDE_GENERIC_JTAGTAP_TDI_SEQ
-void
+void
jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks)
{
uint8_t index = 1;
@@ -63,7 +63,7 @@ jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks)
jtagtap_next(ticks?0:final_tms, *DI & index);
if(!(index <<= 1)) {
index = 1;
- DI++;
+ DI++;
}
}
}
diff --git a/src/lmi.c b/src/lmi.c
index 09a9dd5..cb620c0 100644
--- a/src/lmi.c
+++ b/src/lmi.c
@@ -18,7 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* This file implements TI/LMI LM3S target specific functions providing
+/* This file implements TI/LMI LM3S target specific functions providing
* the XML memory map and Flash memory programming.
*
* Issues:
@@ -35,7 +35,7 @@
#include "target.h"
static int lmi_flash_erase(struct target_s *target, uint32_t addr, int len);
-static int lmi_flash_write(struct target_s *target, uint32_t dest,
+static int lmi_flash_write(struct target_s *target, uint32_t dest,
const uint8_t *src, int len);
static const char lmi_driver_str[] = "LuminaryMicro Stellaris";
@@ -135,7 +135,7 @@ int lmi_flash_erase(struct target_s *target, uint32_t addr, int len)
return 0;
}
-int lmi_flash_write(struct target_s *target, uint32_t dest,
+int lmi_flash_write(struct target_s *target, uint32_t dest,
const uint8_t *src, int len)
{
uint32_t data[(len>>2)+2];
diff --git a/src/nxp_tgt.c b/src/lpc11xx.c
index a22eda8..9adbe2b 100644
--- a/src/nxp_tgt.c
+++ b/src/lpc11xx.c
@@ -51,10 +51,10 @@ static struct flash_program flash_pgm;
static void lpc11x_iap_call(struct target_s *target, 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_erase(struct target_s *target, uint32_t addr, int len);
-static int lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src,
+static int lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src,
int len);
-/*
+/*
* Note that this memory map is actually for the largest of the lpc11xx devices;
* There seems to be no good way to decode the part number to determine the RAM
* and flash sizes.
@@ -98,6 +98,8 @@ lpc11xx_probe(struct target_s *target)
case 0x0444102B:
case 0x2540102B:
case 0x1440102B: /* lpc1114 */
+ case 0x0A40902B:
+ case 0x1A40902B:
case 0x1431102B: /* lpc11c22 */
case 0x1430102B: /* lpc11c24 */
target->driver = "lpc11xx";
@@ -114,7 +116,7 @@ lpc11xx_probe(struct target_s *target)
static void
lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len)
{
- uint32_t regs[target->regs_size];
+ uint32_t regs[target->regs_size / 4];
/* fill out the remainder of the parameters and copy the structure to RAM */
param->opcodes[0] = 0xbe00;
@@ -141,7 +143,7 @@ lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned par
static int
lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len)
-{
+{
/* prepare the sector(s) to be erased */
memset(&flash_pgm.p, 0, sizeof(flash_pgm.p));
flash_pgm.p.command[0] = IAP_CMD_PREPARE;
@@ -194,15 +196,15 @@ lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src,
unsigned chunk;
for (chunk = first_chunk; chunk <= last_chunk; chunk++) {
-
+
DEBUG("chunk %u len %d\n", chunk, len);
/* first and last chunk may require special handling */
if ((chunk == first_chunk) || (chunk == last_chunk)) {
/* fill with all ff to avoid sector rewrite corrupting other writes */
memset(flash_pgm.data, 0xff, sizeof(flash_pgm.data));
-
- /* copy as much as fits */
+
+ /* copy as much as fits */
int copylen = IAP_PGM_CHUNKSIZE - chunk_offset;
if (copylen > len)
copylen = len;
@@ -214,13 +216,18 @@ lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src,
chunk_offset = 0;
/* if we are programming the vectors, calculate the magic number */
- if (chunk == 0) {
+ if (dest == 0) {
uint32_t *w = (uint32_t *)(&flash_pgm.data[0]);
uint32_t sum = 0;
- for (unsigned i = 0; i < 7; i++)
- sum += w[i];
- w[7] = 0 - sum;
+ if (copylen >= 7) {
+ for (unsigned i = 0; i < 7; i++)
+ sum += w[i];
+ w[7] = 0 - sum;
+ } else {
+ /* We can't possibly calculate the magic number */
+ return -1;
+ }
}
} else {
diff --git a/src/lpc43xx.c b/src/lpc43xx.c
index ca1b351..0a8745d 100644
--- a/src/lpc43xx.c
+++ b/src/lpc43xx.c
@@ -17,12 +17,138 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stddef.h>
+#include "command.h"
#include "general.h"
#include "adiv5.h"
#include "target.h"
#define LPC43XX_CHIPID 0x40043200
#define ARM_CPUID 0xE000ED00
+#define ARM_THUMB_BREAKPOINT 0xBE00
+
+#define R_MSP 17 // Main stack pointer register number
+#define R_PC 15 // Program counter register number
+#define R_LR 14 // Link register number
+
+#define IAP_ENTRYPOINT_LOCATION 0x10400100
+
+#define LPC43XX_ETBAHB_SRAM_BASE 0x2000C000
+#define LPC43XX_ETBAHB_SRAM_SIZE (16*1024)
+
+#define IAP_RAM_SIZE LPC43XX_ETBAHB_SRAM_SIZE
+#define IAP_RAM_BASE LPC43XX_ETBAHB_SRAM_BASE
+
+#define IAP_PGM_CHUNKSIZE 4096
+
+#define IAP_CMD_INIT 49
+#define IAP_CMD_PREPARE 50
+#define IAP_CMD_PROGRAM 51
+#define IAP_CMD_ERASE 52
+#define IAP_CMD_BLANKCHECK 53
+#define IAP_CMD_SET_ACTIVE_BANK 60
+
+#define IAP_STATUS_CMD_SUCCESS 0
+#define IAP_STATUS_INVALID_COMMAND 1
+#define IAP_STATUS_SRC_ADDR_ERROR 2
+#define IAP_STATUS_DST_ADDR_ERROR 3
+#define IAP_STATUS_SRC_ADDR_NOT_MAPPED 4
+#define IAP_STATUS_DST_ADDR_NOT_MAPPED 5
+#define IAP_STATUS_COUNT_ERROR 6
+#define IAP_STATUS_INVALID_SECTOR 7
+#define IAP_STATUS_SECTOR_NOT_BLANK 8
+#define IAP_STATUS_SECTOR_NOT_PREPARED 9
+#define IAP_STATUS_COMPARE_ERROR 10
+#define IAP_STATUS_BUSY 11
+
+#define FLASH_BANK_A_BASE 0x1A000000
+#define FLASH_BANK_A_SIZE 0x80000
+#define FLASH_BANK_B_BASE 0x1B000000
+#define FLASH_BANK_B_SIZE 0x80000
+#define FLASH_NUM_BANK 2
+#define FLASH_NUM_SECTOR 15
+#define FLASH_LARGE_SECTOR_OFFSET 0x00010000
+
+/* CPU Frequency */
+#define CPU_CLK_KHZ 12000
+
+struct flash_param {
+ uint16_t opcode; /* opcode to return to after calling the ROM */
+ uint16_t pad0;
+ uint32_t command; /* IAP command */
+ union {
+ uint32_t words[5]; /* command parameters */
+ struct {
+ uint32_t start_sector;
+ uint32_t end_sector;
+ uint32_t flash_bank;
+ } prepare;
+ struct {
+ uint32_t start_sector;
+ uint32_t end_sector;
+ uint32_t cpu_clk_khz;
+ uint32_t flash_bank;
+ } erase;
+ struct {
+ uint32_t dest;
+ uint32_t source;
+ uint32_t byte_count;
+ uint32_t cpu_clk_khz;
+ } program;
+ struct {
+ uint32_t start_sector;
+ uint32_t end_sector;
+ uint32_t flash_bank;
+ } blank_check;
+ struct {
+ uint32_t flash_bank;
+ uint32_t cpu_clk_khz;
+ } make_active;
+ } params;
+ uint32_t result[5]; /* result data */
+};
+
+struct flash_program {
+ struct flash_param p;
+ uint8_t data[IAP_PGM_CHUNKSIZE];
+};
+
+static bool lpc43xx_cmd_erase(target *t);
+static int lpc43xx_flash_init(struct target_s *target);
+static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len);
+static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len);
+static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, int len);
+static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len);
+
+const struct command_s lpc43xx_cmd_list[] = {
+ {"erase_mass", (cmd_handler)lpc43xx_cmd_erase, "Erase entire flash memory"},
+ {NULL, NULL, NULL}
+};
+
+/* blocksize is the erasure block size */
+static const char lpc4337_xml_memory_map[] = "<?xml version=\"1.0\"?>"
+/*
+ "<!DOCTYPE memory-map "
+ " PUBLIC \"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\""
+ "\"http://sourceware.org/gdb/gdb-memory-map.dtd\">"
+*/
+"<memory-map>"
+" <memory type=\"ram\" start=\"0x0\" length=\"0x1A000000\"/>"
+" <memory type=\"flash\" start=\"0x1A000000\" length=\"0x10000\">"
+" <property name=\"blocksize\">0x2000</property>"
+" </memory>"
+" <memory type=\"flash\" start=\"0x1A010000\" length=\"0x70000\">"
+" <property name=\"blocksize\">0x10000</property>"
+" </memory>"
+" <memory type=\"ram\" start=\"0x1A080000\" length=\"0x00F80000\"/>"
+" <memory type=\"flash\" start=\"0x1B000000\" length=\"0x10000\">"
+" <property name=\"blocksize\">0x2000</property>"
+" </memory>"
+" <memory type=\"flash\" start=\"0x1B010000\" length=\"0x70000\">"
+" <property name=\"blocksize\">0x10000</property>"
+" </memory>"
+" <memory type=\"ram\" start=\"0x1B080000\" length=\"0xE4F80000\"/>"
+"</memory-map>";
bool lpc43xx_probe(struct target_s *target)
{
@@ -32,22 +158,330 @@ bool lpc43xx_probe(struct target_s *target)
cpuid = adiv5_ap_mem_read(adiv5_target_ap(target), ARM_CPUID);
switch(chipid) {
- case 0x4906002B: /* Parts with on-chip flash */
- case 0x5906002B: /* Flashless parts */
- case 0x6906002B:
- switch (cpuid & 0xFF00FFF0) {
- case 0x4100C240:
- target->driver = "LPC43xx Cortex-M4";
- break;
- case 0x4100C200:
- target->driver = "LPC43xx Cortex-M0";
- break;
- default:
- target->driver = "LPC43xx <Unknown>";
- }
- return true;
+ case 0x4906002B: /* Parts with on-chip flash */
+ switch (cpuid & 0xFF00FFF0) {
+ case 0x4100C240:
+ target->driver = "LPC43xx Cortex-M4";
+ if (cpuid == 0x410FC241)
+ {
+ /* LPC4337 */
+ target->xml_mem_map = lpc4337_xml_memory_map;
+ target->flash_erase = lpc43xx_flash_erase;
+ target->flash_write = lpc43xx_flash_write;
+ target_add_commands(target, lpc43xx_cmd_list, "LPC43xx");
+ }
+ break;
+ case 0x4100C200:
+ target->driver = "LPC43xx Cortex-M0";
+ break;
+ default:
+ target->driver = "LPC43xx <Unknown>";
+ }
+ return true;
+ case 0x5906002B: /* Flashless parts */
+ case 0x6906002B:
+ switch (cpuid & 0xFF00FFF0) {
+ case 0x4100C240:
+ target->driver = "LPC43xx Cortex-M4";
+ break;
+ case 0x4100C200:
+ target->driver = "LPC43xx Cortex-M0";
+ break;
+ default:
+ target->driver = "LPC43xx <Unknown>";
+ }
+ return true;
}
return false;
}
+static bool lpc43xx_cmd_erase(target *target)
+{
+ uint32_t bank = 0;
+ struct flash_program flash_pgm;
+
+ lpc43xx_flash_init(target);
+
+ for (bank = 0; bank < FLASH_NUM_BANK; bank++)
+ {
+ flash_pgm.p.command = IAP_CMD_PREPARE;
+ flash_pgm.p.params.prepare.start_sector = 0;
+ flash_pgm.p.params.prepare.end_sector = FLASH_NUM_SECTOR-1;
+ flash_pgm.p.params.prepare.flash_bank = bank;
+ flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS;
+ lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p));
+ if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
+ return false;
+ }
+
+ flash_pgm.p.command = IAP_CMD_ERASE;
+ flash_pgm.p.params.erase.start_sector = 0;
+ flash_pgm.p.params.prepare.end_sector = FLASH_NUM_SECTOR-1;
+ flash_pgm.p.params.erase.cpu_clk_khz = CPU_CLK_KHZ;
+ flash_pgm.p.params.erase.flash_bank = bank;
+ flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS;
+ lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p));
+ if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS)
+ {
+ return false;
+ }
+ }
+
+ gdb_outf("Erase OK.\n");
+
+ return true;
+}
+
+static int lpc43xx_flash_init(struct target_s *target)
+{
+ struct flash_program flash_pgm;
+
+ /* Initialize flash IAP */
+ flash_pgm.p.command = IAP_CMD_INIT;
+ flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS;
+ lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p));
+ if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+/**
+ * @brief find a sector number given linear offset
+ */
+static int32_t flash_bank(uint32_t addr)
+{
+ int32_t retVal;
+
+ if (addr >= FLASH_BANK_A_BASE && addr < (FLASH_BANK_A_BASE+FLASH_BANK_A_SIZE))
+ {
+ retVal = 0;
+ }
+ else if (addr >= FLASH_BANK_B_BASE && addr < (FLASH_BANK_B_BASE+FLASH_BANK_B_SIZE))
+ {
+ retVal = 1;
+ }
+ else
+ {
+ retVal = -1;
+ }
+
+ return retVal;
+}
+
+/**
+ * @brief find a sector number given linear offset
+ */
+static int32_t sector_number(uint32_t addr)
+{
+ int32_t retVal = 0;
+ int32_t bank = flash_bank(addr);
+
+ if (bank == 0)
+ {
+ addr = addr - FLASH_BANK_A_BASE;
+ }
+ else if (bank == 1)
+ {
+ addr = addr - FLASH_BANK_B_BASE;
+ }
+ else
+ {
+ retVal = -1;
+ }
+
+ if (retVal != -1)
+ {
+ /* from 47.5 "Sector numbers" (page 1218) UM10503.pdf (Rev 1.6) */
+ if (addr < FLASH_LARGE_SECTOR_OFFSET)
+ {
+ retVal = addr >> 13;
+ }
+ else
+ {
+ retVal = 8 + ((addr - FLASH_LARGE_SECTOR_OFFSET) >> 16);
+ }
+ }
+
+ return retVal;
+}
+
+static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len)
+{
+ uint32_t regs[target->regs_size / 4];
+ uint32_t iap_entry;
+
+ target_mem_read_words(target, &iap_entry, IAP_ENTRYPOINT_LOCATION, sizeof(iap_entry));
+
+ /* fill out the remainder of the parameters and copy the structure to RAM */
+ param->opcode = ARM_THUMB_BREAKPOINT; /* breakpoint */
+ param->pad0 = 0x0000; /* pad */
+ target_mem_write_words(target, IAP_RAM_BASE, (void *)param, param_len);
+
+ /* set up for the call to the IAP ROM */
+ target_regs_read(target, regs);
+ regs[0] = IAP_RAM_BASE + offsetof(struct flash_param, command);
+ regs[1] = IAP_RAM_BASE + offsetof(struct flash_param, result);
+
+ regs[R_MSP] = IAP_RAM_BASE + IAP_RAM_SIZE;
+ regs[R_LR] = IAP_RAM_BASE | 1;
+ regs[R_PC] = iap_entry;
+ target_regs_write(target, regs);
+
+ /* start the target and wait for it to halt again */
+ target_halt_resume(target, 0);
+ while (!target_halt_wait(target));
+
+ /* copy back just the parameters structure */
+ target_mem_read_words(target, (void *)param, IAP_RAM_BASE, sizeof(struct flash_param));
+}
+
+static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len)
+{
+ struct flash_program flash_pgm;
+
+ /* prepare the sector(s) to be erased */
+ flash_pgm.p.command = IAP_CMD_PREPARE;
+ flash_pgm.p.params.prepare.start_sector = sector_number(addr);
+ flash_pgm.p.params.prepare.end_sector = sector_number(addr+len);
+ flash_pgm.p.params.prepare.flash_bank = flash_bank(addr);
+ flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS;
+
+ lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p));
+ if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
+ return -1;
+ }
+
+ return 0;
+}
+
+ static int
+lpc43xx_flash_erase(struct target_s *target, uint32_t addr, int len)
+{
+ struct flash_program flash_pgm;
+
+ /* min block size */
+ if (addr % 8192)
+ {
+ return -1;
+ }
+
+ /* init */
+ if (lpc43xx_flash_init(target))
+ {
+ return -1;
+ }
+
+ /* prepare... */
+ if (lpc43xx_flash_prepare(target, addr, len))
+ {
+ return -1;
+ }
+
+ /* and now erase them */
+ flash_pgm.p.command = IAP_CMD_ERASE;
+ flash_pgm.p.params.erase.start_sector = sector_number(addr);
+ flash_pgm.p.params.erase.end_sector = sector_number(addr+len);
+ flash_pgm.p.params.erase.cpu_clk_khz = CPU_CLK_KHZ;
+ flash_pgm.p.params.erase.flash_bank = flash_bank(addr);
+ flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS;
+ lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p));
+ if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
+ return -1;
+ }
+
+ /* check erase ok */
+ flash_pgm.p.command = IAP_CMD_BLANKCHECK;
+ flash_pgm.p.params.blank_check.start_sector = sector_number(addr);
+ 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.result[0] = IAP_STATUS_CMD_SUCCESS;
+ lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p));
+ if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len)
+{
+ unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE;
+ unsigned last_chunk = (dest + len - 1) / IAP_PGM_CHUNKSIZE;
+ unsigned chunk_offset = dest % IAP_PGM_CHUNKSIZE;
+ unsigned chunk;
+ struct flash_program flash_pgm;
+
+ for (chunk = first_chunk; chunk <= last_chunk; chunk++)
+ {
+
+ /* first and last chunk may require special handling */
+ if ((chunk == first_chunk) || (chunk == last_chunk)) {
+
+ /* fill with all ff to avoid sector rewrite corrupting other writes */
+ memset(flash_pgm.data, 0xff, sizeof(flash_pgm.data));
+
+ /* copy as much as fits */
+ int copylen = IAP_PGM_CHUNKSIZE - chunk_offset;
+ if (copylen > len)
+ copylen = len;
+
+ memcpy(flash_pgm.data + chunk_offset, src, copylen);
+
+ /* update to suit */
+ len -= copylen;
+ src += copylen;
+ chunk_offset = 0;
+ } else {
+
+ /* interior chunk, must be aligned and full-sized */
+ memcpy(flash_pgm.data, src, IAP_PGM_CHUNKSIZE);
+ len -= IAP_PGM_CHUNKSIZE;
+ src += IAP_PGM_CHUNKSIZE;
+ }
+
+ /* prepare... */
+ if (lpc43xx_flash_prepare(target, chunk * IAP_PGM_CHUNKSIZE, IAP_PGM_CHUNKSIZE))
+ {
+ return -1;
+ }
+
+ /* copy buffer into target memory */
+ target_mem_write_words(target,
+ IAP_RAM_BASE + offsetof(struct flash_program, data),
+ (uint32_t*)flash_pgm.data, sizeof(flash_pgm.data));
+
+ /* set the destination address and program */
+ flash_pgm.p.command = IAP_CMD_PROGRAM;
+ flash_pgm.p.params.program.dest = chunk * IAP_PGM_CHUNKSIZE;
+ flash_pgm.p.params.program.source = IAP_RAM_BASE + offsetof(struct flash_program, data);
+ flash_pgm.p.params.program.byte_count = IAP_PGM_CHUNKSIZE;
+ flash_pgm.p.params.program.cpu_clk_khz = CPU_CLK_KHZ;
+ flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS;
+ lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm));
+ if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
+ return -1;
+ }
+
+ /* special command to compute/write magic vector for signature */
+ if (chunk == first_chunk)
+ {
+ flash_pgm.p.command = IAP_CMD_SET_ACTIVE_BANK;
+ flash_pgm.p.params.make_active.flash_bank = flash_bank(dest);
+ flash_pgm.p.params.make_active.cpu_clk_khz = CPU_CLK_KHZ;
+ flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS;
+ lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm));
+ if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) {
+ return -1;
+ }
+ }
+
+ }
+
+ return 0;
+}
diff --git a/src/main.c b/src/main.c
index 4921aed..809d4bf 100644
--- a/src/main.c
+++ b/src/main.c
@@ -18,7 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* Provides main entry point. Initialise subsystems and enter GDB
+/* Provides main entry point. Initialise subsystems and enter GDB
* protocol loop.
*/
diff --git a/src/platforms/f4discovery/Makefile.inc b/src/platforms/f4discovery/Makefile.inc
index f67b278..88575bb 100644
--- a/src/platforms/f4discovery/Makefile.inc
+++ b/src/platforms/f4discovery/Makefile.inc
@@ -7,7 +7,7 @@ CFLAGS += -Istm32/include -mcpu=cortex-m4 -mthumb \
-DSTM32F4 -DF4DISCOVERY -I../libopencm3/include \
-Iplatforms/stm32
-LDFLAGS = -lopencm3_stm32f4 -Wl,--defsym,_stack=0x20020000 \
+LDFLAGS = -lopencm3_stm32f4 -Wl,--defsym,_stack=0x20006000 \
-Wl,-T,platforms/stm32/f4discovery.ld -nostartfiles -lc -lnosys \
-Wl,-Map=mapfile -mthumb -mcpu=cortex-m4 -Wl,-gc-sections \
-mfloat-abi=hard -mfpu=fpv4-sp-d16 \
diff --git a/src/platforms/f4discovery/platform.c b/src/platforms/f4discovery/platform.c
index 645a3c5..6ee36bd 100644
--- a/src/platforms/f4discovery/platform.c
+++ b/src/platforms/f4discovery/platform.c
@@ -53,7 +53,7 @@ int platform_init(void)
scb_reset_core();
}
- rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]);
+ rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_48MHZ]);
/* Enable peripherals */
rcc_peripheral_enable_clock(&RCC_AHB2ENR, RCC_AHB2ENR_OTGFSEN);
diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h
index c1423b6..5523b9c 100644
--- a/src/platforms/f4discovery/platform.h
+++ b/src/platforms/f4discovery/platform.h
@@ -195,23 +195,23 @@ void uart_usb_buf_drain(uint8_t ep);
#define vasprintf vasiprintf
#ifdef INLINE_GPIO
-static inline void _gpio_set(u32 gpioport, u16 gpios)
+static inline void _gpio_set(uint32_t gpioport, uint16_t gpios)
{
GPIO_BSRR(gpioport) = gpios;
GPIO_BSRR(gpioport) = gpios;
}
#define gpio_set _gpio_set
-static inline void _gpio_clear(u32 gpioport, u16 gpios)
+static inline void _gpio_clear(uint32_t gpioport, uint16_t gpios)
{
GPIO_BSRR(gpioport) = gpios<<16;
GPIO_BSRR(gpioport) = gpios<<16;
}
#define gpio_clear _gpio_clear
-static inline u16 _gpio_get(u32 gpioport, u16 gpios)
+static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios)
{
- return (u16)GPIO_IDR(gpioport) & gpios;
+ return (uint16_t)GPIO_IDR(gpioport) & gpios;
}
#define gpio_get _gpio_get
#endif
diff --git a/src/platforms/libftdi/jtagtap.c b/src/platforms/libftdi/jtagtap.c
index c914646..91f6ae2 100644
--- a/src/platforms/libftdi/jtagtap.c
+++ b/src/platforms/libftdi/jtagtap.c
@@ -67,7 +67,7 @@ void jtagtap_reset(void)
jtagtap_soft_reset();
}
-void jtagtap_srst(void)
+void jtagtap_srst(bool assert)
{
platform_buffer_flush();
//ftdi_write_data(ftdic, "\x80\x88\xAB", 3);
@@ -84,7 +84,7 @@ jtagtap_tms_seq(uint32_t MS, int ticks)
//jtagtap_next(MS & 1, 1);
tmp[1] = ticks<7?ticks-1:6;
tmp[2] = 0x80 | (MS & 0x7F);
-
+
// assert(ftdi_write_data(ftdic, tmp, 3) == 3);
platform_buffer_write(tmp, 3);
MS >>= 7; ticks -= 7;
@@ -93,7 +93,7 @@ jtagtap_tms_seq(uint32_t MS, int ticks)
#endif
#ifndef PROVIDE_GENERIC_TAP_TDI_SEQ
-void
+void
jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks)
{
char *tmp;
@@ -119,7 +119,7 @@ jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks)
tmp[index++] = rticks - 1;
tmp[index++] = *DI;
}
-
+
if(final_tms) {
tmp[index++] = 0x4B;
tmp[index++] = 0;
@@ -131,7 +131,7 @@ jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks)
#endif
#ifndef PROVIDE_GENERIC_TAP_TDI_TDO_SEQ
-void
+void
jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks)
{
uint8_t *tmp;
@@ -159,7 +159,7 @@ jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int
tmp[index++] = rticks - 1;
tmp[index++] = *DI;
}
-
+
if(final_tms) {
rsize++;
tmp[index++] = 0x6B;
@@ -176,7 +176,7 @@ jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int
printf("\n");*/
index = 0;
if(final_tms) rsize--;
-
+
while(rsize--) {
/*if(rsize) printf("%02X ", tmp[index]);*/
*DO++ = tmp[index++];
diff --git a/src/platforms/libftdi/platform.c b/src/platforms/libftdi/platform.c
index ec2a8f1..dc57a45 100644
--- a/src/platforms/libftdi/platform.c
+++ b/src/platforms/libftdi/platform.c
@@ -122,7 +122,7 @@ static struct cable_desc_s {
};
int platform_init(int argc, char **argv)
-{
+{
int err;
int c;
int index = 0;
@@ -167,40 +167,40 @@ int platform_init(int argc, char **argv)
ftdic = NULL;
}
if((ftdic = ftdi_new()) == NULL) {
- fprintf(stderr, "ftdi_new: %s\n",
+ fprintf(stderr, "ftdi_new: %s\n",
ftdi_get_error_string(ftdic));
abort();
}
if((err = ftdi_set_interface(ftdic, cable_desc[index].interface)) != 0) {
- fprintf(stderr, "ftdi_set_interface: %d: %s\n",
+ fprintf(stderr, "ftdi_set_interface: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
if((err = ftdi_usb_open_desc(
ftdic, cable_desc[index].vendor, cable_desc[index].product,
cable_desc[index].description, serial)) != 0) {
- fprintf(stderr, "unable to open ftdi device: %d (%s)\n",
+ fprintf(stderr, "unable to open ftdi device: %d (%s)\n",
err, ftdi_get_error_string(ftdic));
abort();
}
if((err = ftdi_set_latency_timer(ftdic, 1)) != 0) {
- fprintf(stderr, "ftdi_set_latency_timer: %d: %s\n",
+ fprintf(stderr, "ftdi_set_latency_timer: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
if((err = ftdi_set_baudrate(ftdic, 1000000)) != 0) {
- fprintf(stderr, "ftdi_set_baudrate: %d: %s\n",
+ fprintf(stderr, "ftdi_set_baudrate: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
if((err = ftdi_usb_purge_buffers(ftdic)) != 0) {
- fprintf(stderr, "ftdi_set_baudrate: %d: %s\n",
+ fprintf(stderr, "ftdi_set_baudrate: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
if((err = ftdi_write_data_set_chunksize(ftdic, BUF_SIZE)) != 0) {
- fprintf(stderr, "ftdi_write_data_set_chunksize: %d: %s\n",
+ fprintf(stderr, "ftdi_write_data_set_chunksize: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
@@ -216,8 +216,8 @@ int platform_init(int argc, char **argv)
assert(gdb_if_init() == 0);
jtag_scan(NULL);
-
- return 0;
+
+ return 0;
}
void platform_buffer_flush(void)
@@ -250,9 +250,9 @@ int vasprintf(char **strp, const char *fmt, va_list ap)
int size = 128, ret = 0;
*strp = malloc(size);
- while(*strp && ((ret = vsnprintf(*strp, size, fmt, ap)) == size))
+ while(*strp && ((ret = vsnprintf(*strp, size, fmt, ap)) == size))
*strp = realloc(*strp, size <<= 1);
-
+
return ret;
}
#endif
diff --git a/src/platforms/libftdi/swdptap.c b/src/platforms/libftdi/swdptap.c
index be329d8..cd3582b 100644
--- a/src/platforms/libftdi/swdptap.c
+++ b/src/platforms/libftdi/swdptap.c
@@ -40,7 +40,7 @@ int swdptap_init(void)
assert(ftdic != NULL);
if((err = ftdi_set_bitmode(ftdic, 0xAB, BITMODE_BITBANG)) != 0) {
- fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
+ fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
@@ -49,11 +49,11 @@ int swdptap_init(void)
/* This must be investigated in more detail.
* As described in STM32 Reference Manual... */
- swdptap_seq_out(0xFFFF, 16);
+ swdptap_seq_out(0xFFFF, 16);
swdptap_reset();
- swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */
+ swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */
swdptap_reset();
- swdptap_seq_out(0, 16);
+ swdptap_seq_out(0, 16);
return 0;
}
@@ -85,7 +85,7 @@ static void swdptap_turnaround(uint8_t dir)
assert(ftdi_set_bitmode(ftdic, 0xAB, BITMODE_BITBANG) == 0);
}
-static uint8_t swdptap_bit_in(void)
+static uint8_t swdptap_bit_in(void)
{
uint8_t ret;
diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c
index 3bd0816..214625e 100644
--- a/src/platforms/native/platform.c
+++ b/src/platforms/native/platform.c
@@ -82,7 +82,6 @@ int platform_init(void)
gpio_set_mode(JTAG_PORT, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL,
TMS_PIN | TCK_PIN | TDI_PIN);
-
/* This needs some fixing... */
/* Toggle required to sort out line drivers... */
gpio_port_write(GPIOA, 0x8100);
@@ -99,6 +98,25 @@ int platform_init(void)
* to release the device from reset if this floats. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO7);
+ /* Enable SRST output. Original uses a NPN to pull down, so setting the
+ * output HIGH asserts. Mini is directly connected so use open drain output
+ * and set LOW to assert.
+ */
+ platform_srst_set_val(false);
+ gpio_set_mode(SRST_PORT, GPIO_MODE_OUTPUT_50_MHZ,
+ (platform_hwversion() == 0
+ ? GPIO_CNF_OUTPUT_PUSHPULL
+ : GPIO_CNF_OUTPUT_OPENDRAIN),
+ SRST_PIN);
+
+ /* Enable internal pull-up on PWR_BR so that we don't drive
+ TPWR locally or inadvertently supply power to the target. */
+ if (platform_hwversion () > 0) {
+ gpio_set (PWR_BR_PORT, PWR_BR_PIN);
+ gpio_set_mode(PWR_BR_PORT, GPIO_MODE_INPUT,
+ GPIO_CNF_INPUT_PULL_UPDOWN,
+ PWR_BR_PIN);
+ }
/* Setup heartbeat timer */
systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8);
@@ -122,10 +140,19 @@ int platform_init(void)
usbuart_init();
jtag_scan(NULL);
-
+
return 0;
}
+void platform_srst_set_val(bool assert)
+{
+ if (platform_hwversion() == 0) {
+ gpio_set_val(SRST_PORT, SRST_PIN, assert);
+ } else {
+ gpio_set_val(SRST_PORT, SRST_PIN, !assert);
+ }
+}
+
void platform_delay(uint32_t delay)
{
timeout_counter = delay;
@@ -249,15 +276,15 @@ const char *platform_target_voltage(void)
return gpio_get(GPIOB, GPIO0) ? "OK" : "ABSENT!";
static char ret[] = "0.0V";
- const u8 channel = 8;
- adc_set_regular_sequence(ADC1, 1, (u8*)&channel);
+ const uint8_t channel = 8;
+ adc_set_regular_sequence(ADC1, 1, (uint8_t*)&channel);
adc_start_conversion_direct(ADC1);
/* Wait for end of conversion. */
while (!adc_eoc(ADC1));
- u32 val = adc_read_regular(ADC1) * 99; /* 0-4095 */
+ uint32_t val = adc_read_regular(ADC1) * 99; /* 0-4095 */
ret[0] = '0' + val / 81910;
ret[2] = '0' + (val / 8191) % 10;
diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h
index eb91f8b..62d565b 100644
--- a/src/platforms/native/platform.h
+++ b/src/platforms/native/platform.h
@@ -51,7 +51,8 @@ extern usbd_device *usbdev;
* LED2 = PB11 (Red LED : Error)
*
* TPWR = RB0 (input) -- analogue on mini design ADC1, ch8
- * nTRST = PB1
+ * nTRST = PB1 [blackmagic]
+ * PWR_BR = PB1 [blackmagic_mini] -- supply power to the target, active low
* SRST_OUT = PA2
* TDI = PA3
* TMS = PA4 (input for SWDP)
@@ -60,7 +61,7 @@ extern usbd_device *usbdev;
* nSRST = PA7 (input)
*
* USB cable pull-up: PA8
- * USB VBUS detect: PB13 -- New on mini design.
+ * USB VBUS detect: PB13 -- New on mini design.
* Enable pull up for compatibility.
* Force DFU mode button: PB12
*/
@@ -83,6 +84,8 @@ extern usbd_device *usbdev;
#define TRST_PORT GPIOB
#define TRST_PIN GPIO1
+#define PWR_BR_PORT GPIOB
+#define PWR_BR_PIN GPIO1
#define SRST_PORT GPIOA
#define SRST_PIN GPIO2
@@ -113,12 +116,15 @@ extern usbd_device *usbdev;
gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, \
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN);
+#define SRST_SET_VAL(x) \
+ platform_srst_set_val(x)
+
#define USB_DRIVER stm32f103_usb_driver
#define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ
#define USB_ISR usb_lp_can_rx0_isr
/* Interrupt priorities. Low numbers are high priority.
* For now USART1 preempts USB which may spin while buffer is drained.
- * TIM3 is used for traceswo capture and must be highest priority.
+ * TIM3 is used for traceswo capture and must be highest priority.
*/
#define IRQ_PRI_USB (2 << 4)
#define IRQ_PRI_USBUSART (1 << 4)
@@ -165,14 +171,14 @@ extern const char *morse_msg;
#define SET_ERROR_STATE(state) {gpio_set_val(LED_PORT, LED_ERROR, state);}
#define PLATFORM_SET_FATAL_ERROR_RECOVERY() {setjmp(fatal_error_jmpbuf);}
-#define PLATFORM_FATAL_ERROR(error) { \
+#define PLATFORM_FATAL_ERROR(error) do { \
if(running_status) gdb_putpacketz("X1D"); \
else gdb_putpacketz("EFF"); \
running_status = 0; \
target_list_free(); \
morse("TARGET LOST.", 1); \
longjmp(fatal_error_jmpbuf, (error)); \
-}
+} while (0)
int platform_init(void);
void morse(const char *msg, char repeat);
@@ -195,21 +201,21 @@ void uart_usb_buf_drain(uint8_t ep);
#define vasprintf vasiprintf
#ifdef INLINE_GPIO
-static inline void _gpio_set(u32 gpioport, u16 gpios)
+static inline void _gpio_set(uint32_t gpioport, uint16_t gpios)
{
GPIO_BSRR(gpioport) = gpios;
}
#define gpio_set _gpio_set
-static inline void _gpio_clear(u32 gpioport, u16 gpios)
+static inline void _gpio_clear(uint32_t gpioport, uint16_t gpios)
{
GPIO_BRR(gpioport) = gpios;
}
#define gpio_clear _gpio_clear
-static inline u16 _gpio_get(u32 gpioport, u16 gpios)
+static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios)
{
- return (u16)GPIO_IDR(gpioport) & gpios;
+ return (uint16_t)GPIO_IDR(gpioport) & gpios;
}
#define gpio_get _gpio_get
#endif
@@ -219,3 +225,4 @@ static inline u16 _gpio_get(u32 gpioport, u16 gpios)
#define disconnect_usb() gpio_set_mode(USB_PU_PORT, GPIO_MODE_INPUT, 0, USB_PU_PIN);
void assert_boot_pin(void);
void setup_vbus_irq(void);
+void platform_srst_set_val(bool assert);
diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c
index e8435b9..03509ea 100644
--- a/src/platforms/stlink/platform.c
+++ b/src/platforms/stlink/platform.c
@@ -92,18 +92,23 @@ int platform_init(void)
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO8);
}
/* Setup GPIO ports */
- gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ,
+ gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN);
- gpio_set_mode(TCK_PORT, GPIO_MODE_OUTPUT_50_MHZ,
+ gpio_set_mode(TCK_PORT, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, TCK_PIN);
- gpio_set_mode(TDI_PORT, GPIO_MODE_OUTPUT_50_MHZ,
+ gpio_set_mode(TDI_PORT, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, TDI_PIN);
-
- gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ,
+ uint16_t srst_pin = platform_hwversion() == 0 ?
+ SRST_PIN_V1 : SRST_PIN_V2;
+ gpio_set(SRST_PORT, srst_pin);
+ gpio_set_mode(SRST_PORT, GPIO_MODE_OUTPUT_50_MHZ,
+ GPIO_CNF_OUTPUT_OPENDRAIN, srst_pin);
+
+ gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run);
/* Setup heartbeat timer */
- systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8);
+ systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8);
systick_set_reload(900000); /* Interrupt us at 10 Hz */
SCB_SHPR(11) &= ~((15 << 4) & 0xff);
SCB_SHPR(11) |= ((14 << 4) & 0xff);
@@ -117,7 +122,7 @@ int platform_init(void)
cdcacm_init();
jtag_scan(NULL);
-
+
return 0;
}
@@ -127,12 +132,22 @@ void platform_delay(uint32_t delay)
while(timeout_counter);
}
+void platform_srst_set_val(bool assert)
+{
+ uint16_t pin;
+ pin = platform_hwversion() == 0 ? SRST_PIN_V1 : SRST_PIN_V2;
+ if (assert)
+ gpio_clear(SRST_PORT, pin);
+ else
+ gpio_set(SRST_PORT, pin);
+}
+
void sys_tick_handler(void)
{
- if(running_status)
+ if(running_status)
gpio_toggle(LED_PORT, led_idle_run);
- if(timeout_counter)
+ if(timeout_counter)
timeout_counter--;
}
diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h
index 09fab96..a9e405b 100644
--- a/src/platforms/stlink/platform.h
+++ b/src/platforms/stlink/platform.h
@@ -59,7 +59,7 @@ extern usbd_device *usbdev;
* nSRST = PA7 (input)
*
* USB cable pull-up: PA8
- * USB VBUS detect: PB13 -- New on mini design.
+ * USB VBUS detect: PB13 -- New on mini design.
* Enable pull up for compatibility.
* Force DFU mode button: PB12
*/
@@ -79,6 +79,10 @@ extern usbd_device *usbdev;
#define SWDIO_PIN TMS_PIN
#define SWCLK_PIN TCK_PIN
+#define SRST_PORT GPIOB
+#define SRST_PIN_V1 GPIO1
+#define SRST_PIN_V2 GPIO0
+
#define LED_PORT GPIOA
/* Use PC14 for a "dummy" uart led. So we can observere at least with scope*/
#define LED_PORT_UART GPIOC
@@ -98,6 +102,9 @@ extern usbd_device *usbdev;
gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, \
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN);
+#define SRST_SET_VAL(x) \
+ platform_srst_set_val(x)
+
#define USB_DRIVER stm32f103_usb_driver
#define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ
#define USB_ISR usb_lp_can_rx0_isr
@@ -145,18 +152,19 @@ extern uint16_t led_idle_run;
#define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, led_idle_run, state);}
#define PLATFORM_SET_FATAL_ERROR_RECOVERY() {setjmp(fatal_error_jmpbuf);}
-#define PLATFORM_FATAL_ERROR(error) { \
+#define PLATFORM_FATAL_ERROR(error) do { \
if(running_status) gdb_putpacketz("X1D"); \
else gdb_putpacketz("EFF"); \
running_status = 0; \
target_list_free(); \
longjmp(fatal_error_jmpbuf, (error)); \
-}
+} while (0)
int platform_init(void);
void morse(const char *msg, char repeat);
const char *platform_target_voltage(void);
void platform_delay(uint32_t delay);
+void platform_srst_set_val(bool assert);
/* <cdcacm.c> */
void cdcacm_init(void);
@@ -173,21 +181,21 @@ void uart_usb_buf_drain(uint8_t ep);
#define vasprintf vasiprintf
#ifdef INLINE_GPIO
-static inline void _gpio_set(u32 gpioport, u16 gpios)
+static inline void _gpio_set(uint32_t gpioport, uint16_t gpios)
{
GPIO_BSRR(gpioport) = gpios;
}
#define gpio_set _gpio_set
-static inline void _gpio_clear(u32 gpioport, u16 gpios)
+static inline void _gpio_clear(uint32_t gpioport, uint16_t gpios)
{
GPIO_BRR(gpioport) = gpios;
}
#define gpio_clear _gpio_clear
-static inline u16 _gpio_get(u32 gpioport, u16 gpios)
+static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios)
{
- return (u16)GPIO_IDR(gpioport) & gpios;
+ return (uint16_t)GPIO_IDR(gpioport) & gpios;
}
#define gpio_get _gpio_get
#endif
diff --git a/src/platforms/stlink/usbdfu.c b/src/platforms/stlink/usbdfu.c
index f688c1c..76a19b0 100644
--- a/src/platforms/stlink/usbdfu.c
+++ b/src/platforms/stlink/usbdfu.c
@@ -40,13 +40,13 @@ static int stlink_test_nrst(void)
* 11 for ST-Link V1, e.g. on VL Discovery, tag as rev 0
* 10 for ST-Link V2, e.g. on F4 Discovery, tag as rev 1
*/
- rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
- gpio_set_mode(GPIOC, GPIO_MODE_INPUT,
- GPIO_CNF_INPUT_PULL_UPDOWN, GPIO14 | GPIO13);
- gpio_set(GPIOC, GPIO14 | GPIO13);
- for (i = 0; i < 100; i++)
- rev = (~(gpio_get(GPIOC, GPIO14 | GPIO13)) >> 13) & 3;
-
+ for (i = 0; i < 0x200; i++) {
+ rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
+ gpio_set_mode(GPIOC, GPIO_MODE_INPUT,
+ GPIO_CNF_INPUT_PULL_UPDOWN, GPIO14 | GPIO13);
+ gpio_set(GPIOC, GPIO14 | GPIO13);
+ rev = (~(gpio_get(GPIOC, GPIO14 | GPIO13)) >> 13) & 3;
+ }
switch (rev) {
case 0:
pin = GPIO1;
diff --git a/src/platforms/stm32/cdcacm.c b/src/platforms/stm32/cdcacm.c
index 93b0f33..010117f 100644
--- a/src/platforms/stm32/cdcacm.c
+++ b/src/platforms/stm32/cdcacm.c
@@ -480,7 +480,7 @@ int cdcacm_get_dtr(void)
return cdcacm_gdb_dtr;
}
-static void cdcacm_set_config(usbd_device *dev, u16 wValue)
+static void cdcacm_set_config(usbd_device *dev, uint16_t wValue)
{
configured = wValue;
@@ -536,8 +536,10 @@ void cdcacm_init(void)
get_dev_unique_id(serial_no);
- usbdev = usbd_init(&USB_DRIVER, &dev, &config, usb_strings, sizeof(usb_strings)/sizeof(char *));
- usbd_set_control_buffer_size(usbdev, sizeof(usbd_control_buffer));
+ usbdev = usbd_init(&USB_DRIVER, &dev, &config, usb_strings,
+ sizeof(usb_strings)/sizeof(char *),
+ usbd_control_buffer, sizeof(usbd_control_buffer));
+
usbd_register_set_config_callback(usbdev, cdcacm_set_config);
nvic_set_priority(USB_IRQ, IRQ_PRI_USB);
diff --git a/src/platforms/stm32/dfu_f1.c b/src/platforms/stm32/dfu_f1.c
index 827712d..08cbb02 100644
--- a/src/platforms/stm32/dfu_f1.c
+++ b/src/platforms/stm32/dfu_f1.c
@@ -48,7 +48,7 @@ void dfu_flash_program_buffer(uint32_t baseaddr, void *buf, int len)
{
for(int i = 0; i < len; i += 2)
flash_program_half_word(baseaddr + i,
- *(u16*)(buf+i));
+ *(uint16_t*)(buf+i));
}
uint32_t dfu_poll_timeout(uint8_t cmd, uint32_t addr, uint16_t blocknum)
@@ -77,12 +77,12 @@ void dfu_protect_enable(void)
void dfu_jump_app_if_valid(void)
{
/* Boot the application if it's valid */
- if((*(volatile u32*)APP_ADDRESS & 0x2FFE0000) == 0x20000000) {
+ if((*(volatile uint32_t*)APP_ADDRESS & 0x2FFE0000) == 0x20000000) {
/* Set vector table base address */
SCB_VTOR = APP_ADDRESS & 0x1FFFFF; /* Max 2 MByte Flash*/
/* Initialise master stack pointer */
asm volatile ("msr msp, %0"::"g"
- (*(volatile u32*)APP_ADDRESS));
+ (*(volatile uint32_t*)APP_ADDRESS));
/* Jump to application */
(*(void(**)())(APP_ADDRESS + 4))();
}
diff --git a/src/platforms/stm32/dfu_f4.c b/src/platforms/stm32/dfu_f4.c
index 960ec23..1421b19 100644
--- a/src/platforms/stm32/dfu_f4.c
+++ b/src/platforms/stm32/dfu_f4.c
@@ -26,17 +26,17 @@
#include "usbdfu.h"
-static u32 sector_addr[] = {0x8000000, 0x8004000, 0x8008000, 0x800c000,
+static uint32_t sector_addr[] = {0x8000000, 0x8004000, 0x8008000, 0x800c000,
0x8010000, 0x8020000, 0x8040000, 0x8060000,
0x8080000, 0x80a0000, 0x80c0000, 0x80e0000,
0x8100000, 0};
-static u16 sector_erase_time[12]= {500, 500, 500, 500,
+static uint16_t sector_erase_time[12]= {500, 500, 500, 500,
1100,
2600, 2600, 2600, 2600, 2600, 2600, 2600};
-static u8 sector_num = 0xff;
+static uint8_t sector_num = 0xff;
/* Find the sector number for a given address*/
-static void get_sector_num(u32 addr)
+static void get_sector_num(uint32_t addr)
{
int i = 0;
while(sector_addr[i+1]) {
@@ -60,7 +60,7 @@ void dfu_flash_program_buffer(uint32_t baseaddr, void *buf, int len)
{
for(int i = 0; i < len; i += 4)
flash_program_word(baseaddr + i,
- *(u32*)(buf+i),
+ *(uint32_t*)(buf+i),
FLASH_PROGRAM_X32);
}
@@ -93,12 +93,12 @@ void dfu_jump_app_if_valid(void)
/* Boot the application if it's valid */
/* Vector table may be anywhere in 128 kByte RAM
CCM not handled*/
- if((*(volatile u32*)APP_ADDRESS & 0x2FFC0000) == 0x20000000) {
+ if((*(volatile uint32_t*)APP_ADDRESS & 0x2FFC0000) == 0x20000000) {
/* Set vector table base address */
SCB_VTOR = APP_ADDRESS & 0x1FFFFF; /* Max 2 MByte Flash*/
/* Initialise master stack pointer */
asm volatile ("msr msp, %0"::"g"
- (*(volatile u32*)APP_ADDRESS));
+ (*(volatile uint32_t*)APP_ADDRESS));
/* Jump to application */
(*(void(**)())(APP_ADDRESS + 4))();
}
diff --git a/src/platforms/stm32/dfucore.c b/src/platforms/stm32/dfucore.c
index 2786e9a..a01616f 100644
--- a/src/platforms/stm32/dfucore.c
+++ b/src/platforms/stm32/dfucore.c
@@ -34,19 +34,19 @@
usbd_device *usbdev;
/* We need a special large control buffer for this device: */
-u8 usbd_control_buffer[1024];
+uint8_t usbd_control_buffer[1024];
-static u32 max_address;
+static uint32_t max_address;
static enum dfu_state usbdfu_state = STATE_DFU_IDLE;
static char *get_dev_unique_id(char *serial_no);
static struct {
- u8 buf[sizeof(usbd_control_buffer)];
- u16 len;
- u32 addr;
- u16 blocknum;
+ uint8_t buf[sizeof(usbd_control_buffer)];
+ uint16_t len;
+ uint32_t addr;
+ uint16_t blocknum;
} prog;
const struct usb_device_descriptor dev = {
@@ -121,13 +121,13 @@ static const char *usb_strings[] = {
DFU_IFACE_STRING,
};
-static u32 get_le32(const void *vp)
+static uint32_t get_le32(const void *vp)
{
- const u8 *p = vp;
- return ((u32)p[3] << 24) + ((u32)p[2] << 16) + (p[1] << 8) + p[0];
+ const uint8_t *p = vp;
+ return ((uint32_t)p[3] << 24) + ((uint32_t)p[2] << 16) + (p[1] << 8) + p[0];
}
-static u8 usbdfu_getstatus(u32 *bwPollTimeout)
+static uint8_t usbdfu_getstatus(uint32_t *bwPollTimeout)
{
switch(usbdfu_state) {
case STATE_DFU_DNLOAD_SYNC:
@@ -157,7 +157,7 @@ usbdfu_getstatus_complete(usbd_device *dev, struct usb_setup_data *req)
flash_unlock();
if(prog.blocknum == 0) {
- u32 addr = get_le32(prog.buf + 1);
+ uint32_t addr = get_le32(prog.buf + 1);
if (addr < APP_ADDRESS ||
(addr >= max_address)) {
flash_lock();
@@ -171,7 +171,7 @@ usbdfu_getstatus_complete(usbd_device *dev, struct usb_setup_data *req)
prog.addr = addr;
}
} else {
- u32 baseaddr = prog.addr +
+ uint32_t baseaddr = prog.addr +
((prog.blocknum - 2) *
dfu_function.wTransferSize);
dfu_flash_program_buffer(baseaddr, prog.buf, prog.len);
@@ -193,7 +193,7 @@ usbdfu_getstatus_complete(usbd_device *dev, struct usb_setup_data *req)
}
static int usbdfu_control_request(usbd_device *dev,
- struct usb_setup_data *req, u8 **buf, u16 *len,
+ struct usb_setup_data *req, uint8_t **buf, uint16_t *len,
void (**complete)(usbd_device *dev, struct usb_setup_data *req))
{
(void)dev;
@@ -227,7 +227,7 @@ static int usbdfu_control_request(usbd_device *dev,
/* Upload not supported for now */
return 0;
case DFU_GETSTATUS: {
- u32 bwPollTimeout = 0; /* 24-bit integer in DFU class spec */
+ uint32_t bwPollTimeout = 0; /* 24-bit integer in DFU class spec */
(*buf)[0] = usbdfu_getstatus(&bwPollTimeout);
(*buf)[1] = bwPollTimeout & 0xFF;
@@ -255,8 +255,9 @@ void dfu_init(const usbd_driver *driver)
{
get_dev_unique_id(serial_no);
- usbdev = usbd_init(driver, &dev, &config, usb_strings, 4);
- usbd_set_control_buffer_size(usbdev, sizeof(usbd_control_buffer));
+ usbdev = usbd_init(driver, &dev, &config, usb_strings, 4,
+ usbd_control_buffer, sizeof(usbd_control_buffer));
+
usbd_register_control_callback(usbdev,
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
@@ -292,7 +293,7 @@ static char *get_dev_unique_id(char *s)
/* Calculated the upper flash limit from the exported data
in theparameter block*/
- max_address = (*(u32 *) FLASH_SIZE_R) <<10;
+ max_address = (*(uint32_t *) FLASH_SIZE_R) <<10;
/* Fetch serial number from chip's unique ID */
for(i = 0; i < 8; i++) {
s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0';
diff --git a/src/platforms/stm32/jtagtap.c b/src/platforms/stm32/jtagtap.c
index d6e298b..78dd300 100644
--- a/src/platforms/stm32/jtagtap.c
+++ b/src/platforms/stm32/jtagtap.c
@@ -50,13 +50,16 @@ void jtagtap_reset(void)
jtagtap_soft_reset();
}
-void jtagtap_srst(void)
+void jtagtap_srst(bool assert)
{
-#ifdef SRST_PORT
- volatile int i;
- gpio_set(SRST_PORT, SRST_PIN);
- for(i = 0; i < 10000; i++) asm("nop");
- gpio_clear(SRST_PORT, SRST_PIN);
+ (void)assert;
+#ifdef SRST_SET_VAL
+ SRST_SET_VAL(assert);
+ if(assert) {
+ int i;
+ for(i = 0; i < 10000; i++)
+ asm volatile("nop");
+ }
#endif
}
diff --git a/src/platforms/stm32/swdptap.c b/src/platforms/stm32/swdptap.c
index 72fb0f9..e7049d3 100644
--- a/src/platforms/stm32/swdptap.c
+++ b/src/platforms/stm32/swdptap.c
@@ -73,9 +73,9 @@ int swdptap_init(void)
/* This must be investigated in more detail.
* As described in STM32 Reference Manual... */
swdptap_reset();
- swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */
+ swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */
swdptap_reset();
- swdptap_seq_out(0, 16);
+ swdptap_seq_out(0, 16);
return 0;
}
@@ -132,7 +132,7 @@ void swdptap_seq_out(uint32_t MS, int ticks)
while(ticks--) {
swdptap_bit_out(MS & 1);
- MS >>= 1;
+ MS >>= 1;
}
}
@@ -146,7 +146,7 @@ void swdptap_seq_out_parity(uint32_t MS, int ticks)
while(ticks--) {
swdptap_bit_out(MS & 1);
parity ^= MS;
- MS >>= 1;
+ MS >>= 1;
}
swdptap_bit_out(parity & 1);
}
diff --git a/src/platforms/swlink/platform.c b/src/platforms/swlink/platform.c
index 1aa45b1..1b45cfb 100644
--- a/src/platforms/swlink/platform.c
+++ b/src/platforms/swlink/platform.c
@@ -86,7 +86,7 @@ int platform_init(void)
AFIO_MAPR = data;
/* Setup heartbeat timer */
- systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8);
+ systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8);
systick_set_reload(900000); /* Interrupt us at 10 Hz */
SCB_SHPR(11) &= ~((15 << 4) & 0xff);
SCB_SHPR(11) |= ((14 << 4) & 0xff);
@@ -112,10 +112,10 @@ void platform_delay(uint32_t delay)
void sys_tick_handler(void)
{
- if(running_status)
+ if(running_status)
gpio_toggle(LED_PORT, led_idle_run);
- if(timeout_counter)
+ if(timeout_counter)
timeout_counter--;
}
diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h
index c7eaca5..d0c9618 100644
--- a/src/platforms/swlink/platform.h
+++ b/src/platforms/swlink/platform.h
@@ -53,7 +53,7 @@ extern usbd_device *usbdev;
* nSRST = PA7 (input)
*
* USB cable pull-up: PA8
- * USB VBUS detect: PB13 -- New on mini design.
+ * USB VBUS detect: PB13 -- New on mini design.
* Enable pull up for compatibility.
* Force DFU mode button: PB9 Low
*/
@@ -179,21 +179,21 @@ void uart_usb_buf_drain(uint8_t ep);
#define vasprintf vasiprintf
#ifdef INLINE_GPIO
-static inline void _gpio_set(u32 gpioport, u16 gpios)
+static inline void _gpio_set(uint32_t gpioport, uint16_t gpios)
{
GPIO_BSRR(gpioport) = gpios;
}
#define gpio_set _gpio_set
-static inline void _gpio_clear(u32 gpioport, u16 gpios)
+static inline void _gpio_clear(uint32_t gpioport, uint16_t gpios)
{
GPIO_BRR(gpioport) = gpios;
}
#define gpio_clear _gpio_clear
-static inline u16 _gpio_get(u32 gpioport, u16 gpios)
+static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios)
{
- return (u16)GPIO_IDR(gpioport) & gpios;
+ return (uint16_t)GPIO_IDR(gpioport) & gpios;
}
#define gpio_get _gpio_get
#endif
diff --git a/src/sam3x.c b/src/sam3x.c
index d348701..79dca3d 100644
--- a/src/sam3x.c
+++ b/src/sam3x.c
@@ -32,14 +32,12 @@
#include "gdb_packet.h"
static int sam3x_flash_erase(struct target_s *target, uint32_t addr, int len);
-static int sam3x_flash_write(struct target_s *target, uint32_t dest,
+static int sam3x_flash_write(struct target_s *target, uint32_t dest,
const uint8_t *src, int len);
static bool sam3x_cmd_gpnvm_get(target *t);
static bool sam3x_cmd_gpnvm_set(target *t, int argc, char *argv[]);
-static const char sam3x_driver_str[] = "Atmel SAM3X";
-
const struct command_s sam3x_cmd_list[] = {
{"gpnvm_get", (cmd_handler)sam3x_cmd_gpnvm_get, "Get GPVNM value"},
{"gpnvm_set", (cmd_handler)sam3x_cmd_gpnvm_set, "Set GPVNM bit"},
@@ -58,13 +56,25 @@ static const char sam3x_xml_memory_map[] = "<?xml version=\"1.0\"?>"
" <memory type=\"ram\" start=\"0x20000000\" length=\"0x200000\"/>"
"</memory-map>";
+static const char sam3n_xml_memory_map[] = "<?xml version=\"1.0\"?>"
+/* "<!DOCTYPE memory-map "
+ " PUBLIC \"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\""
+ " \"http://sourceware.org/gdb/gdb-memory-map.dtd\">"*/
+ "<memory-map>"
+ " <memory type=\"flash\" start=\"0x400000\" length=\"0x400000\">"
+ " <property name=\"blocksize\">0x100</property>"
+ " </memory>"
+ " <memory type=\"rom\" start=\"0x800000\" length=\"0x400000\"/>"
+ " <memory type=\"ram\" start=\"0x20000000\" length=\"0x200000\"/>"
+ "</memory-map>";
/* Enhanced Embedded Flash Controller (EEFC) Register Map */
-#define EEFC_BASE(x) (0x400E0A00+((x)*0x400))
-#define EEFC_FMR(x) (EEFC_BASE(x)+0x00)
-#define EEFC_FCR(x) (EEFC_BASE(x)+0x04)
-#define EEFC_FSR(x) (EEFC_BASE(x)+0x08)
-#define EEFC_FRR(x) (EEFC_BASE(x)+0x0C)
+#define SAM3N_EEFC_BASE 0x400E0A00
+#define SAM3X_EEFC_BASE(x) (0x400E0A00+((x)*0x400))
+#define EEFC_FMR(base) ((base)+0x00)
+#define EEFC_FCR(base) ((base)+0x04)
+#define EEFC_FSR(base) ((base)+0x08)
+#define EEFC_FRR(base) ((base)+0x0C)
#define EEFC_FCR_FKEY (0x5A << 24)
#define EEFC_FCR_FCMD_GETD 0x00
@@ -87,7 +97,8 @@ static const char sam3x_xml_memory_map[] = "<?xml version=\"1.0\"?>"
#define EEFC_FSR_FLOCKE (1 << 2)
#define EEFC_FSR_ERROR (EEFC_FSR_FCMDE | EEFC_FSR_FLOCKE)
-#define CHIPID_CIDR 0x400E0940
+#define SAM3X_CHIPID_CIDR 0x400E0940
+#define SAM3N_CHIPID_CIDR 0x400E0740
#define CHIPID_CIDR_VERSION_MASK (0x1F << 0)
#define CHIPID_CIDR_EPROC_CM3 (0x03 << 5)
@@ -102,6 +113,9 @@ static const char sam3x_xml_memory_map[] = "<?xml version=\"1.0\"?>"
#define CHIPID_CIDR_ARCH_SAM3XxC (0x84 << 20)
#define CHIPID_CIDR_ARCH_SAM3XxE (0x85 << 20)
#define CHIPID_CIDR_ARCH_SAM3XxG (0x86 << 20)
+#define CHIPID_CIDR_ARCH_SAM3NxA (0x93 << 20)
+#define CHIPID_CIDR_ARCH_SAM3NxB (0x94 << 20)
+#define CHIPID_CIDR_ARCH_SAM3NxC (0x95 << 20)
#define CHIPID_CIDR_NVPTYP_MASK (0x07 << 28)
#define CHIPID_CIDR_NVPTYP_FLASH (0x02 << 28)
#define CHIPID_CIDR_NVPTYP_ROM_FLASH (0x03 << 28)
@@ -113,70 +127,92 @@ bool sam3x_probe(struct target_s *target)
{
ADIv5_AP_t *ap = adiv5_target_ap(target);
- target->idcode = adiv5_ap_mem_read(ap, CHIPID_CIDR);
+ target->idcode = adiv5_ap_mem_read(ap, SAM3X_CHIPID_CIDR);
/* FIXME: Check for all variants with similar flash interface */
switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
case CHIPID_CIDR_ARCH_SAM3XxC | CHIPID_CIDR_EPROC_CM3:
case CHIPID_CIDR_ARCH_SAM3XxE | CHIPID_CIDR_EPROC_CM3:
case CHIPID_CIDR_ARCH_SAM3XxG | CHIPID_CIDR_EPROC_CM3:
- target->driver = sam3x_driver_str;
+ target->driver = "Atmel SAM3X";
target->xml_mem_map = sam3x_xml_memory_map;
target->flash_erase = sam3x_flash_erase;
target->flash_write = sam3x_flash_write;
- target_add_commands(target, sam3x_cmd_list, sam3x_driver_str);
+ target_add_commands(target, sam3x_cmd_list, "SAM3X");
return true;
}
+
+ target->idcode = adiv5_ap_mem_read(ap, SAM3N_CHIPID_CIDR);
+ switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
+ case CHIPID_CIDR_ARCH_SAM3NxA | CHIPID_CIDR_EPROC_CM3:
+ case CHIPID_CIDR_ARCH_SAM3NxB | CHIPID_CIDR_EPROC_CM3:
+ case CHIPID_CIDR_ARCH_SAM3NxC | CHIPID_CIDR_EPROC_CM3:
+ target->driver = "Atmel SAM3N";
+ target->xml_mem_map = sam3n_xml_memory_map;
+ target->flash_erase = sam3x_flash_erase;
+ target->flash_write = sam3x_flash_write;
+ target_add_commands(target, sam3x_cmd_list, "SAM3N");
+ return true;
+ }
+
return false;
}
static int
-sam3x_flash_cmd(struct target_s *target, int bank, uint8_t cmd, uint16_t arg)
+sam3x_flash_cmd(struct target_s *target, uint32_t base, uint8_t cmd, uint16_t arg)
{
ADIv5_AP_t *ap = adiv5_target_ap(target);
- adiv5_ap_mem_write(ap, EEFC_FCR(bank),
+ DEBUG("%s: base = 0x%08x cmd = 0x%02X, arg = 0x%06X\n",
+ __func__, base, cmd, arg);
+ adiv5_ap_mem_write(ap, EEFC_FCR(base),
EEFC_FCR_FKEY | cmd | ((uint32_t)arg << 8));
- while(!(adiv5_ap_mem_read(ap, EEFC_FSR(bank)) & EEFC_FSR_FRDY))
- if(target_check_error(target))
+ while(!(adiv5_ap_mem_read(ap, EEFC_FSR(base)) & EEFC_FSR_FRDY))
+ if(target_check_error(target))
return -1;
- uint32_t sr = adiv5_ap_mem_read(ap, EEFC_FSR(bank));
+ uint32_t sr = adiv5_ap_mem_read(ap, EEFC_FSR(base));
return sr & EEFC_FSR_ERROR;
}
-static int
-sam3x_flash_bank(struct target_s *target, uint32_t addr, uint32_t *offset)
+static uint32_t
+sam3x_flash_base(struct target_s *target, uint32_t addr, uint32_t *offset)
{
- uint32_t half = -1;
- switch (target->idcode & CHIPID_CIDR_NVPSIZ_MASK) {
- case CHIPID_CIDR_NVPSIZ_128K:
- half = 0x00090000;
- break;
- case CHIPID_CIDR_NVPSIZ_256K:
- half = 0x000A0000;
- break;
- case CHIPID_CIDR_NVPSIZ_512K:
- half = 0x000C0000;
- break;
- }
-
- if (addr > half) {
- if (offset)
- *offset = addr - half;
- return 1;
+ if (strcmp(target->driver, "Atmel SAM3X") == 0) {
+ uint32_t half = -1;
+ switch (target->idcode & CHIPID_CIDR_NVPSIZ_MASK) {
+ case CHIPID_CIDR_NVPSIZ_128K:
+ half = 0x00090000;
+ break;
+ case CHIPID_CIDR_NVPSIZ_256K:
+ half = 0x000A0000;
+ break;
+ case CHIPID_CIDR_NVPSIZ_512K:
+ half = 0x000C0000;
+ break;
+ }
+ if (addr > half) {
+ if (offset)
+ *offset = addr - half;
+ return SAM3X_EEFC_BASE(1);
+ } else {
+ if (offset)
+ *offset = addr - 0x80000;
+ return SAM3X_EEFC_BASE(0);
+ }
}
+ /* SAM3N device */
if (offset)
- *offset = addr - 0x80000;
- return 0;
+ *offset = addr - 0x400000;
+ return SAM3N_EEFC_BASE;
}
static int sam3x_flash_erase(struct target_s *target, uint32_t addr, int len)
{
uint32_t offset;
- uint8_t bank = sam3x_flash_bank(target, addr, &offset);
+ uint32_t base = sam3x_flash_base(target, addr, &offset);
unsigned chunk = offset / PAGE_SIZE;
uint8_t buf[PAGE_SIZE];
@@ -187,10 +223,10 @@ static int sam3x_flash_erase(struct target_s *target, uint32_t addr, int len)
memset(buf, 0xff, sizeof(buf));
/* Only do this once, since it doesn't change. */
- target_mem_write_words(target, addr, (void*)buf, PAGE_SIZE);
+ target_mem_write_words(target, addr, (void*)buf, PAGE_SIZE);
while (len) {
- if(sam3x_flash_cmd(target, bank, EEFC_FCR_FCMD_EWP, chunk))
+ if(sam3x_flash_cmd(target, base, EEFC_FCR_FCMD_EWP, chunk))
return -1;
len -= PAGE_SIZE;
@@ -201,11 +237,11 @@ static int sam3x_flash_erase(struct target_s *target, uint32_t addr, int len)
return 0;
}
-static int sam3x_flash_write(struct target_s *target, uint32_t dest,
+static int sam3x_flash_write(struct target_s *target, uint32_t dest,
const uint8_t *src, int len)
{
uint32_t offset;
- uint8_t bank = sam3x_flash_bank(target, dest, &offset);
+ uint32_t base = sam3x_flash_base(target, dest, &offset);
uint8_t buf[PAGE_SIZE];
unsigned first_chunk = offset / PAGE_SIZE;
unsigned last_chunk = (offset + len - 1) / PAGE_SIZE;
@@ -213,15 +249,15 @@ static int sam3x_flash_write(struct target_s *target, uint32_t dest,
dest -= offset;
for (unsigned chunk = first_chunk; chunk <= last_chunk; chunk++) {
-
+
DEBUG("chunk %u len %d\n", chunk, len);
/* first and last chunk may require special handling */
if ((chunk == first_chunk) || (chunk == last_chunk)) {
/* fill with all ff to avoid sector rewrite corrupting other writes */
memset(buf, 0xff, sizeof(buf));
-
- /* copy as much as fits */
+
+ /* copy as much as fits */
int copylen = PAGE_SIZE - offset;
if (copylen > len)
copylen = len;
@@ -239,8 +275,8 @@ static int sam3x_flash_write(struct target_s *target, uint32_t dest,
src += PAGE_SIZE;
}
- target_mem_write_words(target, dest, (void*)buf, PAGE_SIZE);
- if(sam3x_flash_cmd(target, bank, EEFC_FCR_FCMD_WP, chunk))
+ target_mem_write_words(target, dest, (void*)buf, PAGE_SIZE);
+ if(sam3x_flash_cmd(target, base, EEFC_FCR_FCMD_WP, chunk))
return -1;
}
@@ -250,9 +286,10 @@ static int sam3x_flash_write(struct target_s *target, uint32_t dest,
static bool sam3x_cmd_gpnvm_get(target *t)
{
ADIv5_AP_t *ap = adiv5_target_ap(t);
-
- sam3x_flash_cmd(t, 0, EEFC_FCR_FCMD_GGPB, 0);
- gdb_outf("GPNVM: 0x%08X\n", adiv5_ap_mem_read(ap, EEFC_FRR(0)));
+ uint32_t base = sam3x_flash_base(t, 0, NULL);
+
+ sam3x_flash_cmd(t, base, EEFC_FCR_FCMD_GGPB, 0);
+ gdb_outf("GPNVM: 0x%08X\n", adiv5_ap_mem_read(ap, EEFC_FRR(base)));
return true;
}
@@ -260,7 +297,8 @@ static bool sam3x_cmd_gpnvm_get(target *t)
static bool sam3x_cmd_gpnvm_set(target *t, int argc, char *argv[])
{
uint32_t bit, cmd;
-
+ uint32_t base = sam3x_flash_base(t, 0, NULL);
+
if (argc != 3) {
gdb_out("usage: monitor gpnvm_set <bit> <val>\n");
return false;
@@ -268,7 +306,7 @@ static bool sam3x_cmd_gpnvm_set(target *t, int argc, char *argv[])
bit = atol(argv[1]);
cmd = atol(argv[2]) ? EEFC_FCR_FCMD_SGPB : EEFC_FCR_FCMD_CGPB;
- sam3x_flash_cmd(t, 0, cmd, bit);
+ sam3x_flash_cmd(t, base, cmd, bit);
sam3x_cmd_gpnvm_get(t);
return true;
diff --git a/src/stm32f1.c b/src/stm32f1.c
index 4cc7b2a..670c5bd 100644
--- a/src/stm32f1.c
+++ b/src/stm32f1.c
@@ -50,9 +50,9 @@ const struct command_s stm32f1_cmd_list[] = {
static int stm32md_flash_erase(struct target_s *target, uint32_t addr, int len);
static int stm32hd_flash_erase(struct target_s *target, uint32_t addr, int len);
-static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, int len,
+static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, int len,
uint32_t pagesize);
-static int stm32f1_flash_write(struct target_s *target, uint32_t dest,
+static int stm32f1_flash_write(struct target_s *target, uint32_t dest,
const uint8_t *src, int len);
static const char stm32f1_driver_str[] = "STM32, Medium density.";
@@ -101,9 +101,11 @@ static const char stm32hd_xml_memory_map[] = "<?xml version=\"1.0\"?>"
#define FLASH_CR_MER (1 << 2)
#define FLASH_CR_PER (1 << 1)
+#define FLASH_OBR_RDPRT (1 << 1)
+
#define FLASH_SR_BSY (1 << 0)
-#define FLASH_OBP_RDP 0x1FFFF800
+#define FLASH_OBP_RDP 0x1FFFF800
#define FLASH_OBP_RDP_KEY 0x5aa5
#define FLASH_OBP_RDP_KEY_F3 0x55AA
@@ -220,7 +222,7 @@ static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, int len,
/* Flash page erase instruction */
adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_PER);
/* write address to FMA */
- adiv5_ap_mem_write(ap, FLASH_AR, addr);
+ adiv5_ap_mem_write(ap, FLASH_AR, addr);
/* Flash page erase start instruction */
adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_STRT | FLASH_CR_PER);
@@ -251,7 +253,7 @@ static int stm32md_flash_erase(struct target_s *target, uint32_t addr, int len)
return stm32f1_flash_erase(target, addr, len, 0x400);
}
-static int stm32f1_flash_write(struct target_s *target, uint32_t dest,
+static int stm32f1_flash_write(struct target_s *target, uint32_t dest,
const uint8_t *src, int len)
{
ADIv5_AP_t *ap = adiv5_target_ap(target);
@@ -287,7 +289,7 @@ static int stm32f1_flash_write(struct target_s *target, uint32_t dest,
static bool stm32f1_cmd_erase_mass(target *t)
{
ADIv5_AP_t *ap = adiv5_target_ap(t);
-
+
stm32f1_flash_unlock(ap);
/* Flash mass erase start instruction */
@@ -313,7 +315,7 @@ static bool stm32f1_option_erase(target *t)
/* Erase option bytes instruction */
adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_OPTER | FLASH_CR_OPTWRE);
- adiv5_ap_mem_write(ap, FLASH_CR,
+ adiv5_ap_mem_write(ap, FLASH_CR,
FLASH_CR_STRT | FLASH_CR_OPTER | FLASH_CR_OPTWRE);
/* Read FLASH_SR to poll for BSY bit */
while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY)
@@ -322,10 +324,12 @@ static bool stm32f1_option_erase(target *t)
return true;
}
-static bool stm32f1_option_write(target *t, uint32_t addr, uint16_t value)
+static bool stm32f1_option_write_erased(target *t, uint32_t addr, uint16_t value)
{
ADIv5_AP_t *ap = adiv5_target_ap(t);
+ if (value == 0xffff)
+ return true;
/* Erase option bytes instruction */
adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_OPTPG | FLASH_CR_OPTWRE);
adiv5_ap_mem_write_halfword(ap, addr, value);
@@ -336,11 +340,42 @@ static bool stm32f1_option_write(target *t, uint32_t addr, uint16_t value)
return true;
}
+static bool stm32f1_option_write(target *t, uint32_t addr, uint16_t value)
+{
+ ADIv5_AP_t *ap = adiv5_target_ap(t);
+ uint16_t opt_val[8];
+ int i, index;
+
+ index = (addr - FLASH_OBP_RDP) / 2;
+ if ((index < 0) || (index > 7))
+ return false;
+ /* Retrieve old values */
+ for (i = 0; i < 16; i = i +4) {
+ uint32_t val = adiv5_ap_mem_read(ap, FLASH_OBP_RDP + i);
+ opt_val[i/2] = val & 0xffff;
+ opt_val[i/2 +1] = val >> 16;
+ }
+ if (opt_val[index] == value)
+ return true;
+ /* Check for erased value */
+ if (opt_val[index] != 0xffff)
+ if (!(stm32f1_option_erase(t)))
+ return false;
+ opt_val[index] = value;
+ /* Write changed values*/
+ for (i = 0; i < 8; i++)
+ if (!(stm32f1_option_write_erased
+ (t, FLASH_OBP_RDP + i*2,opt_val[i])))
+ return false;
+ return true;
+}
+
static bool stm32f1_cmd_option(target *t, int argc, char *argv[])
{
uint32_t addr, val;
uint32_t flash_obp_rdp_key;
ADIv5_AP_t *ap = adiv5_target_ap(t);
+ uint32_t rdprt;
switch(t->idcode) {
case 0x422: /* STM32F30x */
@@ -350,13 +385,18 @@ static bool stm32f1_cmd_option(target *t, int argc, char *argv[])
break;
default: flash_obp_rdp_key = FLASH_OBP_RDP_KEY;
}
+ rdprt = (adiv5_ap_mem_read(ap, FLASH_OBR) & FLASH_OBR_RDPRT);
stm32f1_flash_unlock(ap);
adiv5_ap_mem_write(ap, FLASH_OPTKEYR, KEY1);
adiv5_ap_mem_write(ap, FLASH_OPTKEYR, KEY2);
if ((argc == 2) && !strcmp(argv[1], "erase")) {
stm32f1_option_erase(t);
- stm32f1_option_write(t, FLASH_OBP_RDP, flash_obp_rdp_key);
+ stm32f1_option_write_erased(t, FLASH_OBP_RDP, flash_obp_rdp_key);
+ } else if (rdprt) {
+ gdb_out("Device is Read Protected\n");
+ gdb_out("Use \"monitor option erase\" to unprotect, erasing device\n");
+ return true;
} else if (argc == 3) {
addr = strtol(argv[1], NULL, 0);
val = strtol(argv[2], NULL, 0);
diff --git a/src/stm32f4.c b/src/stm32f4.c
index b9764cc..cfbe9e3 100644
--- a/src/stm32f4.c
+++ b/src/stm32f4.c
@@ -50,7 +50,7 @@ const struct command_s stm32f4_cmd_list[] = {
static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, int len);
-static int stm32f4_flash_write(struct target_s *target, uint32_t dest,
+static int stm32f4_flash_write(struct target_s *target, uint32_t dest,
const uint8_t *src, int len);
static const char stm32f4_driver_str[] = "STM32F4xx";
@@ -170,6 +170,7 @@ bool stm32f4_probe(struct target_s *target)
switch(idcode & 0xFFF) {
case 0x411: /* Documented to be 0x413! This is what I read... */
case 0x413:
+ case 0x423: /* F401 */
case 0x419: /* 427/437 */
target->driver = stm32f4_driver_str;
target->xml_mem_map = stm32f4_xml_memory_map;
@@ -218,11 +219,11 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, int len)
/* Flash page erase instruction */
adiv5_ap_mem_write(ap, FLASH_CR, cr);
/* write address to FMA */
- adiv5_ap_mem_write(ap, FLASH_CR, cr | FLASH_CR_STRT);
+ adiv5_ap_mem_write(ap, FLASH_CR, cr | FLASH_CR_STRT);
/* Read FLASH_SR to poll for BSY bit */
while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY)
- if(target_check_error(target))
+ if(target_check_error(target))
return -1;
len -= pagesize;
@@ -237,7 +238,7 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, int len)
return 0;
}
-static int stm32f4_flash_write(struct target_s *target, uint32_t dest,
+static int stm32f4_flash_write(struct target_s *target, uint32_t dest,
const uint8_t *src, int len)
{
ADIv5_AP_t *ap = adiv5_target_ap(target);
@@ -257,7 +258,7 @@ static int stm32f4_flash_write(struct target_s *target, uint32_t dest,
target_mem_write_words(target, 0x20000000, (void*)stm32f4_flash_write_stub, 0x30);
target_mem_write_words(target, 0x20000030, data, sizeof(data));
target_pc_write(target, 0x20000000);
- if(target_check_error(target))
+ if(target_check_error(target))
return -1;
/* Execute the stub */
diff --git a/src/stm32l1.c b/src/stm32l1.c
index 8fd25f7..8e80582 100644
--- a/src/stm32l1.c
+++ b/src/stm32l1.c
@@ -39,7 +39,7 @@
#include "gdb_packet.h"
static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, int len);
-static int stm32l1_flash_write(struct target_s *target, uint32_t dest,
+static int stm32l1_flash_write(struct target_s *target, uint32_t dest,
const uint8_t *src, int len);
static const char stm32l1_driver_str[] = "STM32L1xx";
@@ -56,40 +56,40 @@ static const char stm32l1_xml_memory_map[] = "<?xml version=\"1.0\"?>"
"</memory-map>";
/* Flash Controller Register Map */
-#define FLASH_BASE 0x40023C00
-#define FLASH_ACR (FLASH_BASE+0x00)
-#define FLASH_PECR (FLASH_BASE+0x04)
-#define FLASH_PDKEYR (FLASH_BASE+0x08)
-#define FLASH_PEKEYR (FLASH_BASE+0x0C)
-#define FLASH_PRGKEYR (FLASH_BASE+0x10)
-#define FLASH_OPTKEYR (FLASH_BASE+0x14)
-#define FLASH_SR (FLASH_BASE+0x18)
-#define FLASH_OBR (FLASH_BASE+0x1C)
-#define FLASH_WRPR1 (FLASH_BASE+0x20)
-#define FLASH_WRPR2 (FLASH_BASE+0x80)
-#define FLASH_WRPR3 (FLASH_BASE+0x84)
-
-#define FLASH_PECR_FPRG (1 << 10)
-#define FLASH_PECR_ERASE (1 << 9)
-#define FLASH_PECR_PROG (1 << 3)
-
-#define FLASH_SR_BSY (1 << 0)
-#define FLASH_SR_EOP (1 << 1)
-
-#define FLASH_SR_ERROR_MASK (0x1f << 8)
-
-#define PEKEY1 0x89ABCDEF
-#define PEKEY2 0x02030405
-#define PRGKEY1 0x8C9DAEBF
-#define PRGKEY2 0x13141516
-
-#define DBGMCU_IDCODE 0xE0042000
+#define STM32L1_FLASH_BASE 0x40023C00
+#define STM32L1_FLASH_ACR (STM32L1_FLASH_BASE + 0x00)
+#define STM32L1_FLASH_PECR (STM32L1_FLASH_BASE + 0x04)
+#define STM32L1_FLASH_PDKEYR (STM32L1_FLASH_BASE + 0x08)
+#define STM32L1_FLASH_PEKEYR (STM32L1_FLASH_BASE + 0x0C)
+#define STM32L1_FLASH_PRGKEYR (STM32L1_FLASH_BASE + 0x10)
+#define STM32L1_FLASH_OPTKEYR (STM32L1_FLASH_BASE + 0x14)
+#define STM32L1_FLASH_SR (STM32L1_FLASH_BASE + 0x18)
+#define STM32L1_FLASH_OBR (STM32L1_FLASH_BASE + 0x1C)
+#define STM32L1_FLASH_WRPR1 (STM32L1_FLASH_BASE + 0x20)
+#define STM32L1_FLASH_WRPR2 (STM32L1_FLASH_BASE + 0x80)
+#define STM32L1_FLASH_WRPR3 (STM32L1_FLASH_BASE + 0x84)
+
+#define STM32L1_FLASH_PECR_FPRG (1 << 10)
+#define STM32L1_FLASH_PECR_ERASE (1 << 9)
+#define STM32L1_FLASH_PECR_PROG (1 << 3)
+
+#define STM32L1_FLASH_SR_BSY (1 << 0)
+#define STM32L1_FLASH_SR_EOP (1 << 1)
+
+#define STM32L1_FLASH_SR_ERROR_MASK (0x1f << 8)
+
+#define STM32L1_PEKEY1 0x89ABCDEF
+#define STM32L1_PEKEY2 0x02030405
+#define STM32L1_PRGKEY1 0x8C9DAEBF
+#define STM32L1_PRGKEY2 0x13141516
+
+#define STM32L1_DBGMCU_IDCODE 0xE0042000
bool stm32l1_probe(struct target_s *target)
{
uint32_t idcode;
- idcode = adiv5_ap_mem_read(adiv5_target_ap(target), DBGMCU_IDCODE);
+ idcode = adiv5_ap_mem_read(adiv5_target_ap(target), STM32L1_DBGMCU_IDCODE);
switch(idcode & 0xFFF) {
case 0x416: /* Medium density */
case 0x436: /* High density */
@@ -105,10 +105,10 @@ bool stm32l1_probe(struct target_s *target)
static void stm32l1_flash_unlock(ADIv5_AP_t *ap)
{
- adiv5_ap_mem_write(ap, FLASH_PEKEYR, PEKEY1);
- adiv5_ap_mem_write(ap, FLASH_PEKEYR, PEKEY2);
- adiv5_ap_mem_write(ap, FLASH_PRGKEYR, PRGKEY1);
- adiv5_ap_mem_write(ap, FLASH_PRGKEYR, PRGKEY2);
+ adiv5_ap_mem_write(ap, STM32L1_FLASH_PEKEYR, STM32L1_PEKEY1);
+ adiv5_ap_mem_write(ap, STM32L1_FLASH_PEKEYR, STM32L1_PEKEY2);
+ adiv5_ap_mem_write(ap, STM32L1_FLASH_PRGKEYR, STM32L1_PRGKEY1);
+ adiv5_ap_mem_write(ap, STM32L1_FLASH_PRGKEYR, STM32L1_PRGKEY2);
}
static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, int len)
@@ -122,10 +122,10 @@ static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, int len)
stm32l1_flash_unlock(ap);
/* Flash page erase instruction */
- adiv5_ap_mem_write(ap, FLASH_PECR, FLASH_PECR_ERASE | FLASH_PECR_PROG);
+ adiv5_ap_mem_write(ap, STM32L1_FLASH_PECR, STM32L1_FLASH_PECR_ERASE | STM32L1_FLASH_PECR_PROG);
/* Read FLASH_SR to poll for BSY bit */
- while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY)
+ while(adiv5_ap_mem_read(ap, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY)
if(target_check_error(target))
return -1;
@@ -138,17 +138,17 @@ static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, int len)
}
/* Disable programming mode */
- adiv5_ap_mem_write(ap, FLASH_PECR, 0);
+ adiv5_ap_mem_write(ap, STM32L1_FLASH_PECR, 0);
/* Check for error */
- sr = adiv5_ap_mem_read(ap, FLASH_SR);
- if ((sr & FLASH_SR_ERROR_MASK) || !(sr & FLASH_SR_EOP))
+ sr = adiv5_ap_mem_read(ap, STM32L1_FLASH_SR);
+ if ((sr & STM32L1_FLASH_SR_ERROR_MASK) || !(sr & STM32L1_FLASH_SR_EOP))
return -1;
return 0;
}
-static int stm32l1_flash_write(struct target_s *target, uint32_t dest,
+static int stm32l1_flash_write(struct target_s *target, uint32_t dest,
const uint8_t *src, int len)
{
ADIv5_AP_t *ap = adiv5_target_ap(target);
@@ -183,10 +183,10 @@ static int stm32l1_flash_write(struct target_s *target, uint32_t dest,
/* Write half-pages */
if(len > 128) {
/* Enable half page mode */
- adiv5_ap_mem_write(ap, FLASH_PECR, FLASH_PECR_FPRG | FLASH_PECR_PROG);
+ adiv5_ap_mem_write(ap, STM32L1_FLASH_PECR, STM32L1_FLASH_PECR_FPRG | STM32L1_FLASH_PECR_PROG);
/* Read FLASH_SR to poll for BSY bit */
- while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY)
+ while(adiv5_ap_mem_read(ap, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY)
if(target_check_error(target))
return -1;
@@ -196,10 +196,10 @@ static int stm32l1_flash_write(struct target_s *target, uint32_t dest,
len -= len & ~127;
/* Disable half page mode */
- adiv5_ap_mem_write(ap, FLASH_PECR, 0);
+ adiv5_ap_mem_write(ap, STM32L1_FLASH_PECR, 0);
/* Read FLASH_SR to poll for BSY bit */
- while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY)
+ while(adiv5_ap_mem_read(ap, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY)
if(target_check_error(target))
return -1;
}
@@ -221,8 +221,8 @@ static int stm32l1_flash_write(struct target_s *target, uint32_t dest,
}
/* Check for error */
- sr = adiv5_ap_mem_read(ap, FLASH_SR);
- if ((sr & FLASH_SR_ERROR_MASK) || !(sr & FLASH_SR_EOP))
+ sr = adiv5_ap_mem_read(ap, STM32L1_FLASH_SR);
+ if ((sr & STM32L1_FLASH_SR_ERROR_MASK) || !(sr & STM32L1_FLASH_SR_EOP))
return -1;
return 0;
diff --git a/src/target.c b/src/target.c
index b46f9e3..2a68f23 100644
--- a/src/target.c
+++ b/src/target.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
target *target_list = NULL;
+bool connect_assert_srst;
target *target_new(unsigned size)
{