summaryrefslogtreecommitdiff
path: root/src/stlink-lib/read_write.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/stlink-lib/read_write.c')
-rw-r--r--src/stlink-lib/read_write.c154
1 files changed, 154 insertions, 0 deletions
diff --git a/src/stlink-lib/read_write.c b/src/stlink-lib/read_write.c
new file mode 100644
index 0000000..4e43d8a
--- /dev/null
+++ b/src/stlink-lib/read_write.c
@@ -0,0 +1,154 @@
+/*
+ * File: read_write.c
+ *
+ * Read and write operations
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <stlink.h>
+#include "read_write.h"
+
+#include "logging.h"
+
+// Endianness
+// https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
+// These functions encode and decode little endian uint16 and uint32 values.
+
+uint16_t read_uint16(const unsigned char *c, const int32_t pt) {
+ return ((uint16_t)c[pt]) | ((uint16_t)c[pt + 1] << 8);
+}
+
+void write_uint16(unsigned char *buf, uint16_t ui) {
+ buf[0] = (uint8_t)ui;
+ buf[1] = (uint8_t)(ui >> 8);
+}
+
+uint32_t read_uint32(const unsigned char *c, const int32_t pt) {
+ return ((uint32_t)c[pt]) | ((uint32_t)c[pt + 1] << 8) |
+ ((uint32_t)c[pt + 2] << 16) | ((uint32_t)c[pt + 3] << 24);
+}
+
+void write_uint32(unsigned char *buf, uint32_t ui) {
+ buf[0] = ui;
+ buf[1] = ui >> 8;
+ buf[2] = ui >> 16;
+ buf[3] = ui >> 24;
+}
+
+int32_t stlink_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) {
+ int32_t ret;
+
+ ret = sl->backend->read_debug32(sl, addr, data);
+ if (!ret)
+ DLOG("*** stlink_read_debug32 %#010x at %#010x\n", *data, addr);
+
+ return (ret);
+}
+
+int32_t stlink_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) {
+ DLOG("*** stlink_write_debug32 %#010x to %#010x\n", data, addr);
+ return sl->backend->write_debug32(sl, addr, data);
+}
+
+int32_t stlink_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
+ DLOG("*** stlink_read_mem32 ***\n");
+
+ if (len % 4 != 0) { // !!! never ever: fw gives just wrong values
+ ELOG("Data length doesn't have a 32 bit alignment: +%d byte.\n", len % 4);
+ return (-1);
+ }
+
+ return (sl->backend->read_mem32(sl, addr, len));
+}
+
+int32_t stlink_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
+ DLOG("*** stlink_write_mem32 %u bytes to %#x\n", len, addr);
+
+ if (len % 4 != 0) {
+ ELOG("Data length doesn't have a 32 bit alignment: +%d byte.\n", len % 4);
+ return (-1);
+ }
+
+ return (sl->backend->write_mem32(sl, addr, len));
+}
+
+int32_t stlink_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) {
+ DLOG("*** stlink_write_mem8 ***\n");
+ return (sl->backend->write_mem8(sl, addr, len));
+}
+
+int32_t stlink_read_reg(stlink_t *sl, int32_t r_idx, struct stlink_reg *regp) {
+ DLOG("*** stlink_read_reg\n");
+ DLOG(" (%d) ***\n", r_idx);
+
+ if (r_idx > 20 || r_idx < 0) {
+ fprintf(stderr, "Error: register index must be in [0..20]\n");
+ return (-1);
+ }
+
+ return (sl->backend->read_reg(sl, r_idx, regp));
+}
+
+int32_t stlink_write_reg(stlink_t *sl, uint32_t reg, int32_t idx) {
+ DLOG("*** stlink_write_reg\n");
+ return (sl->backend->write_reg(sl, reg, idx));
+}
+
+int32_t stlink_read_unsupported_reg(stlink_t *sl, int32_t r_idx,
+ struct stlink_reg *regp) {
+ int32_t r_convert;
+
+ DLOG("*** stlink_read_unsupported_reg\n");
+ DLOG(" (%d) ***\n", r_idx);
+
+ /* Convert to values used by STLINK_REG_DCRSR */
+ if (r_idx >= 0x1C &&
+ r_idx <= 0x1F) { // primask, basepri, faultmask, or control
+ r_convert = 0x14;
+ } 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 (-1);
+ }
+
+ return (sl->backend->read_unsupported_reg(sl, r_convert, regp));
+}
+
+int32_t stlink_write_unsupported_reg(stlink_t *sl, uint32_t val, int32_t r_idx,
+ struct stlink_reg *regp) {
+ int32_t r_convert;
+
+ DLOG("*** stlink_write_unsupported_reg\n");
+ DLOG(" (%d) ***\n", r_idx);
+
+ /* Convert to values used by STLINK_REG_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 (-1);
+ }
+
+ return (sl->backend->write_unsupported_reg(sl, val, r_convert, regp));
+}
+
+int32_t stlink_read_all_regs(stlink_t *sl, struct stlink_reg *regp) {
+ DLOG("*** stlink_read_all_regs ***\n");
+ return (sl->backend->read_all_regs(sl, regp));
+}
+
+int32_t stlink_read_all_unsupported_regs(stlink_t *sl, struct stlink_reg *regp) {
+ DLOG("*** stlink_read_all_unsupported_regs ***\n");
+ return (sl->backend->read_all_unsupported_regs(sl, regp));
+}