quark: add Intel Quark mcu D2000 support 99/3199/2
authorIvan De Cesaris <ivan.de.cesaris@intel.com>
Tue, 12 Jan 2016 15:30:18 +0000 (16:30 +0100)
committerAndreas Fritiofson <andreas.fritiofson@gmail.com>
Sat, 13 Feb 2016 22:55:41 +0000 (22:55 +0000)
Add support for the Intel Quark mcu D2000 using the new quark_d2xx
target.

Changes to the lakemont part are needed for the D2000 core and
backwards compatible with the X1000 one.

Change-Id: I6e1ef5a5d116344942f08e413965abd3945235fa
Signed-off-by: Ivan De Cesaris <ivan.de.cesaris@intel.com>
Reviewed-on: http://openocd.zylin.com/3199
Tested-by: jenkins
Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
src/target/Makefile.am
src/target/lakemont.c
src/target/lakemont.h
src/target/quark_d20xx.c [new file with mode: 0644]
src/target/quark_x10xx.c
src/target/target.c
src/target/x86_32_common.h
tcl/board/quark_d2000_refboard.cfg [new file with mode: 0644]
tcl/target/quark_d20xx.cfg [new file with mode: 0644]

index 9f47b1fd86679fca021e7adcd7cb13de08b82945..1f4cbba42388cf01c7a68e1aba665bb1ce2c0bee 100644 (file)
@@ -129,6 +129,7 @@ NDS32_SRC = \
 
 INTEL_IA32_SRC = \
        quark_x10xx.c \
 
 INTEL_IA32_SRC = \
        quark_x10xx.c \
+       quark_d20xx.c \
        lakemont.c \
        x86_32_common.c
 
        lakemont.c \
        x86_32_common.c
 
