This is an automated email from Gerrit. Christopher Head (ch...@zaber.com) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/2381
-- gerrit commit 788a7dcf4096ab549d277dba8c2b4a5fcdede5c4 Author: Christopher Head <ch...@zaber.com> Date: Fri Nov 7 14:44:17 2014 -0800 src/target/cortex_a.c: avoid extra memory read Without this patch, to perform a memory read, OpenOCD first issues an LDC instruction into DBGITR in Stall mode (thus executing the instruction), then switches to Fast mode and reads from DBGDTRTX once for each word to transfer. At the very end of the transfer, the final Fast mode read of DBGDTRTX has, as always, the side effect of re-issuing the LDC instruction. This causes two problems: (1) If the word immediately beyond the end of the requested region is inaccessible, this spurious LDC will cause a fault. On a fast CPU, the LDC will finish executing by the time the poll of DSCR takes place, failing the entire memory read. On a slow CPU, the LDC might finish executing later, leaving an unexpected and confusing sticky fault lying around for the next operation to see. (2) If the LDC succeeds, it will leave the loaded word in DBGDTRTX, thus setting DBGDSCR.TXFULL=1. The cortex_a_read_apb_ab_memory routine completes without consuming that last word, thus confusing the next routine that tries to use DBGDTRTX (this may not have any visible effect on some implementations, because writing to DBGDTRTXint when TXFULL=1 is defined as Unpredictable, but I believe it caused a visible problem for me). With this patch, the bulk mem_ap_sel_read_buf_noincr is modified to omit the last word of the block. The second-to-last read of DBGDTRTX by that function will cause the issue of the LDC for the last word. After switching back to Normal mode and waiting for that instruction to finish, do a final read of DBGDTRTX to extract the last word into the buffer, leaving TXFULL=0. Change-Id: I11ae7104fbe69a522efadefc705c9a217a7eef41 Signed-off-by: Christopher Head <ch...@zaber.com> diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 0393a44..160acfb 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -2031,15 +2031,21 @@ static int cortex_a_read_apb_ab_memory(struct target *target, /* address and read length are aligned so read directely into the passed buffer */ u8buf_ptr = buffer; - /* Read the data - Each read of the DTRTX register causes the instruction to be reissued + /* Read most of the data - Each read of the DTRTX register causes the instruction to be reissued * Abort flags are sticky, so can be read at end of transactions * * This data is read in aligned to 32 bit boundary. + * + * Avoid reading the last word; in fast mode, doing so would start yet another read, which: + * (1) might overrun the end of a valid memory area and cause an undesirable fault, and + * (2) would, on success, leave DTRTX full when it was not expected to be */ - retval = mem_ap_sel_read_buf_noincr(swjdp, armv7a->debug_ap, u8buf_ptr, 4, total_u32, - armv7a->debug_base + CPUDBG_DTRTX); - if (retval != ERROR_OK) - goto error_unset_dtr_r; + if (total_u32 > 1) { + retval = mem_ap_sel_read_buf_noincr(swjdp, armv7a->debug_ap, u8buf_ptr, 4, total_u32 - 1, + armv7a->debug_base + CPUDBG_DTRTX); + if (retval != ERROR_OK) + goto error_unset_dtr_r; + } /* set DTR access mode back to non blocking b00 */ dscr = (dscr & ~DSCR_EXT_DCC_MASK) | DSCR_EXT_DCC_NON_BLOCKING; @@ -2056,6 +2062,11 @@ static int cortex_a_read_apb_ab_memory(struct target *target, goto error_free_buff_r; } while ((dscr & DSCR_INSTR_COMP) == 0); + /* Read the last word of data, in non blocking mode. */ + retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, + armv7a->debug_base + CPUDBG_DTRTX, + (uint32_t*)(u8buf_ptr + 4 * (total_u32 - 1))); + /* Check for sticky abort flags in the DSCR */ retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); -- ------------------------------------------------------------------------------ _______________________________________________ OpenOCD-devel mailing list OpenOCD-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openocd-devel