xscale: fix trace buffer functionality when resuming from a breakpoint
[openocd.git] / src / target / xscale.c
index 50c9595006e9336f08bb30ddd9c57cb91c86ce0a..24c07941b549765c4db7d7b3bec2098b8371cd1f 100644 (file)
@@ -158,7 +158,7 @@ static int xscale_verify_pointer(struct command_context *cmd_ctx,
        return ERROR_OK;
 }
 
-static int xscale_jtag_set_instr(struct jtag_tap *tap, uint32_t new_instr)
+static int xscale_jtag_set_instr(struct jtag_tap *tap, uint32_t new_instr, tap_state_t end_state)
 {
        if (tap == NULL)
                return ERROR_FAIL;
@@ -171,9 +171,9 @@ static int xscale_jtag_set_instr(struct jtag_tap *tap, uint32_t new_instr)
                memset(&field, 0, sizeof field);
                field.num_bits = tap->ir_length;
                field.out_value = scratch;
-               buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
+               buf_set_u32(scratch, 0, field.num_bits, new_instr);
 
-               jtag_add_ir_scan(tap, &field, jtag_get_end_state());
+               jtag_add_ir_scan(tap, &field, end_state);
        }
 
        return ERROR_OK;
@@ -191,9 +191,9 @@ static int xscale_read_dcsr(struct target *target)
        uint8_t field2_check_value = 0x0;
        uint8_t field2_check_mask = 0x1;
 
-       jtag_set_end_state(TAP_DRPAUSE);
        xscale_jtag_set_instr(target->tap,
-               XSCALE_SELDCSR << xscale->xscale_variant);
+               XSCALE_SELDCSR << xscale->xscale_variant,
+               TAP_DRPAUSE);
 
        buf_set_u32(&field0, 1, 1, xscale->hold_rst);
        buf_set_u32(&field0, 2, 1, xscale->external_debug_break);
@@ -213,7 +213,7 @@ static int xscale_read_dcsr(struct target *target)
        uint8_t tmp2;
        fields[2].in_value = &tmp2;
 
-       jtag_add_dr_scan(target->tap, 3, fields, jtag_get_end_state());
+       jtag_add_dr_scan(target->tap, 3, fields, TAP_DRPAUSE);
 
        jtag_check_value_mask(fields + 0, &field0_check_value, &field0_check_mask);
        jtag_check_value_mask(fields + 2, &field2_check_value, &field2_check_mask);
@@ -234,9 +234,7 @@ static int xscale_read_dcsr(struct target *target)
        fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;
        fields[1].in_value = NULL;
 
-       jtag_set_end_state(TAP_IDLE);
-
-       jtag_add_dr_scan(target->tap, 3, fields, jtag_get_end_state());
+       jtag_add_dr_scan(target->tap, 3, fields, TAP_DRPAUSE);
 
        /* DANGER!!! this must be here. It will make sure that the arguments
         * to jtag_set_check_value() does not go out of scope! */
@@ -285,10 +283,10 @@ static int xscale_receive(struct target *target, uint32_t *buffer, int num_words
        fields[2].check_value = &field2_check_value;
        fields[2].check_mask = &field2_check_mask;
 
-       jtag_set_end_state(TAP_IDLE);
        xscale_jtag_set_instr(target->tap,
-               XSCALE_DBGTX << xscale->xscale_variant);
-       jtag_add_runtest(1, jtag_get_end_state()); /* ensures that we're in the TAP_IDLE state as the above could be a no-op */
+               XSCALE_DBGTX << xscale->xscale_variant,
+               TAP_IDLE);
+       jtag_add_runtest(1, TAP_IDLE); /* ensures that we're in the TAP_IDLE state as the above could be a no-op */
 
        /* repeat until all words have been collected */
        int attempts = 0;
@@ -304,7 +302,7 @@ static int xscale_receive(struct target *target, uint32_t *buffer, int num_words
 
                        fields[1].in_value = (uint8_t *)(field1 + i);
 
-                       jtag_add_dr_scan_check(target->tap, 3, fields, jtag_set_end_state(TAP_IDLE));
+                       jtag_add_dr_scan_check(target->tap, 3, fields, TAP_IDLE);
 
                        jtag_add_callback(xscale_getbuf, (jtag_callback_data_t)(field1 + i));
 
@@ -367,10 +365,9 @@ static int xscale_read_tx(struct target *target, int consume)
        uint8_t field2_check_value = 0x0;
        uint8_t field2_check_mask = 0x1;
 
-       jtag_set_end_state(TAP_IDLE);
-
        xscale_jtag_set_instr(target->tap,
-               XSCALE_DBGTX << xscale->xscale_variant);
+               XSCALE_DBGTX << xscale->xscale_variant,
+               TAP_IDLE);
 
        path[0] = TAP_DRSELECT;
        path[1] = TAP_DRCAPTURE;