index 055d94340114e44e727ed5c7ca213d3b0b98c4c7..151f4abe81387030f3c3460e979befaf0c0baef6 100644 (file)
@@ -1,11 +1,12 @@
 /*
 /*
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013-2016 Intel Corporation.
  *
  * Adrian Burns (adrian.burns@intel.com)
  * Thomas Faust (thomas.faust@intel.com)
  * Ivan De Cesaris (ivan.de.cesaris@intel.com)
  * Julien Carreno (julien.carreno@intel.com)
  * Jeffrey Maxwell (jeffrey.r.maxwell@intel.com)
  *
  * Adrian Burns (adrian.burns@intel.com)
  * Thomas Faust (thomas.faust@intel.com)
  * Ivan De Cesaris (ivan.de.cesaris@intel.com)
  * Julien Carreno (julien.carreno@intel.com)
  * Jeffrey Maxwell (jeffrey.r.maxwell@intel.com)
+ * Jessica Gomez (jessica.gomez.hernandez@intel.com)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -498,6 +499,12 @@ static int halt_prep(struct target *t)
        if (write_hw_reg(t, DSAR, PM_DSAR, 0) != ERROR_OK)
                return ERROR_FAIL;
        LOG_DEBUG("write DSAR 0x%08" PRIx32, PM_DSAR);
        if (write_hw_reg(t, DSAR, PM_DSAR, 0) != ERROR_OK)
                return ERROR_FAIL;
        LOG_DEBUG("write DSAR 0x%08" PRIx32, PM_DSAR);
+       if (write_hw_reg(t, CSB, PM_DSB, 0) != ERROR_OK)
+               return ERROR_FAIL;
+       LOG_DEBUG("write %s 0x%08" PRIx32, regs[CSB].name, PM_DSB);
+       if (write_hw_reg(t, CSL, PM_DSL, 0) != ERROR_OK)
+               return ERROR_FAIL;
+       LOG_DEBUG("write %s 0x%08" PRIx32, regs[CSL].name, PM_DSL);
        if (write_hw_reg(t, DR7, PM_DR7, 0) != ERROR_OK)
                return ERROR_FAIL;
        LOG_DEBUG("write DR7 0x%08" PRIx32, PM_DR7);
        if (write_hw_reg(t, DR7, PM_DR7, 0) != ERROR_OK)
                return ERROR_FAIL;
        LOG_DEBUG("write DR7 0x%08" PRIx32, PM_DR7);
@@ -511,8 +518,7 @@ static int halt_prep(struct target *t)
        LOG_DEBUG("EFLAGS = 0x%08" PRIx32 ", VM86 = %d, IF = %d", eflags,
                        eflags & EFLAGS_VM86 ? 1 : 0,
                        eflags & EFLAGS_IF ? 1 : 0);
        LOG_DEBUG("EFLAGS = 0x%08" PRIx32 ", VM86 = %d, IF = %d", eflags,
                        eflags & EFLAGS_VM86 ? 1 : 0,
                        eflags & EFLAGS_IF ? 1 : 0);
-       if (eflags & EFLAGS_VM86
-               || eflags & EFLAGS_IF) {
+       if ((eflags & EFLAGS_VM86) || (eflags & EFLAGS_IF)) {
                x86_32->pm_regs[I(EFLAGS)] = eflags & ~(EFLAGS_VM86 | EFLAGS_IF);
                if (write_hw_reg(t, EFLAGS, x86_32->pm_regs[I(EFLAGS)], 0) != ERROR_OK)
                        return ERROR_FAIL;
                x86_32->pm_regs[I(EFLAGS)] = eflags & ~(EFLAGS_VM86 | EFLAGS_IF);
                if (write_hw_reg(t, EFLAGS, x86_32->pm_regs[I(EFLAGS)], 0) != ERROR_OK)
                        return ERROR_FAIL;
@@ -530,14 +536,14 @@ static int halt_prep(struct target *t)
                LOG_DEBUG("write CSAR_CPL to 0 0x%08" PRIx32, x86_32->pm_regs[I(CSAR)]);
        }
        if (ssar & SSAR_DPL) {
                LOG_DEBUG("write CSAR_CPL to 0 0x%08" PRIx32, x86_32->pm_regs[I(CSAR)]);
        }
        if (ssar & SSAR_DPL) {
-               x86_32->pm_regs[I(SSAR)] = ssar & ~CSAR_DPL;
+               x86_32->pm_regs[I(SSAR)] = ssar & ~SSAR_DPL;
                if (write_hw_reg(t, SSAR, x86_32->pm_regs[I(SSAR)], 0) != ERROR_OK)
                        return ERROR_FAIL;
                LOG_DEBUG("write SSAR_CPL to 0 0x%08" PRIx32, x86_32->pm_regs[I(SSAR)]);
        }
 
                if (write_hw_reg(t, SSAR, x86_32->pm_regs[I(SSAR)], 0) != ERROR_OK)
                        return ERROR_FAIL;
                LOG_DEBUG("write SSAR_CPL to 0 0x%08" PRIx32, x86_32->pm_regs[I(SSAR)]);
        }
 
-       /* if cache's are enabled, disable and flush */
-       if (!(cr0 & CR0_CD)) {
+       /* if cache's are enabled, disable and flush, depending on the core version */
+       if (!(x86_32->core_type == LMT3_5) && !(cr0 & CR0_CD)) {
                LOG_DEBUG("caching enabled CR0 = 0x%08" PRIx32, cr0);
                if (cr0 & CR0_PG) {
                        x86_32->pm_regs[I(CR0)] = cr0 & ~CR0_PG;
                LOG_DEBUG("caching enabled CR0 = 0x%08" PRIx32, cr0);
                if (cr0 & CR0_PG) {
                        x86_32->pm_regs[I(CR0)] = cr0 & ~CR0_PG;
@@ -563,6 +569,13 @@ static int do_halt(struct target *t)
        t->state = TARGET_DEBUG_RUNNING;
        if (enter_probemode(t) != ERROR_OK)
                return ERROR_FAIL;
        t->state = TARGET_DEBUG_RUNNING;
        if (enter_probemode(t) != ERROR_OK)
                return ERROR_FAIL;
+
+       return lakemont_update_after_probemode_entry(t);
+}
+
+/* we need to expose the update to be able to complete the reset at SoC level */
+int lakemont_update_after_probemode_entry(struct target *t)
+{
        if (save_context(t) != ERROR_OK)
                return ERROR_FAIL;
        if (halt_prep(t) != ERROR_OK)
        if (save_context(t) != ERROR_OK)
                return ERROR_FAIL;
        if (halt_prep(t) != ERROR_OK)
@@ -677,16 +690,16 @@ static int write_hw_reg(struct target *t, int reg, uint32_t regval, uint8_t cach
                        arch_info->op,
                        regval);
 
                        arch_info->op,
                        regval);
 
-       scan.out[0] = RDWRPDR;
        x86_32->flush = 0; /* dont flush scans till we have a batch */
        x86_32->flush = 0; /* dont flush scans till we have a batch */
-       if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK)
-               return ERROR_FAIL;
-       if (drscan(t, reg_buf, scan.out, PDR_SIZE) != ERROR_OK)
-               return ERROR_FAIL;
        if (submit_reg_pir(t, reg) != ERROR_OK)
                return ERROR_FAIL;
        if (submit_instruction_pir(t, SRAMACCESS) != ERROR_OK)
                return ERROR_FAIL;
        if (submit_reg_pir(t, reg) != ERROR_OK)
                return ERROR_FAIL;
        if (submit_instruction_pir(t, SRAMACCESS) != ERROR_OK)
                return ERROR_FAIL;
+       scan.out[0] = RDWRPDR;
+       if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK)
+               return ERROR_FAIL;
+       if (drscan(t, reg_buf, scan.out, PDR_SIZE) != ERROR_OK)
+               return ERROR_FAIL;
        x86_32->flush = 1;
        if (submit_instruction_pir(t, PDR2SRAM) != ERROR_OK)
                return ERROR_FAIL;
        x86_32->flush = 1;
        if (submit_instruction_pir(t, PDR2SRAM) != ERROR_OK)
                return ERROR_FAIL;
index 30b34b3f2e34f7bd55449d8b3c6fe189b5930cf0..1075ad31d499fc431fef56158b764ebb0622db55 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013-2016 Intel Corporation.
  *
  * Adrian Burns (adrian.burns@intel.com)
  * Thomas Faust (thomas.faust@intel.com)
  *
  * Adrian Burns (adrian.burns@intel.com)
  * Thomas Faust (thomas.faust@intel.com)
@@ -101,5 +101,6 @@ int lakemont_step(struct target *t, int current,
                        uint32_t address, int handle_breakpoints);
 int lakemont_reset_assert(struct target *t);
 int lakemont_reset_deassert(struct target *t);
                        uint32_t address, int handle_breakpoints);
 int lakemont_reset_assert(struct target *t);
 int lakemont_reset_deassert(struct target *t);
