From 48d2c10203ab1b1f6fcc6e2ffa74098edb71f35c Mon Sep 17 00:00:00 2001 From: Christophe Priouzeau Date: Wed, 9 Oct 2019 11:26:10 +0200 Subject: [PATCH] OPENOCD: Support single core and fixes Signed-off-by: Antonio Borneo --- ...ore-align-access-with-mmu-off-plus-f.patch | 251 ++++++++++++++++++ .../openocd/openocd-stm32mp_0.10.0.bb | 1 + 2 files changed, 252 insertions(+) create mode 100644 recipes-devtools/openocd/openocd-stm32mp/0006-Support-single-core-align-access-with-mmu-off-plus-f.patch diff --git a/recipes-devtools/openocd/openocd-stm32mp/0006-Support-single-core-align-access-with-mmu-off-plus-f.patch b/recipes-devtools/openocd/openocd-stm32mp/0006-Support-single-core-align-access-with-mmu-off-plus-f.patch new file mode 100644 index 0000000..acb173a --- /dev/null +++ b/recipes-devtools/openocd/openocd-stm32mp/0006-Support-single-core-align-access-with-mmu-off-plus-f.patch @@ -0,0 +1,251 @@ +From b411d805477bd67856403c73bad41534bcf2aa31 Mon Sep 17 00:00:00 2001 +From: Antonio Borneo +Date: Mon, 20 May 2019 17:25:18 +0200 +Subject: [PATCH] Support single-core, align access with mmu off, plus fixes + +--- + src/target/adi_v5_stlink.c | 12 -------- + src/target/cortex_a.c | 43 ++++++++++++++++++++++++++--- + src/target/cortex_m.c | 8 +++--- + tcl/target/stm32mp15x.cfg | 56 ++++++++++++++++++++++++++++---------- + 4 files changed, 84 insertions(+), 35 deletions(-) + +diff --git a/src/target/adi_v5_stlink.c b/src/target/adi_v5_stlink.c +index 9e7ab0f64..fd4a4e28a 100644 +--- a/src/target/adi_v5_stlink.c ++++ b/src/target/adi_v5_stlink.c +@@ -120,18 +120,6 @@ static int stlink_connect(struct adiv5_dap *dap) + + LOG_INFO("stlink_connect(%sconnect)", dap->do_reconnect ? "re" : ""); + +- /* Check if we should reset srst already when connecting, but not if reconnecting. */ +- if (!dap->do_reconnect) { +- enum reset_types jtag_reset_config = jtag_get_reset_config(); +- +- if (jtag_reset_config & RESET_CNCT_UNDER_SRST) { +- if (jtag_reset_config & RESET_SRST_NO_GATING) +- adapter_assert_reset(); +- else +- LOG_WARNING("\'srst_nogate\' reset_config option is required"); +- } +- } +- + dap->do_reconnect = false; + dap_invalidate_cache(dap); + +diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c +index 499dacc9b..9f6f3d5d2 100644 +--- a/src/target/cortex_a.c ++++ b/src/target/cortex_a.c +@@ -1220,6 +1220,8 @@ static int cortex_a_step(struct target *target, int current, target_addr_t addre + retval = cortex_a_poll(target); + if (retval != ERROR_OK) + return retval; ++ if (target->state == TARGET_HALTED) ++ break; + if (timeval_ms() > then + 1000) { + LOG_ERROR("timeout waiting for target halt"); + return ERROR_FAIL; +@@ -2017,7 +2019,8 @@ static int cortex_a_write_cpu_memory_slow(struct target *target, + { + /* Writes count objects of size size from *buffer. Old value of DSCR must + * be in *dscr; updated to new value. This is slow because it works for +- * non-word-sized objects and (maybe) unaligned accesses. If size == 4 and ++ * non-word-sized objects. Avoid unaligned accesses as they do not work ++ * on memory address space without "Normal" attribute. If size == 4 and + * the address is aligned, cortex_a_write_cpu_memory_fast should be + * preferred. + * Preconditions: +@@ -2174,7 +2177,22 @@ static int cortex_a_write_cpu_memory(struct target *target, + /* We are doing a word-aligned transfer, so use fast mode. */ + retval = cortex_a_write_cpu_memory_fast(target, count, buffer, &dscr); + } else { +- /* Use slow path. */ ++ /* Use slow path. Adjust size for aligned accesses */ ++ switch (address % 4) { ++ case 1: ++ case 3: ++ count *= size; ++ size = 1; ++ break; ++ case 2: ++ if (size == 4) { ++ count *= 2; ++ size = 2; ++ } ++ case 0: ++ default: ++ break; ++ } + retval = cortex_a_write_cpu_memory_slow(target, size, count, buffer, &dscr); + } + +@@ -2260,7 +2278,8 @@ static int cortex_a_read_cpu_memory_slow(struct target *target, + { + /* Reads count objects of size size into *buffer. Old value of DSCR must be + * in *dscr; updated to new value. This is slow because it works for +- * non-word-sized objects and (maybe) unaligned accesses. If size == 4 and ++ * non-word-sized objects. Avoid unaligned accesses as they do not work ++ * on memory address space without "Normal" attribute. If size == 4 and + * the address is aligned, cortex_a_read_cpu_memory_fast should be + * preferred. + * Preconditions: +@@ -2476,7 +2495,23 @@ static int cortex_a_read_cpu_memory(struct target *target, + /* We are doing a word-aligned transfer, so use fast mode. */ + retval = cortex_a_read_cpu_memory_fast(target, count, buffer, &dscr); + } else { +- /* Use slow path. */ ++ /* Use slow path. Adjust size for aligned accesses */ ++ switch (address % 4) { ++ case 1: ++ case 3: ++ count *= size; ++ size = 1; ++ break; ++ case 2: ++ if (size == 4) { ++ count *= 2; ++ size = 2; ++ } ++ break; ++ case 0: ++ default: ++ break; ++ } + retval = cortex_a_read_cpu_memory_slow(target, size, count, buffer, &dscr); + } + +diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c +index 79975aa89..9b962192f 100644 +--- a/src/target/cortex_m.c ++++ b/src/target/cortex_m.c +@@ -532,21 +532,21 @@ static int cortex_m_poll(struct target *target) + if (cortex_m->dcb_dhcsr & S_HALT) { + target->state = TARGET_HALTED; + +- if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_RESET)) { ++ if (prev_target_state != TARGET_HALTED) { + retval = cortex_m_debug_entry(target); + if (retval != ERROR_OK) + return retval; ++ } + ++ if (prev_target_state == TARGET_RUNNING || prev_target_state == TARGET_RESET) { + if (arm_semihosting(target, &retval) != 0) + return retval; + + target_call_event_callbacks(target, TARGET_EVENT_HALTED); + } ++ + if (prev_target_state == TARGET_DEBUG_RUNNING) { + LOG_DEBUG(" "); +- retval = cortex_m_debug_entry(target); +- if (retval != ERROR_OK) +- return retval; + + target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED); + } +diff --git a/tcl/target/stm32mp15x.cfg b/tcl/target/stm32mp15x.cfg +index 992975f87..f95070c3c 100644 +--- a/tcl/target/stm32mp15x.cfg ++++ b/tcl/target/stm32mp15x.cfg +@@ -54,8 +54,10 @@ proc cti_prepare_restart_all {} { + global _CHIPNAME + + cti_prepare_restart cti0 +- cti_prepare_restart cti1 +- if { [$_CHIPNAME.cpu2 curstate] ne "examine deferred" } { ++ if { [$_CHIPNAME.cpu1 was_examined] } { ++ cti_prepare_restart cti1 ++ } ++ if { [$_CHIPNAME.cpu2 was_examined] } { + cti_prepare_restart cti2 + } + } +@@ -71,22 +73,22 @@ proc cti_prepare_restart {cti} { + proc cti_start {} { + global _CHIPNAME + +- # Configure both Cortex-A CTIs to halt each other ++ # Configure CTIs to halt the other cores + # TRIGIN0 (DBGTRIGGER) and TRIGOUT0 (EDBGRQ) at CTM_CHANNEL_0 + $_CHIPNAME.cti0 write INEN0 0x1 +- $_CHIPNAME.cti1 write INEN0 0x1 + $_CHIPNAME.cti0 write OUTEN0 0x1 +- $_CHIPNAME.cti1 write OUTEN0 0x1 +- +- $_CHIPNAME.cpu0 configure -event halted { cti_prepare_restart_all } +- $_CHIPNAME.cpu1 configure -event halted { cti_prepare_restart_all } +- +- # enable CTIs ++ $_CHIPNAME.cpu0 configure -event halted { cti_prepare_restart_all } + $_CHIPNAME.cti0 enable on +- $_CHIPNAME.cti1 enable on ++ ++ if { [$_CHIPNAME.cpu1 was_examined] } { ++ $_CHIPNAME.cti1 write INEN0 0x1 ++ $_CHIPNAME.cti1 write OUTEN0 0x1 ++ $_CHIPNAME.cpu1 configure -event halted { cti_prepare_restart_all } ++ $_CHIPNAME.cti1 enable on ++ } + + # Cortex-M4 CTI configuration (enable CM4.CTI and join same CTM channels) +- if { [$_CHIPNAME.cpu2 curstate] ne "examine deferred" } { ++ if { [$_CHIPNAME.cpu2 was_examined] } { + $_CHIPNAME.cti2 write INEN0 0x1 + $_CHIPNAME.cti2 write OUTEN0 0x1 + $_CHIPNAME.cpu2 configure -event halted { cti_prepare_restart_all } +@@ -98,8 +100,9 @@ proc cti_stop {} { + global _CHIPNAME + + $_CHIPNAME.cti0 enable off +- $_CHIPNAME.cti1 enable off +- ++ if { [$_CHIPNAME.cpu1 was_examined] } { ++ $_CHIPNAME.cti1 enable off ++ } + if { [$_CHIPNAME.cpu2 curstate] ne "examine deferred" } { + $_CHIPNAME.cti2 enable off + } +@@ -111,7 +114,7 @@ cti create $_CHIPNAME.cti1 -dap $_CHIPNAME.dap -ap-num 1 -ctibase 0xE00D9000 + cti create $_CHIPNAME.cti2 -dap $_CHIPNAME.dap -ap-num 2 -ctibase 0xE0043000 + + target create $_CHIPNAME.cpu0 cortex_a -dap $_CHIPNAME.dap -coreid 0 -dbgbase 0xE00D0000 +-target create $_CHIPNAME.cpu1 cortex_a -dap $_CHIPNAME.dap -coreid 1 -dbgbase 0xE00D2000 ++target create $_CHIPNAME.cpu1 cortex_a -dap $_CHIPNAME.dap -coreid 1 -dbgbase 0xE00D2000 -defer-examine + target create $_CHIPNAME.axi mem_ap -dap $_CHIPNAME.dap -ap-num 0 + target create $_CHIPNAME.ap1 mem_ap -dap $_CHIPNAME.dap -ap-num 1 + +@@ -228,6 +231,29 @@ adapter_khz $_CLOCK_FREQ + adapter_nsrst_assert_width 200 + adapter_nsrst_delay 200 + ++$_CHIPNAME.ap1 configure -event examine-end { ++ global _CHIPNAME ++ ++ # only on dual-cores chips, examine the second core ++ $_CHIPNAME.ap1 mem2array cpu1_prsr 32 0xE00D2314 1 ++ if {$cpu1_prsr(0) & 1} { ++ $_CHIPNAME.cpu1 invoke-event examine-start ++ set err [catch "$_CHIPNAME.cpu1 arp_examine"] ++ if { $err } { ++ $_CHIPNAME.cpu1 invoke-event examine-fail ++ } else { ++ $_CHIPNAME.cpu1 invoke-event examine-end ++ } ++ } ++} ++ ++$_CHIPNAME.cpu1 configure -event examine-end { ++ global _CHIPNAME ++ ++ if {[$_CHIPNAME.cpu1 was_examined] && [$_CHIPNAME.cpu0 curstate] eq "halted"} { ++ halt ++ } ++} + + set clients_num 0 + proc clients_inc {} { +-- +2.21.0 + diff --git a/recipes-devtools/openocd/openocd-stm32mp_0.10.0.bb b/recipes-devtools/openocd/openocd-stm32mp_0.10.0.bb index 73977d0..e90cab8 100644 --- a/recipes-devtools/openocd/openocd-stm32mp_0.10.0.bb +++ b/recipes-devtools/openocd/openocd-stm32mp_0.10.0.bb @@ -18,3 +18,4 @@ SRC_URI += "file://0002-Add-support-for-silicon-revB.patch" SRC_URI += "file://0003-Align-to-community-code-for-cache-coherency-and-rese.patch" SRC_URI += "file://0004-Fix-init-command.patch" SRC_URI += "file://0005-Add-CTI-plus-fixes.patch" +SRC_URI += "file://0006-Support-single-core-align-access-with-mmu-off-plus-f.patch"