@@ -411,7 +408,7 @@ static int xscale_read_tx(struct target *target, int consume)
                        jtag_add_pathmove(ARRAY_SIZE(noconsume_path), noconsume_path);
                }
 
-               jtag_add_dr_scan(target->tap, 3, fields, jtag_set_end_state(TAP_IDLE));
+               jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE);
 
                jtag_check_value_mask(fields + 0, &field0_check_value, &field0_check_mask);
                jtag_check_value_mask(fields + 2, &field2_check_value, &field2_check_mask);
@@ -463,10 +460,9 @@ static int xscale_write_rx(struct target *target)
        uint8_t field2_check_value = 0x0;
        uint8_t field2_check_mask = 0x1;
 
-       jtag_set_end_state(TAP_IDLE);
-
        xscale_jtag_set_instr(target->tap,
-               XSCALE_DBGRX << xscale->xscale_variant);
+               XSCALE_DBGRX << xscale->xscale_variant,
+               TAP_IDLE);
 
        memset(&fields, 0, sizeof fields);
 
@@ -489,7 +485,7 @@ static int xscale_write_rx(struct target *target)
        LOG_DEBUG("polling RX");
        for (;;)
        {
-               jtag_add_dr_scan(target->tap, 3, fields, jtag_set_end_state(TAP_IDLE));
+               jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE);
 
                jtag_check_value_mask(fields + 0, &field0_check_value, &field0_check_mask);
                jtag_check_value_mask(fields + 2, &field2_check_value, &field2_check_mask);
@@ -521,7 +517,7 @@ static int xscale_write_rx(struct target *target)
 
        /* set rx_valid */
        field2 = 0x1;
-       jtag_add_dr_scan(target->tap, 3, fields, jtag_set_end_state(TAP_IDLE));
+       jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE);
 
        if ((retval = jtag_execute_queue()) != ERROR_OK)
        {
@@ -541,10 +537,9 @@ static int xscale_send(struct target *target, uint8_t *buffer, int count, int si
        int retval;
        int done_count = 0;
 
-       jtag_set_end_state(TAP_IDLE);
-
        xscale_jtag_set_instr(target->tap,
-               XSCALE_DBGRX << xscale->xscale_variant);
+               XSCALE_DBGRX << xscale->xscale_variant,
+               TAP_IDLE);
 
        bits[0]=3;
        t[0]=0;
@@ -585,7 +580,7 @@ static int xscale_send(struct target *target, uint8_t *buffer, int count, int si
                                3,
                                bits,
                                t,
-                               jtag_set_end_state(TAP_IDLE));
+                               TAP_IDLE);
                buffer += size;
        }
 
@@ -624,9 +619,9 @@ static int xscale_write_dcsr(struct target *target, int hold_rst, int ext_dbg_br
        if (ext_dbg_brk != -1)
                xscale->external_debug_break = ext_dbg_brk;
 
-       jtag_set_end_state(TAP_IDLE);
        xscale_jtag_set_instr(target->tap,
-               XSCALE_SELDCSR << xscale->xscale_variant);
+               XSCALE_SELDCSR << xscale->xscale_variant,
+               TAP_IDLE);
 
        buf_set_u32(&field0, 1, 1, xscale->hold_rst);
        buf_set_u32(&field0, 2, 1, xscale->external_debug_break);
@@ -646,7 +641,7 @@ static int xscale_write_dcsr(struct target *target, int hold_rst, int ext_dbg_br
        uint8_t tmp2;
        fields[2].in_value = &tmp2;
 
-       jtag_add_dr_scan(target->tap, 3, fields, jtag_get_end_state());
+       jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE);
 
        jtag_check_value_mask(fields + 0, &field0_check_value, &field0_check_mask);
        jtag_check_value_mask(fields + 2, &field2_check_value, &field2_check_mask);
@@ -686,9 +681,9 @@ static int xscale_load_ic(struct target *target, uint32_t va, uint32_t buffer[8]
        LOG_DEBUG("loading miniIC at 0x%8.8" PRIx32 "", va);
 
        /* LDIC into IR */
-       jtag_set_end_state(TAP_IDLE);
        xscale_jtag_set_instr(target->tap,
-               XSCALE_LDIC << xscale->xscale_variant);
+               XSCALE_LDIC << xscale->xscale_variant,
+               TAP_IDLE);
 
        /* CMD is b011 to load a cacheline into the Mini ICache.
         * Loading into the main ICache is deprecated, and unused.
@@ -707,7 +702,7 @@ static int xscale_load_ic(struct target *target, uint32_t va, uint32_t buffer[8]
        fields[1].num_bits = 27;
        fields[1].out_value = packet;
 
-       jtag_add_dr_scan(target->tap, 2, fields, jtag_get_end_state());
+       jtag_add_dr_scan(target->tap, 2, fields, TAP_IDLE);
 
        /* rest of packet is a cacheline: 8 instructions, with parity */
        fields[0].num_bits = 32;