+int lakemont_update_after_probemode_entry(struct target *t);
 
 #endif /* LAKEMONT_H */
 
 #endif /* LAKEMONT_H */
diff --git a/src/target/quark_d20xx.c b/src/target/quark_d20xx.c
new file mode 100644 (file)
index 0000000..f797214
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright(c) 2015-2016 Intel Corporation.
+ *
+ * Jessica Gomez (jessica.gomez.hernandez@intel.com)
+ * Ivan De Cesaris (ivan.de.cesaris@intel.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * Contact Information:
+ * Intel Corporation
+ */
+
+/*
+ * @file
+ * Debugger for Intel Quark D20xx
+ * The CPU TAP (Lakemont TAP) is used for software debug and the CLTAP is
+ * used for SoC level operations.
+ *
+ * Reference document:
+ * Intel Quark microcontroller D2000 Debug Operations (web search for doc num 333241)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/log.h>
+
+#include "target.h"
+#include "target_type.h"
+#include "breakpoints.h"
+#include "lakemont.h"
+#include "x86_32_common.h"
+
+int quark_d20xx_target_create(struct target *t, Jim_Interp *interp)
+{
+       struct x86_32_common *x86_32 = calloc(1, sizeof(struct x86_32_common));
+       if (x86_32 == NULL) {
+               LOG_ERROR("%s out of memory", __func__);
+               return ERROR_FAIL;
+       }
+       x86_32_common_init_arch_info(t, x86_32);
+       lakemont_init_arch_info(t, x86_32);
+       x86_32->core_type = LMT3_5;
+       return ERROR_OK;
+}
+
+int quark_d20xx_init_target(struct command_context *cmd_ctx, struct target *t)
+{
+       return lakemont_init_target(cmd_ctx, t);
+}
+
+static int quark_d20xx_reset_deassert(struct target *t)
+{
+       int retval;
+
+       /* Can't detect if a warm reset happened while halted but we can make the
+        * openocd and target state consistent here if in probe mode already
+        */
+       if (!check_not_halted(t)) {
+               retval = lakemont_update_after_probemode_entry(t);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("%s core state update fail", __func__);
+                       return retval;
+               }
+               /* resume target if reset mode is run */
+               if (!t->reset_halt) {
+                       retval = lakemont_resume(t, 1, 0, 0, 0);
+                       if (retval != ERROR_OK) {
+                               LOG_ERROR("%s could not resume target", __func__);
+                               return retval;
+                       }
+               }
+       }
+
+       return ERROR_OK;
+}
+
+struct target_type quark_d20xx_target = {
+       .name = "quark_d20xx",
+       .target_create = quark_d20xx_target_create,
+       .init_target = quark_d20xx_init_target,
+       /* lakemont probemode specific code */
+       .poll = lakemont_poll,
+       .arch_state = lakemont_arch_state,
+       .halt = lakemont_halt,
+       .resume = lakemont_resume,
+       .step = lakemont_step,
+       .assert_reset = lakemont_reset_assert,
+       .deassert_reset = quark_d20xx_reset_deassert,
+       /* common x86 code */
+       .commands = x86_32_command_handlers,
+       .get_gdb_reg_list = x86_32_get_gdb_reg_list,
+       .read_memory = x86_32_common_read_memory,
+       .write_memory = x86_32_common_write_memory,
+       .add_breakpoint = x86_32_common_add_breakpoint,
+       .remove_breakpoint = x86_32_common_remove_breakpoint,
+       .add_watchpoint = x86_32_common_add_watchpoint,
+       .remove_watchpoint = x86_32_common_remove_watchpoint,
+       .virt2phys = x86_32_common_virt2phys,
+       .read_phys_memory = x86_32_common_read_phys_mem,
+       .write_phys_memory = x86_32_common_write_phys_mem,
+       .mmu = x86_32_common_mmu,
+};
index 9a1ccb65dda6827104f8f96984dafd0ad4fd3f1d..a3b8a266df944667fd635a7ec3c59967a55e6350 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013-2016 Intel Corporation.
  *
  * Adrian Burns (adrian.burns@intel.com)
  * Thomas Faust (thomas.faust@intel.com)
  *
  * Adrian Burns (adrian.burns@intel.com)
  * Thomas Faust (thomas.faust@intel.com)
