kopia lustrzana https://github.com/stlink-org/stlink
155 wiersze
4.4 KiB
C
155 wiersze
4.4 KiB
C
/*
|
|
* 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));
|
|
}
|