@@ -724,7 +719,7 @@ static int xscale_load_ic(struct target *target, uint32_t va, uint32_t buffer[8]
                memcpy(&value, packet, sizeof(uint32_t));
                cmd = parity(value);
 
-               jtag_add_dr_scan(target->tap, 2, fields, jtag_get_end_state());
+               jtag_add_dr_scan(target->tap, 2, fields, TAP_IDLE);
        }
 
        return jtag_execute_queue();
@@ -737,9 +732,9 @@ static int xscale_invalidate_ic_line(struct target *target, uint32_t va)
        uint8_t cmd;
        struct scan_field fields[2];
 
-       jtag_set_end_state(TAP_IDLE);
        xscale_jtag_set_instr(target->tap,
-               XSCALE_LDIC << xscale->xscale_variant);
+               XSCALE_LDIC << xscale->xscale_variant,
+               TAP_IDLE);
 
        /* CMD for invalidate IC line b000, bits [6:4] b000 */
        buf_set_u32(&cmd, 0, 6, 0x0);
@@ -755,7 +750,7 @@ static int xscale_invalidate_ic_line(struct target *target, uint32_t va)
        fields[1].num_bits = 27;
        fields[1].out_value = packet;
 
-       jtag_add_dr_scan(target->tap, 2, fields, jtag_get_end_state());
+       jtag_add_dr_scan(target->tap, 2, fields, TAP_IDLE);
 
        return ERROR_OK;
 }