@@ -61,6 +61,7 @@ int quark_x10xx_target_create(struct target *t, Jim_Interp *interp)
        }
        x86_32_common_init_arch_info(t, x86_32);
        lakemont_init_arch_info(t, x86_32);
        }
        x86_32_common_init_arch_info(t, x86_32);
        lakemont_init_arch_info(t, x86_32);
+       x86_32->core_type = LMT1;
        return ERROR_OK;
 }
 
        return ERROR_OK;
 }
 
index 598d7d5a8043303b4ddbef21082c19bd9e7cb262..6df8d8b97124b50d28c832a535aad326e472ff1c 100644 (file)
@@ -104,6 +104,7 @@ extern struct target_type nds32_v3_target;
 extern struct target_type nds32_v3m_target;
 extern struct target_type or1k_target;
 extern struct target_type quark_x10xx_target;
 extern struct target_type nds32_v3m_target;
 extern struct target_type or1k_target;
 extern struct target_type quark_x10xx_target;
+extern struct target_type quark_d20xx_target;
 
 static struct target_type *target_types[] = {
        &arm7tdmi_target,
 
 static struct target_type *target_types[] = {
        &arm7tdmi_target,
@@ -133,6 +134,7 @@ static struct target_type *target_types[] = {
        &nds32_v3m_target,
        &or1k_target,
        &quark_x10xx_target,
        &nds32_v3m_target,
        &or1k_target,
        &quark_x10xx_target,
+       &quark_d20xx_target,
        NULL,
 };
 
        NULL,
 };
 
index af57a5f7eefeca9bc6323a210ac1011e5599f4a8..c9cb389b52be59d517ec7d624afe6389b16aa5e0 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2013-2016 Intel Corporation.
  *
  * Adrian Burns (adrian.burns@intel.com)
  * Thomas Faust (thomas.faust@intel.com)
  *
  * Adrian Burns (adrian.burns@intel.com)
  * Thomas Faust (thomas.faust@intel.com)
@@ -196,6 +196,11 @@ enum {
        WBINVD,
 };
 
        WBINVD,
 };
 
