Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Write to extra (FP, etc) registers from GDB

The extra registers added in my previous commit can now be modified from
within GDB.  Since the ST-LINK does not support accessing these
registers, a workaround was used from reading an writing to them.

That is, the Debug Core Register Selector Register (DCRSR) can be written
with the register requested, and it will be read/written to/from the
Debug Core Register Data Register (DCRDR).  The standard ST-LINK memory
access functions are used to make these accesses.

A target descriptor XML file is sent to GDB from the server, which tells
GDB which registers exist on the target.

This is only supported for the STM32F4, and has only been tested on the
STM32F4DISCOVERY.  I tested st-util on an STM32L-DISCOVERY and my
changes did not seem to interfere with its operation.
  • Loading branch information...
commit c6274f026b7848cf45029eccc327f8215738a743 1 parent b1e65ea
@prattmic prattmic authored
View
3  AUTHORS
@@ -14,4 +14,5 @@ bravikov@gmail.com
jnosky - codegrinder69@hotmail.com
marpe@mimuw.edu.pl
marco.cassinerio@gmail.com
-jserv@0xlab.org
+jserv@0xlab.org
+michael@pratt.im
View
16 gdbserver/gdb-server.c
@@ -999,6 +999,22 @@ int serve(stlink_t *sl, int port) {
stlink_write_reg(sl, ntohl(value), reg);
} else if(reg == 0x19) {
stlink_write_reg(sl, ntohl(value), 16);
+ } else if(reg == 0x1A) {
+ stlink_write_reg(sl, ntohl(value), 17);
+ } else if(reg == 0x1B) {
+ stlink_write_reg(sl, ntohl(value), 18);
+ } else if(reg == 0x1C) {
+ stlink_write_unsupported_reg(sl, ntohl(value), reg, &regp);
+ } else if(reg == 0x1D) {
+ stlink_write_unsupported_reg(sl, ntohl(value), reg, &regp);
+ } else if(reg == 0x1E) {
+ stlink_write_unsupported_reg(sl, ntohl(value), reg, &regp);
+ } else if(reg == 0x1F) {
+ stlink_write_unsupported_reg(sl, ntohl(value), reg, &regp);
+ } else if(reg >= 0x20 && reg < 0x40) {
+ stlink_write_unsupported_reg(sl, ntohl(value), reg, &regp);
+ } else if(reg == 0x40) {
+ stlink_write_unsupported_reg(sl, ntohl(value), reg, &regp);
} else {
reply = strdup("E00");
}
View
21 src/stlink-common.c
@@ -620,6 +620,27 @@ void stlink_read_unsupported_reg(stlink_t *sl, int r_idx, reg *regp) {
sl->backend->read_unsupported_reg(sl, r_convert, regp);
}
+void stlink_write_unsupported_reg(stlink_t *sl, uint32_t val, int r_idx, reg *regp) {
+ int r_convert;
+
+ DLOG("*** stlink_write_unsupported_reg\n");
+ DLOG(" (%d) ***\n", r_idx);
+
+ /* Convert to values used by DCRSR */
+ if (r_idx >= 0x1C && r_idx <= 0x1F) { /* primask, basepri, faultmask, or control */
+ r_convert = r_idx; /* The backend function handles this */
+ } else if (r_idx == 0x40) { /* FPSCR */
+ r_convert = 0x21;
+ } else if (r_idx >= 0x20 && r_idx < 0x40) {
+ r_convert = 0x40 + (r_idx - 0x20);
+ } else {
+ fprintf(stderr, "Error: register address must be in [0x1C..0x40]\n");
+ return;
+ }
+
+ sl->backend->write_unsupported_reg(sl, val, r_convert, regp);
+}
+
unsigned int is_core_halted(stlink_t *sl) {
/* return non zero if core is halted */
stlink_status(sl);
View
4 src/stlink-common.h
@@ -112,6 +112,8 @@ extern "C" {
/* Cortex™-M3 Technical Reference Manual */
/* Debug Halting Control and Status Register */
#define DHCSR 0xe000edf0
+#define DCRSR 0xe000edf4
+#define DCRDR 0xe000edf8
#define DBGKEY 0xa05f0000
/* Enough space to hold both a V2 command or a V1 command packaged as generic scsi*/
@@ -303,6 +305,7 @@ extern "C" {
void (*read_reg) (stlink_t *sl, int r_idx, reg * regp);
void (*read_all_unsupported_regs) (stlink_t *sl, reg *regp);
void (*read_unsupported_reg) (stlink_t *sl, int r_idx, reg *regp);
+ void (*write_unsupported_reg) (stlink_t *sl, uint32_t value, int idx, reg *regp);
void (*write_reg) (stlink_t *sl, uint32_t reg, int idx);
void (*step) (stlink_t * stl);
int (*current_mode) (stlink_t * stl);
@@ -371,6 +374,7 @@ extern "C" {
void stlink_read_all_unsupported_regs(stlink_t *sl, reg *regp);
void stlink_read_reg(stlink_t *sl, int r_idx, reg *regp);
void stlink_read_unsupported_reg(stlink_t *sl, int r_idx, reg *regp);
+ void stlink_write_unsupported_reg(stlink_t *sl, uint32_t value, int r_idx, reg *regp);
void stlink_write_reg(stlink_t *sl, uint32_t reg, int idx);
void stlink_step(stlink_t *sl);
int stlink_current_mode(stlink_t *sl);
View
44 src/stlink-usb.c
@@ -585,8 +585,8 @@ void _stlink_usb_read_unsupported_reg(stlink_t *sl, int r_idx, reg *regp) {
sl->q_buf[i] = 0;
}
- _stlink_usb_write_mem32(sl, 0xE000EDF4, 4);
- _stlink_usb_read_mem32(sl, 0xE000EDF8, 4);
+ _stlink_usb_write_mem32(sl, DCRSR, 4);
+ _stlink_usb_read_mem32(sl, DCRDR, 4);
r = read_uint32(sl->q_buf, 0);
DLOG("r_idx (%2d) = 0x%08x\n", r_idx, r);
@@ -608,6 +608,7 @@ void _stlink_usb_read_unsupported_reg(stlink_t *sl, int r_idx, reg *regp) {
}
void _stlink_usb_read_all_unsupported_regs(stlink_t *sl, reg *regp) {
+ _stlink_usb_read_unsupported_reg(sl, 0x14, regp);
_stlink_usb_read_unsupported_reg(sl, 0x21, regp);
for (int i = 0; i < 32; i++) {
@@ -615,6 +616,44 @@ void _stlink_usb_read_all_unsupported_regs(stlink_t *sl, reg *regp) {
}
}
+/* See section C1.6 of the ARMv7-M Architecture Reference Manual */
+void _stlink_usb_write_unsupported_reg(stlink_t *sl, uint32_t val, int r_idx, reg *regp) {
+ if (r_idx >= 0x1C && r_idx <= 0x1F) { /* primask, basepri, faultmask, or control */
+ /* These are held in the same register */
+ _stlink_usb_read_unsupported_reg(sl, 0x14, regp);
+
+ val = (uint8_t) (val>>24);
+
+ switch (r_idx) {
+ case 0x1C: /* control */
+ val = (((uint32_t) val) << 24) | (((uint32_t) regp->faultmask) << 16) | (((uint32_t) regp->basepri) << 8) | ((uint32_t) regp->primask);
+ break;
+ case 0x1D: /* faultmask */
+ val = (((uint32_t) regp->control) << 24) | (((uint32_t) val) << 16) | (((uint32_t) regp->basepri) << 8) | ((uint32_t) regp->primask);
+ break;
+ case 0x1E: /* basepri */
+ val = (((uint32_t) regp->control) << 24) | (((uint32_t) regp->faultmask) << 16) | (((uint32_t) val) << 8) | ((uint32_t) regp->primask);
+ break;
+ case 0x1F: /* primask */
+ val = (((uint32_t) regp->control) << 24) | (((uint32_t) regp->faultmask) << 16) | (((uint32_t) regp->basepri) << 8) | ((uint32_t) val);
+ break;
+ }
+
+ r_idx = 0x14;
+ }
+
+ write_uint32(sl->q_buf, val);
+
+ _stlink_usb_write_mem32(sl, DCRDR, 4);
+
+ sl->q_buf[0] = (unsigned char) r_idx;
+ sl->q_buf[1] = 0;
+ sl->q_buf[2] = 0x01;
+ sl->q_buf[3] = 0;
+
+ _stlink_usb_write_mem32(sl, DCRSR, 4);
+}
+
void _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const data = sl->q_buf;
@@ -657,6 +696,7 @@ stlink_backend_t _stlink_usb_backend = {
_stlink_usb_read_reg,
_stlink_usb_read_all_unsupported_regs,
_stlink_usb_read_unsupported_reg,
+ _stlink_usb_write_unsupported_reg,
_stlink_usb_write_reg,
_stlink_usb_step,
_stlink_usb_current_mode,
Please sign in to comment.
Something went wrong with that request. Please try again.