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

Reply via email to