Discussion:
[OpenOCD-devel] [PATCH]: 3244970 mips32: fastdata transfer, check spracc
gerrit
2017-05-20 15:43:37 UTC
Permalink
This is an automated email from Gerrit.

Salvador Arroyo (***@yahoo.es) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/4145

-- gerrit

commit 32449709ea8613c686872de34ceb8ff02a70399e
Author: Salvador Arroyo <***@yahoo.es>
Date: Sat May 20 16:49:53 2017 +0200

mips32: fastdata transfer, check spracc

the code now executes scans until the number of
succesful scans specified by count is reached. Also
means the handler completes execution.
Upload success indepently of scan delay setting.
Added simple bulk read code. Some minor changes in r/w
functions to reduce size of code.

Change-Id: I52bc835925b2c62db6ebd5c6bc6f804afa4b66b0
Signed-off-by: Salvador Arroyo <***@yahoo.es>

diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c
index 7b00efd..c5c7aeb 100644
--- a/src/target/mips32_pracc.c
+++ b/src/target/mips32_pracc.c
@@ -925,6 +925,13 @@ int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source,
int write_t, uint32_t addr, int count, uint32_t *buf)
{
+ /* one byte for spracc, four for data, per fastdata scan */
+ uint8_t *in_buf = malloc(5 * XFER_BLOCK * sizeof(uint8_t));
+ if (in_buf == NULL) {
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
+ }
+
uint32_t isa = ejtag_info->isa ? 1 : 0;
uint32_t handler_code[] = {
/* $15 already points to xfer area, loaded in jump code */
@@ -956,13 +963,19 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are

pracc_swap16_array(ejtag_info, handler_code, ARRAY_SIZE(handler_code));
/* write program into RAM */
+
+ int retval;
if (write_t != ejtag_info->fast_access_save) {
- mips32_pracc_write_mem(ejtag_info, source->address, 4, ARRAY_SIZE(handler_code), handler_code);
+ retval = mips32_pracc_write_mem(ejtag_info, source->address, 4, ARRAY_SIZE(handler_code),
+ handler_code);
+ if (retval != ERROR_OK)
+ goto exit_free;
+
/* save previous operation to speed to any consecutive read/writes */
ejtag_info->fast_access_save = write_t;
}

- LOG_DEBUG("%s using 0x%.8" TARGET_PRIxADDR " for write handler", __func__, source->address);
+ LOG_DEBUG("%s using 0x%.8" TARGET_PRIxADDR " for r/w handler", __func__, source->address);

uint32_t jmp_code[] = {
MIPS32_LUI(isa, 8, UPPER16(source->address)), /* load addr of jump in $8 */
@@ -972,12 +985,13 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are
};

pracc_swap16_array(ejtag_info, jmp_code, ARRAY_SIZE(jmp_code));
+ mips_ejtag_update_clocks(ejtag_info);

/* execute jump code, with no address check */
for (unsigned i = 0; i < ARRAY_SIZE(jmp_code); i++) {
- int retval = wait_for_pracc_rw(ejtag_info, 0);
+ retval = wait_for_pracc_rw(ejtag_info, 0);
if (retval != ERROR_OK)
- return retval;
+ goto exit_free;

mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
mips_ejtag_drscan_32_out(ejtag_info, jmp_code[i]);
@@ -987,48 +1001,81 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are
}

/* wait PrAcc pending bit for FASTDATA write, read address */
- int retval = wait_for_pracc_rw(ejtag_info, READ_ADDR);
+ retval = wait_for_pracc_rw(ejtag_info, READ_ADDR);
if (retval != ERROR_OK)
- return retval;
+ goto exit_free;

/* next fetch to dmseg should be in FASTDATA_AREA, check */
- if (ejtag_info->pa_addr != MIPS32_PRACC_FASTDATA_AREA)
- return ERROR_FAIL;
-
- mips_ejtag_update_clocks(ejtag_info);
+ if (ejtag_info->pa_addr != MIPS32_PRACC_FASTDATA_AREA) {
+ retval = ERROR_FAIL;
+ goto exit;
+ }

/* Send the load start address */
uint32_t val = addr;
- mips_ejtag_fastdata_scan(ejtag_info, 1, &val, 1);
+ mips_ejtag_fastdata_scan(ejtag_info, 1, &val, in_buf, 1);

retval = wait_for_pracc_rw(ejtag_info, 0);
if (retval != ERROR_OK)
- return retval;
+ goto exit_free;

/* Send the load end address */
val = addr + (count - 1) * 4;
- mips_ejtag_fastdata_scan(ejtag_info, 1, &val, 1);
+ mips_ejtag_fastdata_scan(ejtag_info, 1, &val, in_buf, 1);

+ int failed_scan = 0;
+ int consecutive_fails = 0;
while (count) {
+ int fails = 0;
int this_round_count = count > XFER_BLOCK ? XFER_BLOCK : count;
- mips_ejtag_fastdata_scan(ejtag_info, 1, buf, this_round_count);
+ mips_ejtag_fastdata_scan(ejtag_info, write_t, buf, in_buf, this_round_count);

retval = jtag_execute_queue();
if (retval != ERROR_OK) {
LOG_ERROR("fastdata load failed");
- return retval;
+ goto exit_free;
}

- buf += this_round_count;
- count -= this_round_count;
+ for (int i = 0; i != this_round_count; i++) {
+ if (in_buf[i * 5] & 1) { /* check spracc, 1: successful scan */
+ consecutive_fails = 0;
+ if (!write_t)
+ *buf++ = buf_get_u32(&in_buf[1 + (i * 5)], 0, 32);
+ } else {
+ fails++;
+ consecutive_fails++;
+ }
+ }
+
+ if (consecutive_fails > 1000) { /* something is wrong, exception ?, needs check, for now exit*/
+ LOG_ERROR("excessive fails");
+ goto exit;
+ }
+
+ if (fails)
+ failed_scan++;
+
+ if (write_t) {
+ if (failed_scan)
+ buf = NULL; /* afterwards shift out only 0's */
+ else
+ buf += this_round_count;
+ }
+
+ count -= this_round_count - fails; /* successful scans only */
}

+ if (failed_scan && write_t)
+ LOG_USER("failed to download, increase scan delay and or reduce scan rate");
+exit:
retval = wait_for_pracc_rw(ejtag_info, READ_ADDR);
if (retval != ERROR_OK)
- return retval;
+ goto exit_free;

- if (ejtag_info->pa_addr != MIPS32_PRACC_TEXT)
+ if (ejtag_info->pa_addr != MIPS32_PRACC_TEXT) /* should not occur, but... */
LOG_ERROR("mini program did not return to start");

+exit_free:
+ free(in_buf);
return retval;
}
diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h
index b01ffce..4f4a46b 100644
--- a/src/target/mips32_pracc.h
+++ b/src/target/mips32_pracc.h
@@ -45,7 +45,7 @@

#define PRACC_BLOCK 128 /* 1 Kbyte */
#define READ_ADDR 1
-#define XFER_BLOCK 1024 /* 4 kbyte */
+#define XFER_BLOCK 1024 /* 4 kbyte of data */

typedef struct {
uint32_t instr;
diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c
index d7a4093..93ca480 100644
--- a/src/target/mips_ejtag.c
+++ b/src/target/mips_ejtag.c
@@ -386,11 +386,13 @@ int mips_ejtag_init(struct mips_ejtag *ejtag_info)
return ERROR_OK;
}

-void mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_t *data, int count)
+void mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t,
+ uint32_t *data_out, uint8_t *data_in, int count)
{
mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA);