+enum x86_core_type {
+       LMT1,
+       LMT3_5
+};
+
 struct swbp_mem_patch {
        uint8_t orig_byte;
        uint32_t swbp_unique_id;
 struct swbp_mem_patch {
        uint8_t orig_byte;
        uint32_t swbp_unique_id;
@@ -209,6 +214,7 @@ struct swbp_mem_patch {
 struct x86_32_common {
        uint32_t common_magic;
        void *arch_info;
 struct x86_32_common {
        uint32_t common_magic;
        void *arch_info;
+       enum x86_core_type core_type;
        struct reg_cache *cache;
        struct jtag_tap *curr_tap;
        uint32_t stored_pc;
        struct reg_cache *cache;
        struct jtag_tap *curr_tap;
        uint32_t stored_pc;
diff --git a/tcl/board/quark_d2000_refboard.cfg b/tcl/board/quark_d2000_refboard.cfg
new file mode 100644 (file)
index 0000000..d1388bb
--- /dev/null
@@ -0,0 +1,15 @@
+# Intel Quark microcontroller D2000 Reference Board (web search for doc num 333582)
+
+# the board has an onboard FTDI FT232H chip
+interface ftdi
+ftdi_vid_pid 0x0403 0x6014
+ftdi_channel 0
+
+ftdi_layout_init 0x0000 0x030b
+ftdi_layout_signal nTRST -data 0x0100 -noe 0x0100
+
+source [find target/quark_d20xx.cfg]
+
+adapter_khz 1000
+
+reset_config trst_only
diff --git a/tcl/target/quark_d20xx.cfg b/tcl/target/quark_d20xx.cfg
new file mode 100644 (file)
index 0000000..419f9dc
--- /dev/null
@@ -0,0 +1,50 @@
+if { [info exists CPUTAPID] } {
+   set _CPUTAPID $CPUTAPID
+} else {
+   set _CPUTAPID 0x38289013
+}
+
+jtag newtap quark_d20xx quark -irlen 8 -irmask 0xff -expected-id $_CPUTAPID -disable
+jtag newtap quark_d20xx cltap -irlen 8 -irmask 0xff -expected-id 0x0e786013 -enable
+
+proc quark_d20xx_tapenable {} {
+       echo "enabling quark core tap"
+       irscan quark_d20xx.cltap 0x11
+       drscan quark_d20xx.cltap 12 1
+       runtest 10
+}
+
+proc quark_d20xx_tapdisable {} {
+       echo "disabling quark core tap"
+       irscan quark_d20xx.cltap 0x11
+       drscan quark_d20xx.cltap 12 0
+       runtest 10
+}
+
+proc quark_d20xx_setup {} {
+       jtag tapenable quark_d20xx.quark
+}
+
+jtag configure quark_d20xx.quark -event tap-enable \
+   "quark_d20xx_tapenable"
+
+jtag configure quark_d20xx.quark -event tap-disable \
+   "quark_d20xx_tapdisable"
+
+target create quark_d20xx.quark quark_d20xx -endian little -chain-position quark_d20xx.quark
+
+quark_d20xx.quark configure -event gdb-attach { halt }
+
+quark_d20xx.quark configure -event reset-start {
+       # need to halt the target to write to memory
+       if {[quark_d20xx.quark curstate] ne "halted"} { halt }
+       # set resetbreak via the core tap
+       irscan quark_d20xx.quark 0x35 ; drscan quark_d20xx.quark 1 0x1
+       # trigger a warm reset
+       mww 0xb0800570 0x2
+       # clear resetbreak
+       irscan quark_d20xx.quark 0x35 ; drscan quark_d20xx.quark 1 0x0
+}
+
+jtag configure quark_d20xx.quark -event setup \
+   "quark_d20xx_setup"

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)