@@ -1211,6 +1206,7 @@ static int xscale_resume(struct target *target, int current,
                if (breakpoint != NULL)
                {
                        uint32_t next_pc;
+                       int saved_trace_buffer_enabled;
 
                        /* there's a breakpoint at the current PC, we have to step over it */
                        LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address);
@@ -1230,15 +1226,8 @@ static int xscale_resume(struct target *target, int current,
                        /* restore banked registers */
                        retval = xscale_restore_banked(target);
 
-                       /* send resume request (command 0x30 or 0x31)
-                        * clean the trace buffer if it is to be enabled (0x62) */
-                       if (xscale->trace.buffer_enabled)
-                       {
-                               xscale_send_u32(target, 0x62);
-                               xscale_send_u32(target, 0x31);
-                       }
-                       else
-                               xscale_send_u32(target, 0x30);
+                       /* send resume request */
+                       xscale_send_u32(target, 0x30);
 
                        /* send CPSR */
                        xscale_send_u32(target,
@@ -1259,9 +1248,16 @@ static int xscale_resume(struct target *target, int current,
                        LOG_DEBUG("writing PC with value 0x%8.8" PRIx32,
                                        buf_get_u32(armv4_5->pc->value, 0, 32));
 
+                       /* disable trace data collection in xscale_debug_entry() */
+                       saved_trace_buffer_enabled = xscale->trace.buffer_enabled;
+                       xscale->trace.buffer_enabled = 0;
+
                        /* wait for and process debug entry */
                        xscale_debug_entry(target);
 
+                       /* re-enable trace buffer, if enabled previously */
+                       xscale->trace.buffer_enabled = saved_trace_buffer_enabled;
+
                        LOG_DEBUG("disable single-step");
                        xscale_disable_single_step(target);
 
@@ -1281,6 +1277,12 @@ static int xscale_resume(struct target *target, int current,
         * clean the trace buffer if it is to be enabled (0x62) */
        if (xscale->trace.buffer_enabled)
        {
+               /* if trace buffer is set to 'fill' mode, save starting pc */
+               if (xscale->trace.buffer_fill > 0)
+               {
+                       xscale->trace.pc_ok = 1;
+                       xscale->trace.current_pc = buf_get_u32(armv4_5->pc->value, 0, 32);
+               }
                xscale_send_u32(target, 0x62);
                xscale_send_u32(target, 0x31);
        }
@@ -1476,9 +1478,9 @@ static int xscale_assert_reset(struct target *target)
        /* select DCSR instruction (set endstate to R-T-I to ensure we don't
         * end up in T-L-R, which would reset JTAG
         */
-       jtag_set_end_state(TAP_IDLE);
        xscale_jtag_set_instr(target->tap,
-               XSCALE_SELDCSR << xscale->xscale_variant);
+               XSCALE_SELDCSR << xscale->xscale_variant,
+               TAP_IDLE);
 
        /* set Hold reset, Halt mode and Trap Reset */
        buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 30, 1, 0x1);
@@ -1486,7 +1488,7 @@ static int xscale_assert_reset(struct target *target)
        xscale_write_dcsr(target, 1, 0);
 
        /* select BYPASS, because having DCSR selected caused problems on the PXA27x */
-       xscale_jtag_set_instr(target->tap, ~0);
+       xscale_jtag_set_instr(target->tap, ~0, TAP_IDLE);
        jtag_execute_queue();
 
        /* assert reset */
@@ -1556,7 +1558,7 @@ static int xscale_deassert_reset(struct target *target)
                /* wait 300ms; 150 and 100ms were not enough */
                jtag_add_sleep(300*1000);
 
-               jtag_add_runtest(2030, jtag_set_end_state(TAP_IDLE));
+               jtag_add_runtest(2030, TAP_IDLE);
                jtag_execute_queue();
 
                /* set Hold reset, Halt mode and Trap Reset */
@@ -1613,7 +1615,7 @@ static int xscale_deassert_reset(struct target *target)
                if (retval != ERROR_OK)
                        return retval;
 
-               jtag_add_runtest(30, jtag_set_end_state(TAP_IDLE));
+               jtag_add_runtest(30, TAP_IDLE);
 
                jtag_add_sleep(100000);
 
@@ -2130,7 +2132,7 @@ static int xscale_set_breakpoint(struct target *target,
                        {
                                return retval;
                        }
-                       /* write the original instruction in target endianness (arm7_9->arm_bkpt is host endian) */
+                       /* write the bkpt instruction in target endianness (arm7_9->arm_bkpt is host endian) */
                        if ((retval = target_write_u32(target, breakpoint->address, xscale->arm_bkpt)) != ERROR_OK)
                        {
                                return retval;
@@ -2143,13 +2145,18 @@ static int xscale_set_breakpoint(struct target *target,
                        {
                                return retval;
                        }
-                       /* write the original instruction in target endianness (arm7_9->arm_bkpt is host endian) */
+                       /* write the bkpt instruction in target endianness (arm7_9->arm_bkpt is host endian) */
                        if ((retval = target_write_u32(target, breakpoint->address, xscale->thumb_bkpt)) != ERROR_OK)
                        {
                                return retval;
                        }
                }
                breakpoint->set = 1;
+
+               xscale_send_u32(target, 0x50);   /* clean dcache */
+               xscale_send_u32(target, xscale->cache_clean_address);
+               xscale_send_u32(target, 0x51);   /* invalidate dcache */
+               xscale_send_u32(target, 0x52);   /* invalidate icache and flush fetch buffers */
        }
 
        return ERROR_OK;
@@ -2230,6 +2237,11 @@ static int xscale_unset_breakpoint(struct target *target,
                        }
                }
                breakpoint->set = 0;
+
+               xscale_send_u32(target, 0x50);   /* clean dcache */
+               xscale_send_u32(target, xscale->cache_clean_address);
+               xscale_send_u32(target, 0x51);   /* invalidate dcache */
+               xscale_send_u32(target, 0x52);   /* invalidate icache and flush fetch buffers */
        }
 
        return ERROR_OK;
@@ -3204,14 +3216,19 @@ COMMAND_HANDLER(xscale_handle_idcache_command)
        {
                bool enable;
                COMMAND_PARSE_ENABLE(CMD_ARGV[0], enable);
-               if (enable)
-                       xscale_enable_mmu_caches(target, 1, 0, 0);
-               else
-                       xscale_disable_mmu_caches(target, 1, 0, 0);
-               if (icache)
+               if (icache) {
                        xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled = enable;
-               else
+                       if (enable)
+                               xscale_enable_mmu_caches(target, 0, 0, 1);
+                       else
+                               xscale_disable_mmu_caches(target, 0, 0, 1);
+               } else {
                        xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = enable;
+                       if (enable)
+                               xscale_enable_mmu_caches(target, 0, 1, 0);
+                       else
+                               xscale_disable_mmu_caches(target, 0, 1, 0);
+               }
        }
 
        bool enabled = icache ?
@@ -3419,7 +3436,7 @@ COMMAND_HANDLER(xscale_handle_trace_image_command)
        if (CMD_ARGC >= 2)
        {
                xscale->trace.image->base_address_set = 1;
-               COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], xscale->trace.image->base_address);
+               COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], xscale->trace.image->base_address);
        }
        else
        {

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)