for (int i = 0; i != count; i++) {
+
assert(ejtag_info->tap != NULL);
struct jtag_tap *tap = ejtag_info->tap;

@@ -401,7 +403,7 @@ void mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32

uint8_t spracc = 0;
fields[0].out_value = &spracc;
- fields[0].in_value = NULL;
+ fields[0].in_value = &data_in[i * 5];

/* processor access data register 32 bit */
fields[1].num_bits = 32;
@@ -411,17 +413,13 @@ void mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32

if (write_t) {
fields[1].in_value = NULL;
- buf_set_u32(t, 0, 32, *data);
+ if (data_out) /* if data_out == NULL, shift out 0 */
+ buf_set_u32(t, 0, 32, *data_out++);
} else
- fields[1].in_value = (uint8_t *) data;
+ fields[1].in_value = &data_in[1 + (i * 5)];

jtag_add_clocks(ejtag_info->clocks);
jtag_add_dr_scan(tap, 2, fields, TAP_IDLE);
-
- if (!write_t && data)
- jtag_add_callback(mips_le_to_h_u32,
- (jtag_callback_data_t) data);
- data++;
}

keep_alive();
diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h
index ec9d547..3642e7d 100644
--- a/src/target/mips_ejtag.h
+++ b/src/target/mips_ejtag.h
@@ -238,8 +238,8 @@ int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data);
void mips_ejtag_drscan_32_queued(struct mips_ejtag *ejtag_info, uint32_t data_out, uint8_t *data_in);
void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data);
int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint8_t *data);
-void mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_t *data, int count);
-
+void mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t,
+ uint32_t *data_out, uint8_t *data_in, int count);
int mips_ejtag_init(struct mips_ejtag *ejtag_info);
int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step);

diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c
index dd351d7..19a9c96 100644
--- a/src/target/mips_m4k.c
+++ b/src/target/mips_m4k.c
@@ -46,6 +46,7 @@ static int mips_m4k_internal_restore(struct target *target, int current,
static int mips_m4k_halt(struct target *target);
static int mips_m4k_bulk_write_memory(struct target *target, target_addr_t address,
uint32_t count, const uint8_t *buffer);
+static int mips_m4k_bulk_read_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *buf);

static int mips_m4k_examine_debug_reason(struct target *target)
{
@@ -1049,25 +1050,26 @@ static int mips_m4k_read_memory(struct target *target, target_addr_t address,
} else
t = buffer;

- /* if noDMA off, use DMAACC mode for memory read */
int retval;
+ if (size == 4 && count > 32) {
+ retval = mips_m4k_bulk_read_memory(target, address, count, t);
+ if (retval == ERROR_OK)
+ goto save;
+ LOG_WARNING("Falling back to non-bulk read");
+ }
+
+ /* if noDMA off, use DMAACC mode for memory read */
if (ejtag_info->impcode & EJTAG_IMP_NODMA)
retval = mips32_pracc_read_mem(ejtag_info, address, size, count, t);
else
retval = mips32_dmaacc_read_mem(ejtag_info, address, size, count, t);

+save:
/* mips32_..._read_mem with size 4/2 returns uint32_t/uint16_t in host */
/* endianness, but byte array should represent target endianness */
- if (ERROR_OK == retval) {
- switch (size) {
- case 4:
- target_buffer_set_u32_array(target, buffer, count, t);
- break;
- case 2:
+ if (ERROR_OK == retval && size > 1)
+ size == 4 ? target_buffer_set_u32_array(target, buffer, count, t) :
target_buffer_set_u16_array(target, buffer, count, t);
- break;
- }
- }

if ((size > 1) && (t != NULL))
free(t);
@@ -1114,14 +1116,9 @@ static int mips_m4k_write_memory(struct target *target, target_addr_t address,
return ERROR_FAIL;
}

- switch (size) {
- case 4:
- target_buffer_get_u32_array(target, buffer, count, (uint32_t *)t);
- break;
- case 2:
+ size == 4 ? target_buffer_get_u32_array(target, buffer, count, (uint32_t *)t) :
target_buffer_get_u16_array(target, buffer, count, (uint16_t *)t);
- break;
- }
+
buffer = t;
}

@@ -1135,10 +1132,7 @@ static int mips_m4k_write_memory(struct target *target, target_addr_t address,
if (t != NULL)
free(t);

- if (ERROR_OK != retval)
- return retval;
-
- return ERROR_OK;
+ return retval;
}

static int mips_m4k_init_target(struct command_context *cmd_ctx,
@@ -1184,7 +1178,7 @@ static int mips_m4k_examine(struct target *target)
return retval;
}
if (((ejtag_info->idcode >> 1) & 0x7FF) == 0x29) {
- /* we are using a pic32mx so select ejtag port
+ /* we are using a pic32 so select ejtag port
* as it is not selected by default */
mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP);
LOG_DEBUG("PIC32 Detected - using EJTAG Interface");
@@ -1268,6 +1262,28 @@ static int mips_m4k_bulk_write_memory(struct target *target, target_addr_t addre
return retval;
}

+static int mips_m4k_bulk_read_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *buf)
+{
+ struct mips32_common *mips32 = target_to_mips32(target);
+ struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
+
+ LOG_DEBUG("address: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, count);
+
+ if (mips32->fast_data_area == NULL) {
+ int retval = target_alloc_working_area(target, MIPS32_FASTDATA_HANDLER_SIZE,
+ &mips32->fast_data_area);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("No working area available");
+ return retval;
+ }
+
+ ejtag_info->fast_access_save = -1; /* force handler reload */
+ }
+
+ int write_t = 0;
+ return mips32_pracc_fastdata_xfer(ejtag_info, mips32->fast_data_area, write_t, address, count, buf);
+}
+
static int mips_m4k_verify_pointer(struct command_context *cmd_ctx,
struct mips_m4k_common *mips_m4k)
{

--

Loading...