You can subscribe to this list here.
| 2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(75) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2009 |
Jan
(70) |
Feb
(20) |
Mar
(52) |
Apr
(149) |
May
(387) |
Jun
(466) |
Jul
(133) |
Aug
(87) |
Sep
(122) |
Oct
(140) |
Nov
(185) |
Dec
(105) |
| 2010 |
Jan
(85) |
Feb
(45) |
Mar
(75) |
Apr
(17) |
May
(41) |
Jun
(52) |
Jul
(33) |
Aug
(29) |
Sep
(36) |
Oct
(15) |
Nov
(26) |
Dec
(34) |
| 2011 |
Jan
(26) |
Feb
(25) |
Mar
(26) |
Apr
(29) |
May
(20) |
Jun
(27) |
Jul
(15) |
Aug
(32) |
Sep
(13) |
Oct
(64) |
Nov
(60) |
Dec
(10) |
| 2012 |
Jan
(64) |
Feb
(63) |
Mar
(39) |
Apr
(43) |
May
(54) |
Jun
(11) |
Jul
(30) |
Aug
(45) |
Sep
(11) |
Oct
(70) |
Nov
(24) |
Dec
(23) |
| 2013 |
Jan
(17) |
Feb
(8) |
Mar
(35) |
Apr
(40) |
May
(20) |
Jun
(24) |
Jul
(36) |
Aug
(25) |
Sep
(42) |
Oct
(40) |
Nov
(9) |
Dec
(21) |
| 2014 |
Jan
(29) |
Feb
(24) |
Mar
(60) |
Apr
(22) |
May
(22) |
Jun
(46) |
Jul
(11) |
Aug
(23) |
Sep
(26) |
Oct
(10) |
Nov
(14) |
Dec
(2) |
| 2015 |
Jan
(28) |
Feb
(47) |
Mar
(33) |
Apr
(58) |
May
(5) |
Jun
(1) |
Jul
|
Aug
(8) |
Sep
(12) |
Oct
(25) |
Nov
(58) |
Dec
(21) |
| 2016 |
Jan
(12) |
Feb
(40) |
Mar
(2) |
Apr
(1) |
May
(67) |
Jun
(2) |
Jul
(5) |
Aug
(36) |
Sep
|
Oct
(24) |
Nov
(17) |
Dec
(50) |
| 2017 |
Jan
(14) |
Feb
(16) |
Mar
(2) |
Apr
(35) |
May
(14) |
Jun
(16) |
Jul
(3) |
Aug
(3) |
Sep
|
Oct
(19) |
Nov
|
Dec
(16) |
| 2018 |
Jan
(55) |
Feb
(11) |
Mar
(34) |
Apr
(14) |
May
(4) |
Jun
(20) |
Jul
(39) |
Aug
(16) |
Sep
(17) |
Oct
(16) |
Nov
(20) |
Dec
(30) |
| 2019 |
Jan
(29) |
Feb
(24) |
Mar
(37) |
Apr
(26) |
May
(19) |
Jun
(21) |
Jul
(2) |
Aug
(3) |
Sep
(9) |
Oct
(12) |
Nov
(12) |
Dec
(12) |
| 2020 |
Jan
(47) |
Feb
(36) |
Mar
(54) |
Apr
(44) |
May
(37) |
Jun
(19) |
Jul
(32) |
Aug
(13) |
Sep
(16) |
Oct
(24) |
Nov
(32) |
Dec
(11) |
| 2021 |
Jan
(14) |
Feb
(5) |
Mar
(40) |
Apr
(32) |
May
(42) |
Jun
(31) |
Jul
(29) |
Aug
(47) |
Sep
(38) |
Oct
(17) |
Nov
(74) |
Dec
(33) |
| 2022 |
Jan
(11) |
Feb
(15) |
Mar
(40) |
Apr
(21) |
May
(39) |
Jun
(44) |
Jul
(19) |
Aug
(46) |
Sep
(79) |
Oct
(35) |
Nov
(21) |
Dec
(15) |
| 2023 |
Jan
(56) |
Feb
(13) |
Mar
(43) |
Apr
(28) |
May
(60) |
Jun
(15) |
Jul
(29) |
Aug
(28) |
Sep
(32) |
Oct
(21) |
Nov
(42) |
Dec
(39) |
| 2024 |
Jan
(35) |
Feb
(17) |
Mar
(28) |
Apr
(7) |
May
(14) |
Jun
(35) |
Jul
(30) |
Aug
(35) |
Sep
(30) |
Oct
(28) |
Nov
(38) |
Dec
(18) |
| 2025 |
Jan
(21) |
Feb
(28) |
Mar
(36) |
Apr
(35) |
May
(34) |
Jun
(58) |
Jul
(9) |
Aug
(54) |
Sep
(47) |
Oct
(15) |
Nov
(47) |
Dec
|
|
From: openocd-gerrit <ope...@us...> - 2024-05-11 11:55:17
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 126d8a0972ab6031588eb2f0e1fc3957bd3ccc6b (commit)
via caabdd4a6627a86be43cd91e09f127173eb9e692 (commit)
from dbef02789fb1f30ae77020754b1468549fd16510 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 126d8a0972ab6031588eb2f0e1fc3957bd3ccc6b
Author: Antonio Borneo <bor...@gm...>
Date: Sat May 4 19:13:51 2024 +0200
cortex_a: drop cortex_a_dap_write_memap_register_u32()
Historically, the function cortex_a_dap_write_memap_register_u32()
was used to discriminate the register write in APB-AP CPU debug
against the complex memory access in AHB-AP memory bus.
It has no sense to keep the function and its comment.
Plus, by forcing atomic write it impacts the debug performance.
Drop it!
A further rework to enqueue sequence of atomic writes is needed.
Change-Id: I2f5e9015f0e27fa5a6d8337a1ae25e753e2e1d26
Signed-off-by: Antonio Borneo <bor...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8231
Reviewed-by: Oleksij Rempel <li...@re...>
Tested-by: jenkins
diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c
index a23540463..2de77c960 100644
--- a/src/target/cortex_a.c
+++ b/src/target/cortex_a.c
@@ -314,19 +314,6 @@ static int cortex_a_exec_opcode(struct target *target,
return retval;
}
-/* Write to memory mapped registers directly with no cache or mmu handling */
-static int cortex_a_dap_write_memap_register_u32(struct target *target,
- uint32_t address,
- uint32_t value)
-{
- int retval;
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap, address, value);
-
- return retval;
-}
-
/*
* Cortex-A implementation of Debug Programmer's Model
*
@@ -611,11 +598,11 @@ static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned index_t,
LOG_DEBUG("A: bpwp enable, vr %08x cr %08x",
(unsigned) vr, (unsigned) cr);
- retval = cortex_a_dap_write_memap_register_u32(dpm->arm->target,
+ retval = mem_ap_write_atomic_u32(a->armv7a_common.debug_ap,
vr, addr);
if (retval != ERROR_OK)
return retval;
- retval = cortex_a_dap_write_memap_register_u32(dpm->arm->target,
+ retval = mem_ap_write_atomic_u32(a->armv7a_common.debug_ap,
cr, control);
return retval;
}
@@ -641,7 +628,7 @@ static int cortex_a_bpwp_disable(struct arm_dpm *dpm, unsigned index_t)
LOG_DEBUG("A: bpwp disable, cr %08x", (unsigned) cr);
/* clear control register */
- return cortex_a_dap_write_memap_register_u32(dpm->arm->target, cr, 0);
+ return mem_ap_write_atomic_u32(a->armv7a_common.debug_ap, cr, 0);
}
static int cortex_a_dpm_setup(struct cortex_a_common *a, uint32_t didr)
@@ -1323,13 +1310,13 @@ static int cortex_a_set_breakpoint(struct target *target,
brp_list[brp_i].used = true;
brp_list[brp_i].value = (breakpoint->address & 0xFFFFFFFC);
brp_list[brp_i].control = control;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn,
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn,
brp_list[brp_i].value);
if (retval != ERROR_OK)
return retval;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn,
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn,
brp_list[brp_i].control);
if (retval != ERROR_OK)
return retval;
@@ -1415,13 +1402,13 @@ static int cortex_a_set_context_breakpoint(struct target *target,
brp_list[brp_i].used = true;
brp_list[brp_i].value = (breakpoint->asid);
brp_list[brp_i].control = control;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn,
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn,
brp_list[brp_i].value);
if (retval != ERROR_OK)
return retval;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn,
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn,
brp_list[brp_i].control);
if (retval != ERROR_OK)
return retval;
@@ -1481,13 +1468,13 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoi
brp_list[brp_1].used = true;
brp_list[brp_1].value = (breakpoint->asid);
brp_list[brp_1].control = control_ctx;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BVR_BASE + 4 * brp_list[brp_1].brpn,
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_1].brpn,
brp_list[brp_1].value);
if (retval != ERROR_OK)
return retval;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BCR_BASE + 4 * brp_list[brp_1].brpn,
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_1].brpn,
brp_list[brp_1].control);
if (retval != ERROR_OK)
return retval;
@@ -1499,13 +1486,13 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoi
brp_list[brp_2].used = true;
brp_list[brp_2].value = (breakpoint->address & 0xFFFFFFFC);
brp_list[brp_2].control = control_iva;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BVR_BASE + 4 * brp_list[brp_2].brpn,
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_2].brpn,
brp_list[brp_2].value);
if (retval != ERROR_OK)
return retval;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BCR_BASE + 4 * brp_list[brp_2].brpn,
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_2].brpn,
brp_list[brp_2].control);
if (retval != ERROR_OK)
return retval;
@@ -1538,13 +1525,13 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b
brp_list[brp_i].used = false;
brp_list[brp_i].value = 0;
brp_list[brp_i].control = 0;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn,
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn,
brp_list[brp_i].control);
if (retval != ERROR_OK)
return retval;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn,
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn,
brp_list[brp_i].value);
if (retval != ERROR_OK)
return retval;
@@ -1557,13 +1544,13 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b
brp_list[brp_j].used = false;
brp_list[brp_j].value = 0;
brp_list[brp_j].control = 0;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BCR_BASE + 4 * brp_list[brp_j].brpn,
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_j].brpn,
brp_list[brp_j].control);
if (retval != ERROR_OK)
return retval;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BVR_BASE + 4 * brp_list[brp_j].brpn,
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_j].brpn,
brp_list[brp_j].value);
if (retval != ERROR_OK)
return retval;
@@ -1582,13 +1569,13 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b
brp_list[brp_i].used = false;
brp_list[brp_i].value = 0;
brp_list[brp_i].control = 0;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn,
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn,
brp_list[brp_i].control);
if (retval != ERROR_OK)
return retval;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn,
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn,
brp_list[brp_i].value);
if (retval != ERROR_OK)
return retval;
@@ -1783,14 +1770,14 @@ static int cortex_a_set_watchpoint(struct target *target, struct watchpoint *wat
wrp_list[wrp_i].value = address;
wrp_list[wrp_i].control = control;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].wrpn,
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].wrpn,
wrp_list[wrp_i].value);
if (retval != ERROR_OK)
return retval;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].wrpn,
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].wrpn,
wrp_list[wrp_i].control);
if (retval != ERROR_OK)
return retval;
@@ -1832,13 +1819,13 @@ static int cortex_a_unset_watchpoint(struct target *target, struct watchpoint *w
wrp_list[wrp_i].used = false;
wrp_list[wrp_i].value = 0;
wrp_list[wrp_i].control = 0;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].wrpn,
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].wrpn,
wrp_list[wrp_i].control);
if (retval != ERROR_OK)
return retval;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].wrpn,
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].wrpn,
wrp_list[wrp_i].value);
if (retval != ERROR_OK)
return retval;
commit caabdd4a6627a86be43cd91e09f127173eb9e692
Author: Antonio Borneo <bor...@gm...>
Date: Sat May 4 20:09:51 2024 +0200
cortex_a: drop the command 'cache auto'
The command 'cache auto' was introduced with commit cd440bd32a12
("add armv7a_cache handlers") in 2015 to allow disabling the cache
handling done automatically by OpenOCD.
This was probably a way to test the cache handling when there were
still the two independent accesses for APB-AP CPU debug and for
AHB-AP memory bus.
The handling of cache for cortex_a is robust and there is no more
reason to disable it.
The command 'cache auto' is not used in any upstream script.
On target aarch64 this command has never been introduced as the
cache is always handled automatically by OpenOCD.
Drop the command 'cache auto' and add it in the deprecated list.
Drop the flag 'auto_cache_enabled' by considering it as true.
Rename the function 'armv7a_cache_auto_flush_all_data()' as
'armv7a_cache_flush_all_data()' and, while there, fix the error
propagation in SMP case.
Change-Id: I0399f1081b08c4929e0795b76f4a686630f41d56
Signed-off-by: Antonio Borneo <bor...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8230
Tested-by: jenkins
Reviewed-by: Oleksij Rempel <li...@re...>
diff --git a/src/target/armv7a.c b/src/target/armv7a.c
index 82f4be5a0..dc3752e0b 100644
--- a/src/target/armv7a.c
+++ b/src/target/armv7a.c
@@ -473,7 +473,7 @@ int armv7a_identify_cache(struct target *target)
/* if no l2 cache initialize l1 data cache flush function function */
if (!armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache) {
armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache =
- armv7a_cache_auto_flush_all_data;
+ armv7a_cache_flush_all_data;
}
armv7a->armv7a_mmu.armv7a_cache.info = 1;
@@ -525,7 +525,6 @@ int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a)
armv7a->armv7a_mmu.armv7a_cache.info = -1;
armv7a->armv7a_mmu.armv7a_cache.outer_cache = NULL;
armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache = NULL;
- armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled = 1;
return ERROR_OK;
}
diff --git a/src/target/armv7a.h b/src/target/armv7a.h
index 6b9c2a68f..8943f1c69 100644
--- a/src/target/armv7a.h
+++ b/src/target/armv7a.h
@@ -65,8 +65,6 @@ struct armv7a_cache_common {
struct armv7a_arch_cache arch[6]; /* cache info, L1 - L7 */
int i_cache_enabled;
int d_u_cache_enabled;
- int auto_cache_enabled; /* openocd automatic
- * cache handling */
/* outer unified cache if some */
void *outer_cache;
int (*flush_all_data_cache)(struct target *target);
diff --git a/src/target/armv7a_cache.c b/src/target/armv7a_cache.c
index 681c06aff..f2f1097c5 100644
--- a/src/target/armv7a_cache.c
+++ b/src/target/armv7a_cache.c
@@ -118,20 +118,19 @@ done:
return retval;
}
-int armv7a_cache_auto_flush_all_data(struct target *target)
+int armv7a_cache_flush_all_data(struct target *target)
{
int retval = ERROR_FAIL;
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled)
- return ERROR_OK;
if (target->smp) {
struct target_list *head;
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
- if (curr->state == TARGET_HALTED)
- retval = armv7a_l1_d_cache_clean_inval_all(curr);
+ if (curr->state == TARGET_HALTED) {
+ int retval1 = armv7a_l1_d_cache_clean_inval_all(curr);
+ if (retval1 != ERROR_OK)
+ retval = retval1;
+ }
}
} else
retval = armv7a_l1_d_cache_clean_inval_all(target);
@@ -472,28 +471,6 @@ COMMAND_HANDLER(arm7a_l1_i_cache_inval_virt_cmd)
return armv7a_l1_i_cache_inval_virt(target, virt, size);
}
-COMMAND_HANDLER(arm7a_cache_disable_auto_cmd)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- if (CMD_ARGC == 0) {
- command_print(CMD, "auto cache is %s",
- armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled ? "enabled" : "disabled");
- return ERROR_OK;
- }
-
- if (CMD_ARGC == 1) {
- uint32_t set;
-
- COMMAND_PARSE_ENABLE(CMD_ARGV[0], set);
- armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled = !!set;
- return ERROR_OK;
- }
-
- return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
static const struct command_registration arm7a_l1_d_cache_commands[] = {
{
.name = "flush_all",
@@ -563,13 +540,6 @@ static const struct command_registration arm7a_l1_di_cache_group_handlers[] = {
};
static const struct command_registration arm7a_cache_group_handlers[] = {
- {
- .name = "auto",
- .handler = arm7a_cache_disable_auto_cmd,
- .mode = COMMAND_ANY,
- .help = "disable or enable automatic cache handling.",
- .usage = "(1|0)",
- },
{
.name = "l1",
.mode = COMMAND_ANY,
diff --git a/src/target/armv7a_cache.h b/src/target/armv7a_cache.h
index 3e3eae55c..c4637c5d3 100644
--- a/src/target/armv7a_cache.h
+++ b/src/target/armv7a_cache.h
@@ -20,7 +20,7 @@ int armv7a_l1_d_cache_flush_virt(struct target *target, uint32_t virt,
int armv7a_l1_i_cache_inval_all(struct target *target);
int armv7a_l1_i_cache_inval_virt(struct target *target, uint32_t virt,
uint32_t size);
-int armv7a_cache_auto_flush_all_data(struct target *target);
+int armv7a_cache_flush_all_data(struct target *target);
int armv7a_cache_flush_virt(struct target *target, uint32_t virt,
uint32_t size);
extern const struct command_registration arm7a_cache_command_handlers[];
diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c
index f90c02a95..a23540463 100644
--- a/src/target/cortex_a.c
+++ b/src/target/cortex_a.c
@@ -1362,10 +1362,8 @@ static int cortex_a_set_breakpoint(struct target *target,
return retval;
/* make sure data cache is cleaned & invalidated down to PoC */
- if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled) {
- armv7a_cache_flush_virt(target, breakpoint->address,
+ armv7a_cache_flush_virt(target, breakpoint->address,
breakpoint->length);
- }
retval = target_write_memory(target,
breakpoint->address & 0xFFFFFFFE,
@@ -1600,10 +1598,8 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b
} else {
/* make sure data cache is cleaned & invalidated down to PoC */
- if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled) {
- armv7a_cache_flush_virt(target, breakpoint->address,
+ armv7a_cache_flush_virt(target, breakpoint->address,
breakpoint->length);
- }
/* restore original instruction (kept in target endianness) */
if (breakpoint->length == 4) {
diff --git a/src/target/startup.tcl b/src/target/startup.tcl
index 75e0edc77..e9646097f 100644
--- a/src/target/startup.tcl
+++ b/src/target/startup.tcl
@@ -294,3 +294,25 @@ proc "mips_m4k smp_off" {args} {
echo "DEPRECATED! use 'mips_m4k smp off' not 'mips_m4k smp_off'"
eval mips_m4k smp off $args
}
+
+lappend _telnet_autocomplete_skip _post_init_target_cortex_a_cache_auto
+proc _post_init_target_cortex_a_cache_auto {} {
+ set cortex_a_found 0
+
+ foreach t [target names] {
+ if { [$t cget -type] != "cortex_a" } { continue }
+ set cortex_a_found 1
+ lappend ::_telnet_autocomplete_skip "$t cache auto"
+ proc "$t cache auto" { enable } {
+ echo "DEPRECATED! Don't use anymore '[dict get [info frame 0] proc] $enable' as it's always enabled"
+ }
+ }
+
+ if { $cortex_a_found } {
+ lappend ::_telnet_autocomplete_skip "cache auto"
+ proc "cache auto" { enable } {
+ echo "DEPRECATED! Don't use anymore 'cache auto $enable' as it's always enabled"
+ }
+ }
+}
+lappend post_init_commands _post_init_target_cortex_a_cache_auto
-----------------------------------------------------------------------
Summary of changes:
src/target/armv7a.c | 3 +-
src/target/armv7a.h | 2 -
src/target/armv7a_cache.c | 42 +++-----------------
src/target/armv7a_cache.h | 2 +-
src/target/cortex_a.c | 99 ++++++++++++++++++++---------------------------
src/target/startup.tcl | 22 +++++++++++
6 files changed, 71 insertions(+), 99 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-05-11 11:54:57
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via dbef02789fb1f30ae77020754b1468549fd16510 (commit)
from bc9ca5f4a82ccbbdbe07108a83f7979b53e89889 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit dbef02789fb1f30ae77020754b1468549fd16510
Author: Antonio Borneo <bor...@gm...>
Date: Thu May 2 15:24:57 2024 +0200
cortex_a: drop useless cache invalidate on mem write
The initial OpenOCD code for Cortex-A (ARMv7a) [1] was merged in
2009 but, due to lack of public documentation for ARMv7a, it was
almost a simple copy/paste from the existing code for Cortex-M
(ARMv7m).
On Cortex-M the same AP provides access to both CPU debug and CPU
memory. This feature is not present on ARMv7a.
To still keep some communality with ARMv7m code, the change [2]
splits the CPU debug access from the CPU memory access by using
two independent AP; this is copied from the system architecture of
TI OMAP3530 which provides to DAP a direct AHB-AP memory bus on
AP#0, separated from AP#1 for the APB-AP CPU debug.
But the direct memory access through the system bus breaks the
coherency between memory and CPU caches, so change [3] added some
cache invalidation to avoid issues.
The code to allow ARMv7a CPU to really read/write in CPU memory
was added by change [4] in 2011. Such still not optimized
implementation was very slow, so it did not replace the access
through the system bus. A selection through DAP's 'apsel" command
was used to select between the two modes.
Only in 2015, with change [5], the speed of CPU read/write was
improved using the DCC_FAST_MODE. But the direct access to the
memory through the system bus remained.
Finally, with change [6] in 2018 the system bus access was dropped
for good, as the new virtual target "mem_ap" could implement such
access in a more clean way.
Only memory access through CPU remained for ARMv7a.
Nevertheless, a useless cache invalidation remained in the code,
decreasing the speed of the write access.
Drop the useless cache invalidate on CPU memory write and the
associated comment, not anymore valid.
Drop the now unused function armv7a_cache_auto_flush_on_write().
This provides a speedup of between 4 and 8, depending on adapter
and JTAG/SWD speed.
Link: [1] 7a93100c2dfe ("Add minimalist Cortex A8 file")
Link: [2] 1d0b276c9f75 ("The rest of the Cortex-A8 support from Magnus: ...")
Link: [3] d4e4d65d284f ("Cache invalidation when writing to memory")
Link: [4] 05ab8bdb813a ("cortex_a9: implement read/write memory through APB-AP")
Link: [5] 0228f8e8274d ("Cortex A: fix extra memory read and non-word sizes")
Link: [6] fac9be64d944 ("target/cortex_a: remove buggy memory AP accesses")
Change-Id: Ifa3c7ddf2698b2c87037fb48f783844034a7140e
Signed-off-by: Antonio Borneo <bor...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8229
Tested-by: jenkins
Reviewed-by: Oleksij Rempel <li...@re...>
diff --git a/src/target/armv7a_cache.c b/src/target/armv7a_cache.c
index e1f0dfafb..681c06aff 100644
--- a/src/target/armv7a_cache.c
+++ b/src/target/armv7a_cache.c
@@ -391,27 +391,6 @@ int armv7a_cache_flush_virt(struct target *target, uint32_t virt,
return ERROR_OK;
}
-/*
- * We assume that target core was chosen correctly. It means if same data
- * was handled by two cores, other core will loose the changes. Since it
- * is impossible to know (FIXME) which core has correct data, keep in mind
- * that some kind of data lost or corruption is possible.
- * Possible scenario:
- * - core1 loaded and changed data on 0x12345678
- * - we halted target and modified same data on core0
- * - data on core1 will be lost.
- */
-int armv7a_cache_auto_flush_on_write(struct target *target, uint32_t virt,
- uint32_t size)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled)
- return ERROR_OK;
-
- return armv7a_cache_flush_virt(target, virt, size);
-}
-
COMMAND_HANDLER(arm7a_l1_cache_info_cmd)
{
struct target *target = get_current_target(CMD_CTX);
diff --git a/src/target/armv7a_cache.h b/src/target/armv7a_cache.h
index 17ec5e6de..3e3eae55c 100644
--- a/src/target/armv7a_cache.h
+++ b/src/target/armv7a_cache.h
@@ -20,8 +20,6 @@ int armv7a_l1_d_cache_flush_virt(struct target *target, uint32_t virt,
int armv7a_l1_i_cache_inval_all(struct target *target);
int armv7a_l1_i_cache_inval_virt(struct target *target, uint32_t virt,
uint32_t size);
-int armv7a_cache_auto_flush_on_write(struct target *target, uint32_t virt,
- uint32_t size);
int armv7a_cache_auto_flush_all_data(struct target *target);
int armv7a_cache_flush_virt(struct target *target, uint32_t virt,
uint32_t size);
diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c
index 78fd4482c..f90c02a95 100644
--- a/src/target/cortex_a.c
+++ b/src/target/cortex_a.c
@@ -2791,9 +2791,6 @@ static int cortex_a_write_memory(struct target *target, target_addr_t address,
LOG_DEBUG("Writing memory at address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32,
address, size, count);
- /* memory writes bypass the caches, must flush before writing */
- armv7a_cache_auto_flush_on_write(target, address, size * count);
-
cortex_a_prep_memaccess(target, 0);
retval = cortex_a_write_cpu_memory(target, address, size, count, buffer);
cortex_a_post_memaccess(target, 0);
-----------------------------------------------------------------------
Summary of changes:
src/target/armv7a_cache.c | 21 ---------------------
src/target/armv7a_cache.h | 2 --
src/target/cortex_a.c | 3 ---
3 files changed, 26 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-05-04 08:37:18
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via bc9ca5f4a82ccbbdbe07108a83f7979b53e89889 (commit)
from a84d1b5f5e2754680c12c1595db9d296eec7d45c (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit bc9ca5f4a82ccbbdbe07108a83f7979b53e89889
Author: Daniel Anselmi <dan...@gm...>
Date: Sun Mar 17 01:15:16 2024 +0100
ipdbg: fix double free of virtual-ir data
Fix possible double free and possible
memory leak while creating an ipdbg hub.
Change-Id: I6254663c27c4f38d46008c4dbff11aa27b84f399
Signed-off-by: Daniel Anselmi <dan...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8085
Tested-by: jenkins
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/src/server/ipdbg.c b/src/server/ipdbg.c
index e7eb96e13..859fdb035 100644
--- a/src/server/ipdbg.c
+++ b/src/server/ipdbg.c
@@ -285,6 +285,7 @@ static struct ipdbg_hub *ipdbg_allocate_hub(uint8_t data_register_length, struct
{
struct ipdbg_hub *new_hub = calloc(1, sizeof(struct ipdbg_hub));
if (!new_hub) {
+ free(virtual_ir);
LOG_ERROR("Out of memory");
return NULL;
}
@@ -292,6 +293,7 @@ static struct ipdbg_hub *ipdbg_allocate_hub(uint8_t data_register_length, struct
new_hub->name = strdup(name);
if (!new_hub->name) {
free(new_hub);
+ free(virtual_ir);
LOG_ERROR("Out of memory");
return NULL;
}
@@ -304,8 +306,10 @@ static struct ipdbg_hub *ipdbg_allocate_hub(uint8_t data_register_length, struct
new_hub->scratch_memory.fields = calloc(IPDBG_SCRATCH_MEMORY_SIZE, sizeof(struct scan_field));
new_hub->connections = calloc(max_tools, sizeof(struct connection *));
- if (virtual_ir)
+ if (virtual_ir) {
+ new_hub->virtual_ir = virtual_ir;
new_hub->scratch_memory.vir_out_val = calloc(1, DIV_ROUND_UP(virtual_ir->length, 8));
+ }
if (!new_hub->scratch_memory.dr_out_vals || !new_hub->scratch_memory.dr_in_vals ||
!new_hub->scratch_memory.fields || (virtual_ir && !new_hub->scratch_memory.vir_out_val) ||
@@ -997,7 +1001,6 @@ static int ipdbg_create_hub(struct jtag_tap *tap, uint32_t user_instruction, uin
new_hub->xoff_mask = BIT(data_register_length - 2);
new_hub->tool_mask = (new_hub->xoff_mask - 1) >> 8;
new_hub->last_dn_tool = new_hub->tool_mask;
- new_hub->virtual_ir = virtual_ir;
new_hub->max_tools = ipdbg_max_tools_from_data_register_length(data_register_length);
new_hub->using_queue_size = IPDBG_SCRATCH_MEMORY_SIZE;
@@ -1123,11 +1126,7 @@ COMMAND_HANDLER(handle_ipdbg_create_hub_command)
return ERROR_FAIL;
}
- int retval = ipdbg_create_hub(tap, user_instruction, data_register_length, virtual_ir, hub_name, cmd);
- if (retval != ERROR_OK)
- free(virtual_ir);
-
- return retval;
+ return ipdbg_create_hub(tap, user_instruction, data_register_length, virtual_ir, hub_name, cmd);
}
static const struct command_registration ipdbg_config_command_handlers[] = {
-----------------------------------------------------------------------
Summary of changes:
src/server/ipdbg.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-05-04 08:36:55
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via a84d1b5f5e2754680c12c1595db9d296eec7d45c (commit)
from 3eba7b53bf067508197e2455b81fc1375b1d945e (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit a84d1b5f5e2754680c12c1595db9d296eec7d45c
Author: Sean Anderson <sea...@se...>
Date: Thu Feb 22 12:18:36 2024 -0500
tcl/target: Add helpers for booting Xilinx ZynqMP from JTAG
Add some helpers for booting ZynqMPs over JTAG. Normally, the CSU ROM
will load boot.bin from the boot medium. However, when booting from JTAG
we have to do this ourselves. There are generally two parts to this.
First, we need to load the PMU firmware. Xilinx's tools do this by
attaching to the PMU (a Microblaze CPU) over JTAG. However, the TAP is
undocumented and we don't have any microblaze support in-tree. So
instead we do it the same way FSBL does it:
- We ask the PMU to halt
- We load the firmware into the PMU RAM
- We ask the PMU to resume
The second thing we need to do is start one of the APU cores. When an
APU is released from reset, it starts executing at the value of its
RVBARADDR. While we could load the APU firmware over the AXI target,
it is faster to load it over the APU target. To do this, we put the APU
into an infinite loop before halting it. As an aside, I chose to use the
"APU" terminology as opposed to "core" to make it clear that these
commands operate on the A53 cores and not the R5F cores.
Typical usage of these commands could look something like
targets uscale.axi
boot_pmu /path/to/pmu-firmware.bin
boot_apu /path/to/u-boot-spl.bin
But of course there is always the option to call lower-level commands
individually if your boot process is more unusual.
Signed-off-by: Sean Anderson <sea...@se...>
Change-Id: I816940c2022ccca0fabb489aa75d682edd0f6138
Reviewed-on: https://review.openocd.org/c/openocd/+/8133
Reviewed-by: Antonio Borneo <bor...@gm...>
Tested-by: jenkins
diff --git a/tcl/target/xilinx_zynqmp.cfg b/tcl/target/xilinx_zynqmp.cfg
index 9734a1837..e8224be04 100644
--- a/tcl/target/xilinx_zynqmp.cfg
+++ b/tcl/target/xilinx_zynqmp.cfg
@@ -104,3 +104,137 @@ proc core_up { args } {
$_TARGETNAME.$core arp_examine
}
}
+
+proc BIT {n} {
+ return [expr {1 << $n}]
+}
+
+set IPI_BASE 0xff300000
+set IPI_PMU_0_TRIG [expr {$IPI_BASE + 0x30000}]
+set IPI_PMU_0_IER [expr {$IPI_BASE + 0x30018}]
+set IPI_PMU_0 [BIT 16]
+
+set CRF_APB_BASE 0xfd1a0000
+set CRF_APB_RST_FPD_APU [expr {$CRF_APB_BASE + 0x104}]
+set CRF_APB_RST_FPD_APU_ACPU0_PWRON_RESET [BIT 10]
+set CRF_APB_RST_FPD_APU_L2_RESET [BIT 8]
+set CRF_APB_RST_FPD_APU_ACPU0_RESET [BIT 0]
+
+set APU_BASE 0xfd5c0000
+set APU_RVBARADDR_BASE [expr {$APU_BASE + 0x40}]
+
+set PMU_BASE 0xffd80000
+set PMU_GLOBAL $PMU_BASE
+set PMU_GLOBAL_MB_SLEEP [BIT 16]
+set PMU_GLOBAL_FW_IS_PRESENT [BIT 4]
+set PMU_GLOBAL_DONT_SLEEP [BIT 0]
+
+set PMU_RAM_BASE 0xffdc0000
+
+set OCM_RAM_BASE 0xfffc0000
+
+rename BIT {}
+
+add_help_text halt_pmu "Halt the PMU in preparation for loading new firmware.\
+ This should be matched with a call to resume_pmu."
+proc halt_pmu {} {
+ set axi $::_CHIPNAME.axi
+ set val [$axi read_memory $::IPI_PMU_0_IER 32 1]
+ $axi write_memory $::IPI_PMU_0_IER 32 [expr {$val | $::IPI_PMU_0}]
+
+ set val [$axi read_memory $::IPI_PMU_0_TRIG 32 1]
+ $axi write_memory $::IPI_PMU_0_TRIG 32 [expr {$val | $::IPI_PMU_0}]
+
+ set start [ms]
+ while {!([$axi read_memory $::PMU_GLOBAL 32 1] & $::PMU_GLOBAL_MB_SLEEP)} {
+ if {[ms] - $start > 1000} {
+ error "Timed out waiting for PMU to halt"
+ }
+ }
+}
+
+add_help_text resume_pmu "Resume the PMU after loading new firmware. This\
+ should be matched with a call to halt_pmu."
+proc resume_pmu {} {
+ set axi $::_CHIPNAME.axi
+ set val [$axi read_memory $::PMU_GLOBAL 32 1]
+ $axi write_memory $::PMU_GLOBAL 32 [expr {$val | $::PMU_GLOBAL_DONT_SLEEP}]
+
+ set start [ms]
+ while {!([$axi read_memory $::PMU_GLOBAL 32 1] & $::PMU_GLOBAL_FW_IS_PRESENT)} {
+ if {[ms] - $start > 5000} {
+ error "Timed out waiting for PMU firmware"
+ }
+ }
+}
+
+add_usage_text release_apu {apu}
+add_help_text release_apu "Release an APU from reset. It will start executing\
+ at RVBARADDR. You probably want resume_apu or start_apu instead."
+proc release_apu {apu} {
+ set axi $::_CHIPNAME.axi
+ set val [$axi read_memory $::CRF_APB_RST_FPD_APU 32 1]
+ set mask [expr {
+ (($::CRF_APB_RST_FPD_APU_ACPU0_PWRON_RESET | \
+ $::CRF_APB_RST_FPD_APU_ACPU0_RESET) << $apu) | \
+ $::CRF_APB_RST_FPD_APU_L2_RESET
+ }]
+ $axi write_memory $::CRF_APB_RST_FPD_APU 32 [expr {$val & ~$mask}]
+
+ core_up $apu
+ $::_TARGETNAME.$apu aarch64 dbginit
+}
+
+proc _rvbaraddr {apu} {
+ return [expr {$::APU_RVBARADDR_BASE + 8 * $apu}]
+}
+
+add_usage_text resume_apu {apu addr}
+add_help_text resume_apu "Resume an APU at a given address."
+proc resume_apu {apu addr} {
+ set addrl [expr {$addr & 0xffffffff}]
+ set addrh [expr {$addr >> 32}]
+ $::_CHIPNAME.axi write_memory [_rvbaraddr $apu] 32 [list $addrl $addrh]
+
+ release_apu $apu
+}
+
+add_usage_text start_apu {apu}
+add_help_text start_apu "Start an APU and put it into an infinite loop at\
+ RVBARADDR. This can be convenient if you just want to halt the APU\
+ (since it won't execute anything unusual)."
+proc start_apu {apu} {
+ set axi $::_CHIPNAME.axi
+ foreach {addrl addrh} [$axi read_memory [_rvbaraddr $apu] 32 2] {
+ set addr [expr {($addrh << 32) | $addrl}]
+ }
+ # write the infinite loop instruction
+ $axi write_memory $addr 32 0x14000000
+
+ release_apu $apu
+}
+
+add_usage_text boot_pmu {image}
+add_help_text boot_pmu "Boot the PMU with a given firmware image, loading it\
+ to the beginning of PMU RAM. The PMU ROM will jump to this location\
+ after we resume it."
+proc boot_pmu {image} {
+ halt_pmu
+ echo "Info : Loading PMU firmware $image to $::PMU_RAM_BASE"
+ load_image $image $::PMU_RAM_BASE
+ resume_pmu
+}
+
+add_usage_text boot_apu "image \[apu=0 \[addr=$OCM_RAM_BASE\]\]"
+add_help_text boot_apu "Boot an APU with a given firmware image. The default\
+ address is the beginning of OCM RAM. Upon success, the default target\
+ will be changed to the (running) apu."
+proc boot_apu [list image {apu 0} [list addr $OCM_RAM_BASE]] {
+ start_apu $apu
+ targets $::_TARGETNAME.$apu
+ halt
+
+ echo "Info : Loading APU$apu firmware $image to $addr"
+ load_image $image $addr
+ resume $addr
+}
-----------------------------------------------------------------------
Summary of changes:
tcl/target/xilinx_zynqmp.cfg | 134 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 134 insertions(+)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-05-04 08:36:05
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 3eba7b53bf067508197e2455b81fc1375b1d945e (commit)
from c72afedce794a7251fd9c822e3bfc89f870b9fc1 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 3eba7b53bf067508197e2455b81fc1375b1d945e
Author: Antonio Borneo <bor...@gm...>
Date: Mon Apr 15 17:42:12 2024 +0200
smp: fix SIGSEGV for "smp off" during target examine
The gdb subsystem is initialized after the first target examine,
so the field struct target::gdb_service is NULL during examine.
A command "smp off" in the examine event handler causes a SIGSEGV
during OpenOCD startup.
Check for pointer not NULL before dereferencing it.
Change-Id: Id115e28be23a957fef1b97ab66d7273f0ea0dce4
Signed-off-by: Antonio Borneo <bor...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8216
Tested-by: jenkins
diff --git a/src/target/smp.c b/src/target/smp.c
index 50b19d01a..41ca880d4 100644
--- a/src/target/smp.c
+++ b/src/target/smp.c
@@ -119,7 +119,7 @@ COMMAND_HANDLER(default_handle_smp_command)
head->target->smp = 0;
/* fixes the target display to the debugger */
- if (!list_empty(target->smp_targets))
+ if (!list_empty(target->smp_targets) && target->gdb_service)
target->gdb_service->target = target;
return ERROR_OK;
-----------------------------------------------------------------------
Summary of changes:
src/target/smp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-05-04 08:35:31
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via c72afedce794a7251fd9c822e3bfc89f870b9fc1 (commit)
from 42e31d75b443e369597669b5ff7901de902ad35e (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit c72afedce794a7251fd9c822e3bfc89f870b9fc1
Author: Antonio Borneo <bor...@gm...>
Date: Sat Apr 13 18:54:12 2024 +0200
target: cortex_a: fix regs invalidation when -defer-examine
The code for cortex_a allocates the register cache during the very
first examine of the target.
To prevent a segmentation fault in assert_reset(), the call to
register_cache_invalidate() is guarded by target_was_examined().
But for targets with -defer-examine, the target is set as not
examined in handle_target_reset() just before entering in
assert_reset().
This causes registers to not be invalidated while reset a target
examined but with -defer-examine.
Change the condition and invalidate the register cache if it has
been already allocated.
Change-Id: I81ae782ddce07431d5f2c1bea3e2f19dfcd6d1ce
Signed-off-by: Antonio Borneo <bor...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8215
Tested-by: jenkins
diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c
index 7fa0c4e8b..78fd4482c 100644
--- a/src/target/cortex_a.c
+++ b/src/target/cortex_a.c
@@ -1932,7 +1932,7 @@ static int cortex_a_assert_reset(struct target *target)
}
/* registers are now invalid */
- if (target_was_examined(target))
+ if (armv7a->arm.core_cache)
register_cache_invalidate(armv7a->arm.core_cache);
target->state = TARGET_RESET;
-----------------------------------------------------------------------
Summary of changes:
src/target/cortex_a.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-05-04 08:35:16
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 42e31d75b443e369597669b5ff7901de902ad35e (commit)
from 89d881c19ae89712652f17962b8b7d2e79e25ca3 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 42e31d75b443e369597669b5ff7901de902ad35e
Author: Antonio Borneo <bor...@gm...>
Date: Sat Apr 13 18:46:11 2024 +0200
target: aarch64: fix regs invalidation when -defer-examine
The code for aarch64 allocates the register cache during the very
first examine of the target.
To prevent a segmentation fault in assert_reset(), the call to
register_cache_invalidate() is guarded by target_was_examined().
But for targets with -defer-examine, the target is set as not
examined in handle_target_reset() just before entering in
assert_reset().
This causes registers to not be invalidated while reset a target
examined but with -defer-examine.
Change the condition and invalidate the register cache if it has
been already allocated.
Change-Id: Ie13abb0ae2cc28fc3295d678c4ad1691024eb7b8
Signed-off-by: Antonio Borneo <bor...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8214
Tested-by: jenkins
diff --git a/src/target/aarch64.c b/src/target/aarch64.c
index 2e4d0b5c0..6a70b2ddf 100644
--- a/src/target/aarch64.c
+++ b/src/target/aarch64.c
@@ -1983,7 +1983,7 @@ static int aarch64_assert_reset(struct target *target)
}
/* registers are now invalid */
- if (target_was_examined(target)) {
+ if (armv8->arm.core_cache) {
register_cache_invalidate(armv8->arm.core_cache);
register_cache_invalidate(armv8->arm.core_cache->next);
}
-----------------------------------------------------------------------
Summary of changes:
src/target/aarch64.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-05-04 08:34:25
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 89d881c19ae89712652f17962b8b7d2e79e25ca3 (commit)
from 8667a726532604afab099881779a4b898539dabf (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 89d881c19ae89712652f17962b8b7d2e79e25ca3
Author: Antonio Borneo <bor...@gm...>
Date: Mon Apr 8 17:40:09 2024 +0200
cortex_m: don't try to halt not-examined targets
Prevent a segmentation fault by preventing to try to halt a target
that has not been examined yet.
Change-Id: I5d344e7fbdb5422f7c5e2c39bdd48cbc6c2a3e58
Signed-off-by: Antonio Borneo <bor...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8213
Tested-by: jenkins
diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c
index a26df2e5a..c225b1aa9 100644
--- a/src/target/cortex_m.c
+++ b/src/target/cortex_m.c
@@ -1109,6 +1109,11 @@ static int cortex_m_halt_one(struct target *target)
int retval;
LOG_TARGET_DEBUG(target, "target->state: %s", target_state_name(target));
+ if (!target_was_examined(target)) {
+ LOG_TARGET_ERROR(target, "target non examined yet");
+ return ERROR_TARGET_NOT_EXAMINED;
+ }
+
if (target->state == TARGET_HALTED) {
LOG_TARGET_DEBUG(target, "target was already halted");
return ERROR_OK;
-----------------------------------------------------------------------
Summary of changes:
src/target/cortex_m.c | 5 +++++
1 file changed, 5 insertions(+)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-05-04 08:31:46
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 8667a726532604afab099881779a4b898539dabf (commit)
from ac6b00c3cae5def9c1b3f08fae68703abc494109 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 8667a726532604afab099881779a4b898539dabf
Author: Marc Schink <de...@za...>
Date: Sat Nov 18 12:48:33 2023 +0100
target/target: Add 'debug_reason' to current target
Change-Id: Ie35b13b3e06411b4866ffeada47b3262493dbf2e
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8021
Tested-by: jenkins
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/doc/openocd.texi b/doc/openocd.texi
index 52a51c196..55e6e7680 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -9191,6 +9191,18 @@ read_memory 0x20000000 32 2
@end example
@end deffn
+@deffn {Command} {debug_reason}
+Displays the current debug reason:
+@code{debug-request},
+@code{breakpoint},
+@code{watchpoint},
+@code{watchpoint-and-breakpoint},
+@code{single-step},
+@code{target-not-halted},
+@code{program-exit},
+@code{exception-catch} or @code{undefined}.
+@end deffn
+
@deffn {Command} {halt} [ms]
@deffnx {Command} {wait_halt} [ms]
The @command{halt} command first sends a halt request to the target,
diff --git a/src/target/target.c b/src/target/target.c
index 45698a66c..5168305de 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -6736,6 +6736,13 @@ static const struct command_registration target_exec_command_handlers[] = {
.help = "Write Tcl list of 8/16/32/64 bit numbers to target memory",
.usage = "address width data ['phys']",
},
+ {
+ .name = "debug_reason",
+ .mode = COMMAND_EXEC,
+ .handler = handle_target_debug_reason,
+ .help = "displays the debug reason of this target",
+ .usage = "",
+ },
{
.name = "reset_nag",
.handler = handle_target_reset_nag,
-----------------------------------------------------------------------
Summary of changes:
doc/openocd.texi | 12 ++++++++++++
src/target/target.c | 7 +++++++
2 files changed, 19 insertions(+)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-05-04 08:24:57
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via ac6b00c3cae5def9c1b3f08fae68703abc494109 (commit)
from a9e8ca55a6f44cf6edef7ea5ca66927fa02f3cca (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit ac6b00c3cae5def9c1b3f08fae68703abc494109
Author: Antonio Borneo <bor...@gm...>
Date: Sat Apr 6 00:26:38 2024 +0200
target: cortex_m: fix display of DWT registers
Commit 16b4b8cf5453 ("Cortex-M3: expose most DWT registers") added
the DWT registers to the list of CPU registers.
The commit message from 2009 reports the reason behind this odd
mixing of CPU and DWT registers.
This feature got broken in 2017 with the introduction of the field
struct reg::exist and its further use in the code. As result, the
command 'reg' on a target Cortex-M reports only the core registers
and then the header line
===== Cortex-M DWT registers
not anymore followed by the DWT registers.
Fix it by tagging each DWT registers as existing.
Change-Id: Iab026e7da8d6b8ba052514c3fd3b5cdfe301f330
Signed-off-by: Antonio Borneo <bor...@gm...>
Fixes: b5964191f0d2 ("register: support non-existent registers")
Reviewed-on: https://review.openocd.org/c/openocd/+/8198
Reviewed-by: Tomas Vanek <va...@fb...>
Tested-by: jenkins
diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c
index 4894cabf8..a26df2e5a 100644
--- a/src/target/cortex_m.c
+++ b/src/target/cortex_m.c
@@ -2351,6 +2351,7 @@ static void cortex_m_dwt_addreg(struct target *t, struct reg *r, const struct dw
r->value = state->value;
r->arch_info = state;
r->type = &dwt_reg_type;
+ r->exist = true;
}
static void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target)
-----------------------------------------------------------------------
Summary of changes:
src/target/cortex_m.c | 1 +
1 file changed, 1 insertion(+)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-05-04 08:22:45
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via a9e8ca55a6f44cf6edef7ea5ca66927fa02f3cca (commit)
from 495311d2067e85ee1fb53593a4671ef0ec09c6f1 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit a9e8ca55a6f44cf6edef7ea5ca66927fa02f3cca
Author: Antonio Borneo <bor...@gm...>
Date: Sun Apr 7 12:28:55 2024 +0200
jtag: linuxgpiod: minor alignment to coding style
Avoid double TAB in 'then' block by increasing indentation of the
multi-line condition.
Change-Id: I7f5a4437fe4f74228f1b0d98e5c5921af4fd36b8
Signed-off-by: Antonio Borneo <bor...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8200
Tested-by: jenkins
Reviewed-by: Oleksij Rempel <li...@re...>
diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c
index 2f3d64454..1926ed9ae 100644
--- a/src/jtag/drivers/linuxgpiod.c
+++ b/src/jtag/drivers/linuxgpiod.c
@@ -378,12 +378,12 @@ static int linuxgpiod_init(void)
goto out_error;
}
- if (helper_get_line(ADAPTER_GPIO_IDX_TDO) != ERROR_OK ||
- helper_get_line(ADAPTER_GPIO_IDX_TDI) != ERROR_OK ||
- helper_get_line(ADAPTER_GPIO_IDX_TCK) != ERROR_OK ||
- helper_get_line(ADAPTER_GPIO_IDX_TMS) != ERROR_OK ||
- helper_get_line(ADAPTER_GPIO_IDX_TRST) != ERROR_OK)
- goto out_error;
+ if (helper_get_line(ADAPTER_GPIO_IDX_TDO) != ERROR_OK
+ || helper_get_line(ADAPTER_GPIO_IDX_TDI) != ERROR_OK
+ || helper_get_line(ADAPTER_GPIO_IDX_TCK) != ERROR_OK
+ || helper_get_line(ADAPTER_GPIO_IDX_TMS) != ERROR_OK
+ || helper_get_line(ADAPTER_GPIO_IDX_TRST) != ERROR_OK)
+ goto out_error;
}
if (transport_is_swd()) {
@@ -413,9 +413,9 @@ static int linuxgpiod_init(void)
goto out_error;
}
- if (helper_get_line(ADAPTER_GPIO_IDX_SRST) != ERROR_OK ||
- helper_get_line(ADAPTER_GPIO_IDX_LED) != ERROR_OK)
- goto out_error;
+ if (helper_get_line(ADAPTER_GPIO_IDX_SRST) != ERROR_OK
+ || helper_get_line(ADAPTER_GPIO_IDX_LED) != ERROR_OK)
+ goto out_error;
return ERROR_OK;
-----------------------------------------------------------------------
Summary of changes:
src/jtag/drivers/linuxgpiod.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-05-04 08:22:12
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 495311d2067e85ee1fb53593a4671ef0ec09c6f1 (commit)
from 04154af5d6cd5fe76a2583778379bdacb5aa6fb0 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 495311d2067e85ee1fb53593a4671ef0ec09c6f1
Author: Antonio Borneo <bor...@gm...>
Date: Sun Apr 7 12:41:48 2024 +0200
doc: style: report indentation of multi-line condition
To help readability and discriminate the 'then' block from the
multi-line condition, suggest to increase the indentation of the
condition.
Change-Id: I02e3834be3001e7ecf24349ad3cefe94b27b79c8
Signed-off-by: Antonio Borneo <bor...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8199
Reviewed-by: Tomas Vanek <va...@fb...>
Tested-by: jenkins
Reviewed-by: Oleksij Rempel <li...@re...>
diff --git a/doc/manual/style.txt b/doc/manual/style.txt
index 1d3ec6748..a1e6b8f01 100644
--- a/doc/manual/style.txt
+++ b/doc/manual/style.txt
@@ -97,6 +97,21 @@ OpenOCD project.
x = 0;
}
@endcode
+- on <tt> if </tt> statements where the condition is split among multiple
+ lines, increase the indentation of the condition to prevent it to match
+ to the indentation of the <tt> then </tt> block due to length of 'if ('
+ being same of the TAB width of 4 characters. Use:
+ @code
+ if (CMD_ARGC < 3
+ || CMD_ARGC > 8)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ @endcode
+ instead of:
+ @code
+ if (CMD_ARGC < 3 ||
+ CMD_ARGC > 8)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ @endcode
Finally, try to avoid lines of code that are longer than 72-80 columns:
-----------------------------------------------------------------------
Summary of changes:
doc/manual/style.txt | 15 +++++++++++++++
1 file changed, 15 insertions(+)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-04-07 20:10:42
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 04154af5d6cd5fe76a2583778379bdacb5aa6fb0 (commit)
from 47d983a77aeefa511d18450d65e7111799d926a8 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 04154af5d6cd5fe76a2583778379bdacb5aa6fb0
Author: Antonio Borneo <bor...@gm...>
Date: Sun Mar 24 22:57:52 2024 +0100
jtag: linuxgpiod: drop extra parenthesis
Checkpatch complains for extra parenthesis not required.
Drop them.
Change-Id: I311409f5732acf10a4910de5dcf0fb05f43e21b5
Signed-off-by: Antonio Borneo <bor...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8187
Reviewed-by: Tomas Vanek <va...@fb...>
Tested-by: jenkins
diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c
index 3ca452357..2f3d64454 100644
--- a/src/jtag/drivers/linuxgpiod.c
+++ b/src/jtag/drivers/linuxgpiod.c
@@ -157,7 +157,7 @@ static int linuxgpiod_swd_write(int swclk, int swdio)
int retval;
if (!swdio_input) {
- if (!last_stored || (swdio != last_swdio)) {
+ if (!last_stored || swdio != last_swdio) {
retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWDIO], swdio);
if (retval < 0)
LOG_WARNING("Fail set swdio");
@@ -165,7 +165,7 @@ static int linuxgpiod_swd_write(int swclk, int swdio)
}
/* write swclk last */
- if (!last_stored || (swclk != last_swclk)) {
+ if (!last_stored || swclk != last_swclk) {
retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWCLK], swclk);
if (retval < 0)
LOG_WARNING("Fail set swclk");
-----------------------------------------------------------------------
Summary of changes:
src/jtag/drivers/linuxgpiod.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-04-07 19:37:22
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 47d983a77aeefa511d18450d65e7111799d926a8 (commit)
from 79b51fedab9e8023a2e72551c4dcaf4373274287 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 47d983a77aeefa511d18450d65e7111799d926a8
Author: Walter Ji <wal...@os...>
Date: Mon Mar 18 17:24:51 2024 +0800
target/mips32: fix clang sbuild check fail
Initialized `value` variables that could only be set in a branch.
Change-Id: Iec7413ade9d053c93352a58ff954ad49a6545923
Signed-off-by: Walter Ji <wal...@os...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8179
Tested-by: jenkins
Reviewed-by: Oleksij Rempel <li...@re...>
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/src/target/mips32.c b/src/target/mips32.c
index 6bbf71bd8..81faab72d 100644
--- a/src/target/mips32.c
+++ b/src/target/mips32.c
@@ -2109,7 +2109,7 @@ static int mips32_dsp_find_register_by_name(const char *reg_name)
*/
static int mips32_dsp_get_all_regs(struct command_invocation *cmd, struct mips_ejtag *ejtag_info)
{
- uint32_t value;
+ uint32_t value = 0;
for (int i = 0; i < MIPS32NUMDSPREGS; i++) {
int retval = mips32_pracc_read_dsp_reg(ejtag_info, &value, i);
if (retval != ERROR_OK) {
@@ -2134,7 +2134,7 @@ static int mips32_dsp_get_all_regs(struct command_invocation *cmd, struct mips_e
*/
static int mips32_dsp_get_register(struct command_invocation *cmd, struct mips_ejtag *ejtag_info)
{
- uint32_t value;
+ uint32_t value = 0;
int index = mips32_dsp_find_register_by_name(CMD_ARGV[0]);
if (index == MIPS32NUMDSPREGS) {
command_print(CMD, "ERROR: register '%s' not found", CMD_ARGV[0]);
-----------------------------------------------------------------------
Summary of changes:
src/target/mips32.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-04-07 19:37:02
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 79b51fedab9e8023a2e72551c4dcaf4373274287 (commit)
from e035756b22f96adc95b791aaa01de7a2c11d7f2e (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 79b51fedab9e8023a2e72551c4dcaf4373274287
Author: J. Neuschäfer <j.n...@gm...>
Date: Sat Mar 30 13:18:43 2024 +0100
remote_bitbang: Change sleep commands to Zz to avoid conflict with SWD
It was noticed that the remote_bitbang protocol has a design issue:
SWD and sleep commands cannot be implemented at the same time, because
they overlap:
- SWD uses d,e,f,g for setting pin state
- sleep uses d,D for microsecond and millisecond sleep, respectively
This has previously been reported by Marek Vrbka, but it wasn't fixed.
This commit does the following to resolve the issue:
- Change the sleep commands to 'Z' for 1 ms, 'z' for 1 µs
- Document 'D' and 'd' as deprecated aliases
- Switch the remote_bitbang driver in OpenOCD to 'Z' and 'z'
Unfortunately that's a breaking change, because existing adapter-side
implementations of the protocol will have to implement the new commands
to keep working with future versions of OpenOCD. Fortunately, the
remote sleep commands haven't been part of an OpenOCD release yet,
which should limit the breakage somewhat.
Reported-by: Marek Vrbka <mar...@co...>
Link: https://sourceforge.net/p/openocd/mailman/openocd-devel/thread/670d28d2-75a1-45ec-afe5-541415701d7a%40codasip.com/
Fixes: e8e09b1b5 ("remote_bitbang: add use_remote_sleep option to send delays to remote")
Change-Id: I04d2790a33bff9d47eb7f69b3275fd9a271625ae
Signed-off-by: J. Neuschäfer <j.n...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8191
Reviewed-by: David Ryskalczyk <dav...@gm...>
Reviewed-by: Antonio Borneo <bor...@gm...>
Tested-by: jenkins
Reviewed-by: Jeremy Herbert <jer...@gm...>
diff --git a/doc/manual/jtag/drivers/remote_bitbang.txt b/doc/manual/jtag/drivers/remote_bitbang.txt
index 94d603816..8316cb0dd 100644
--- a/doc/manual/jtag/drivers/remote_bitbang.txt
+++ b/doc/manual/jtag/drivers/remote_bitbang.txt
@@ -77,7 +77,12 @@ The read responses are encoded in ASCII as either digit 0 or 1.
If the use_remote_sleep option is set to 'yes', two additional requests may
be sent:
- D - Sleep for 1 millisecond
- d - Sleep for 1 microsecond
+ Z - Sleep for 1 millisecond
+ z - Sleep for 1 microsecond
+
+NOTE: Previously these were specified as 'D' and 'd', which conflicts with the
+"SWD write 0 0" command defined above. Adapters that implement Dd for remote
+sleep must be updated to work with Zz.
+
*/
diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c
index c97b6b6ab..53d2151fd 100644
--- a/src/jtag/drivers/remote_bitbang.c
+++ b/src/jtag/drivers/remote_bitbang.c
@@ -230,13 +230,13 @@ static int remote_bitbang_sleep(unsigned int microseconds)
unsigned int us = microseconds % 1000;
for (unsigned int i = 0; i < ms; i++) {
- tmp = remote_bitbang_queue('D', NO_FLUSH);
+ tmp = remote_bitbang_queue('Z', NO_FLUSH);
if (tmp != ERROR_OK)
return tmp;
}
for (unsigned int i = 0; i < us; i++) {
- tmp = remote_bitbang_queue('d', NO_FLUSH);
+ tmp = remote_bitbang_queue('z', NO_FLUSH);
if (tmp != ERROR_OK)
return tmp;
}
-----------------------------------------------------------------------
Summary of changes:
doc/manual/jtag/drivers/remote_bitbang.txt | 9 +++++++--
src/jtag/drivers/remote_bitbang.c | 4 ++--
2 files changed, 9 insertions(+), 4 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-04-07 19:36:15
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via e035756b22f96adc95b791aaa01de7a2c11d7f2e (commit)
from 74e7fcb2dd96c09f946bc8b0f59bfdf6215d8873 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit e035756b22f96adc95b791aaa01de7a2c11d7f2e
Author: Antonio Borneo <bor...@gm...>
Date: Sun Mar 24 16:17:11 2024 +0100
jtag: linuxgpiod: fix detection for line request bias
Commit 290eac04b93c ("drivers/linuxgpiod: Migrate to adapter gpio
commands") introduced an incorrect check to determine if the
library libgpiod declares the line request flags:
GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE
GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP
GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN
The names above are declared by the library inside an enum, thus
cannot be used by the C preprocessor in a #ifdef.
Determine in configure if the version of libgpiod provides the
line request flags for "bias" and define a C macro.
Use the new macro in the driver code.
Change-Id: Iaa452230f4753fce4c6e9daa254299cedb7cab7f
Signed-off-by: Antonio Borneo <bor...@gm...>
Fixes: 290eac04b93c ("drivers/linuxgpiod: Migrate to adapter gpio commands")
Reviewed-on: https://review.openocd.org/c/openocd/+/8186
Tested-by: jenkins
Reviewed-by: Michael Heimpold <mic...@gm...>
diff --git a/configure.ac b/configure.ac
index fd7b64d15..761384837 100644
--- a/configure.ac
+++ b/configure.ac
@@ -669,7 +669,11 @@ PKG_CHECK_MODULES([LIBFTDI], [libftdi1], [
PKG_CHECK_MODULES([LIBFTDI], [libftdi], [use_libftdi=yes], [use_libftdi=no])
])
-PKG_CHECK_MODULES([LIBGPIOD], [libgpiod < 2.0], [use_libgpiod=yes], [use_libgpiod=no])
+PKG_CHECK_MODULES([LIBGPIOD], [libgpiod < 2.0], [
+ use_libgpiod=yes
+ PKG_CHECK_EXISTS([libgpiod >= 1.5],
+ [AC_DEFINE([HAVE_LIBGPIOD1_FLAGS_BIAS], [1], [define if libgpiod v1 has line request flags bias])])
+], [use_libgpiod=no])
PKG_CHECK_MODULES([LIBJAYLINK], [libjaylink >= 0.2],
[use_libjaylink=yes], [use_libjaylink=no])
diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c
index 942883788..3ca452357 100644
--- a/src/jtag/drivers/linuxgpiod.c
+++ b/src/jtag/drivers/linuxgpiod.c
@@ -320,12 +320,12 @@ static int helper_get_line(enum adapter_gpio_config_index idx)
switch (adapter_gpio_config[idx].pull) {
case ADAPTER_GPIO_PULL_NONE:
-#ifdef GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE
+#ifdef HAVE_LIBGPIOD1_FLAGS_BIAS
flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE;
#endif
break;
case ADAPTER_GPIO_PULL_UP:
-#ifdef GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP
+#ifdef HAVE_LIBGPIOD1_FLAGS_BIAS
flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP;
#else
LOG_WARNING("linuxgpiod: ignoring request for pull-up on %s: not supported by gpiod v%s",
@@ -333,7 +333,7 @@ static int helper_get_line(enum adapter_gpio_config_index idx)
#endif
break;
case ADAPTER_GPIO_PULL_DOWN:
-#ifdef GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN
+#ifdef HAVE_LIBGPIOD1_FLAGS_BIAS
flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN;
#else
LOG_WARNING("linuxgpiod: ignoring request for pull-down on %s: not supported by gpiod v%s",
-----------------------------------------------------------------------
Summary of changes:
configure.ac | 6 +++++-
src/jtag/drivers/linuxgpiod.c | 6 +++---
2 files changed, 8 insertions(+), 4 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-04-07 19:35:50
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 74e7fcb2dd96c09f946bc8b0f59bfdf6215d8873 (commit)
from 329e983ee9bb24bfa49c59c949d5da250506b7f4 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 74e7fcb2dd96c09f946bc8b0f59bfdf6215d8873
Author: Antonio Borneo <bor...@gm...>
Date: Sun Mar 24 15:53:33 2024 +0100
configure: prevent build of linuxgpiod with libgpiod v2
The API in libgpiod v2 have changed, and current driver code for
linuxgpiod does not build anymore.
Prevent building the current driver linuxgpiod with the new
library.
Change-Id: Ie673db786dc50ae18a263d2c0a2b46b106866450
Signed-off-by: Antonio Borneo <bor...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8185
Reviewed-by: Michael Heimpold <mic...@gm...>
Tested-by: jenkins
Reviewed-by: Tomas Vanek <va...@fb...>
diff --git a/configure.ac b/configure.ac
index c9cf0214e..fd7b64d15 100644
--- a/configure.ac
+++ b/configure.ac
@@ -669,7 +669,7 @@ PKG_CHECK_MODULES([LIBFTDI], [libftdi1], [
PKG_CHECK_MODULES([LIBFTDI], [libftdi], [use_libftdi=yes], [use_libftdi=no])
])
-PKG_CHECK_MODULES([LIBGPIOD], [libgpiod], [use_libgpiod=yes], [use_libgpiod=no])
+PKG_CHECK_MODULES([LIBGPIOD], [libgpiod < 2.0], [use_libgpiod=yes], [use_libgpiod=no])
PKG_CHECK_MODULES([LIBJAYLINK], [libjaylink >= 0.2],
[use_libjaylink=yes], [use_libjaylink=no])
-----------------------------------------------------------------------
Summary of changes:
configure.ac | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-04-07 13:46:43
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 329e983ee9bb24bfa49c59c949d5da250506b7f4 (commit)
from dd1758272276e20d5b60c16146a820ec8b5bfaa1 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 329e983ee9bb24bfa49c59c949d5da250506b7f4
Author: Dominik Wernberger <dom...@gm...>
Date: Tue Mar 26 20:32:22 2024 +0100
zynq_7000.cfg: Fix issue 'Error: can't read "zynq_pl": no such variable'
Change-Id: Ic79ce114b60d0707a6e082a81743b378b164b4e2
Signed-off-by: Dominik Wernberger <dom...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8190
Reviewed-by: Daniel Anselmi <dan...@gm...>
Reviewed-by: Tomas Vanek <va...@fb...>
Tested-by: jenkins
diff --git a/tcl/target/zynq_7000.cfg b/tcl/target/zynq_7000.cfg
index f5b4478ff..5a88b6e9d 100644
--- a/tcl/target/zynq_7000.cfg
+++ b/tcl/target/zynq_7000.cfg
@@ -47,7 +47,7 @@ ${_TARGETNAME}0 configure -event reset-assert-post "cortex_a dbginit"
${_TARGETNAME}1 configure -event reset-assert-post "cortex_a dbginit"
pld create zynq_pl.pld virtex2 -chain-position zynq_pl.bs -no_jstart
-virtex2 set_user_codes $zynq_pl.pld 0x02 0x03 0x22 0x23
+virtex2 set_user_codes zynq_pl.pld 0x02 0x03 0x22 0x23
set XC7_JSHUTDOWN 0x0d
set XC7_JPROGRAM 0x0b
-----------------------------------------------------------------------
Summary of changes:
tcl/target/zynq_7000.cfg | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-04-01 05:52:06
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via dd1758272276e20d5b60c16146a820ec8b5bfaa1 (commit)
from a35e254c5383008cdacf7838a777f7f17af5eeb1 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit dd1758272276e20d5b60c16146a820ec8b5bfaa1
Author: Steven Chang <st...@en...>
Date: Sun Feb 11 21:34:50 2024 +0800
flash/nor/eneispif: support ENE KB1200 ispi flash
Change-Id: I03bccceb1956ee121e6a3728b7d647ef1262fa23
Signed-off-by: Steven Chang <st...@en...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8136
Tested-by: jenkins
Reviewed-by: Tomas Vanek <va...@fb...>
diff --git a/doc/openocd.texi b/doc/openocd.texi
index 6b71fe869..52a51c196 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -6776,6 +6776,24 @@ Note that in order for this command to take effect, the target needs to be reset
supported.}
@end deffn
+@deffn {Flash Driver} {eneispif}
+All versions of the KB1200 microcontrollers from ENE include internal
+flash. The eneispif flash driver supports the KB1200 family of devices. The driver
+automatically recognizes the specific version's flash parameters and
+autoconfigures itself. The flash bank starts at address 0x60000000. An optional additional
+parameter sets the address of eneispif controller, with the default address is 0x50101000.
+
+@example
+
+flash bank $_FLASHNAME eneispif 0x60000000 0 0 0 $_TARGETNAME \
+ 0x50101000
+
+# Address defaults to 0x50101000
+flash bank $_FLASHNAME eneispif 0x60000000 0 0 0 $_TARGETNAME
+
+@end example
+@end deffn
+
@deffn {Flash Driver} {esirisc}
Members of the eSi-RISC family may optionally include internal flash programmed
via the eSi-TSMC Flash interface. Additional parameters are required to
diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am
index 534a7a804..afa11e7d4 100644
--- a/src/flash/nor/Makefile.am
+++ b/src/flash/nor/Makefile.am
@@ -28,6 +28,7 @@ NOR_DRIVERS = \
%D%/dsp5680xx_flash.c \
%D%/efm32.c \
%D%/em357.c \
+ %D%/eneispif.c \
%D%/esirisc_flash.c \
%D%/faux.c \
%D%/fespi.c \
diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h
index a63b72c8f..7d6f8c5cc 100644
--- a/src/flash/nor/driver.h
+++ b/src/flash/nor/driver.h
@@ -256,6 +256,7 @@ extern const struct flash_driver cfi_flash;
extern const struct flash_driver dsp5680xx_flash;
extern const struct flash_driver efm32_flash;
extern const struct flash_driver em357_flash;
+extern const struct flash_driver eneispif_flash;
extern const struct flash_driver esirisc_flash;
extern const struct flash_driver faux_flash;
extern const struct flash_driver fespi_flash;
diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
index 3157bd329..34359889a 100644
--- a/src/flash/nor/drivers.c
+++ b/src/flash/nor/drivers.c
@@ -33,6 +33,7 @@ static const struct flash_driver * const flash_drivers[] = {
&dsp5680xx_flash,
&efm32_flash,
&em357_flash,
+ &eneispif_flash,
&esirisc_flash,
&faux_flash,
&fm3_flash,
diff --git a/src/flash/nor/eneispif.c b/src/flash/nor/eneispif.c
new file mode 100644
index 000000000..6572b8c25
--- /dev/null
+++ b/src/flash/nor/eneispif.c
@@ -0,0 +1,433 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/*
+ * Copyright (c) 2024 ENE Technology Inc.
+ * st...@en...
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/time_support.h>
+#include <helper/bits.h>
+#include <target/target.h>
+#include <flash/nor/core.h>
+#include <flash/nor/driver.h>
+#include <flash/nor/spi.h>
+
+#define ISPICFG 0x0000
+#define ISPISTS 0x0004
+#define ISPIADDR 0x0008
+#define ISPICMD 0x000C
+#define ISPIDAT 0x0100
+
+#define ISPISTS_BUSY BIT(0)
+#define STATUS1_QE BIT(1)
+
+#define CFG_READ 0x372
+#define CFG_WRITE 0x371
+
+#define ISPI_CTRL_BASE 0x50101000
+
+/* name read qread page erase chip device_id page erase flash
+ * _cmd _cmd _prog _cmd* _erase size size* size
+ * _cmd _cmd
+ */
+struct flash_device ene_flash_device =
+ FLASH_ID("ISPI flash", 0x03, 0x00, 0x02, 0x20, 0x60, 0x00132085, 0x100, 0x1000, 0x80000);
+
+struct eneispif_flash_bank {
+ bool probed;
+ target_addr_t ctrl_base;
+ uint32_t dev_id;
+ const struct flash_device *dev;
+};
+
+FLASH_BANK_COMMAND_HANDLER(eneispif_flash_bank_command)
+{
+ struct eneispif_flash_bank *eneispif_info;
+
+ LOG_DEBUG("%s", __func__);
+
+ if (CMD_ARGC < 6)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ eneispif_info = malloc(sizeof(struct eneispif_flash_bank));
+ if (!eneispif_info) {
+ LOG_ERROR("not enough memory");
+ return ERROR_FAIL;
+ }
+
+ bank->driver_priv = eneispif_info;
+ eneispif_info->probed = false;
+ eneispif_info->ctrl_base = ISPI_CTRL_BASE;
+ if (CMD_ARGC >= 7) {
+ COMMAND_PARSE_ADDRESS(CMD_ARGV[6], eneispif_info->ctrl_base);
+ LOG_INFO("ASSUMING ISPI device at ctrl_base = " TARGET_ADDR_FMT,
+ eneispif_info->ctrl_base);
+ }
+
+ return ERROR_OK;
+}
+
+static int eneispif_read_reg(struct flash_bank *bank, uint32_t *value, target_addr_t address)
+{
+ struct target *target = bank->target;
+ struct eneispif_flash_bank *eneispif_info = bank->driver_priv;
+
+ int result = target_read_u32(target, eneispif_info->ctrl_base + address, value);
+ if (result != ERROR_OK) {
+ LOG_ERROR("%s error at " TARGET_ADDR_FMT, __func__,
+ eneispif_info->ctrl_base + address);
+ return result;
+ }
+ LOG_DEBUG("Read address " TARGET_ADDR_FMT " = 0x%" PRIx32,
+ eneispif_info->ctrl_base + address, *value);
+ return ERROR_OK;
+}
+
+static int eneispif_write_reg(struct flash_bank *bank, target_addr_t address, uint32_t value)
+{
+ struct target *target = bank->target;
+ struct eneispif_flash_bank *eneispif_info = bank->driver_priv;
+
+ LOG_DEBUG("Write address " TARGET_ADDR_FMT " = 0x%" PRIx32,
+ eneispif_info->ctrl_base + address, value);
+ int result = target_write_u32(target, eneispif_info->ctrl_base + address, value);
+ if (result != ERROR_OK) {
+ LOG_ERROR("%s error writing 0x%" PRIx32 " to " TARGET_ADDR_FMT, __func__,
+ value, eneispif_info->ctrl_base + address);
+ return result;
+ }
+ return ERROR_OK;
+}
+
+static int eneispif_wait(struct flash_bank *bank)
+{
+ int64_t start = timeval_ms();
+
+ while (1) {
+ uint32_t status;
+
+ if (eneispif_read_reg(bank, &status, ISPISTS) != ERROR_OK)
+ return ERROR_FAIL;
+
+ if (!(status & ISPISTS_BUSY))
+ break;
+
+ int64_t now = timeval_ms();
+ if (now - start > 1000) {
+ LOG_ERROR("Busy more than 1000ms.");
+ return ERROR_TARGET_TIMEOUT;
+ }
+ }
+
+ return ERROR_OK;
+}
+
+static int eneispi_erase_sector(struct flash_bank *bank, int sector)
+{
+ int retval = ERROR_OK;
+ struct eneispif_flash_bank *eneispif_info = bank->driver_priv;
+ uint32_t offset;
+ uint32_t conf;
+
+ retval = eneispif_read_reg(bank, &conf, ISPICFG);
+ if (retval != ERROR_OK)
+ return retval;
+
+ offset = bank->sectors[sector].offset;
+ retval = eneispif_write_reg(bank, ISPIADDR, offset); /* Address */
+ if (retval != ERROR_OK)
+ goto done;
+
+ eneispif_write_reg(bank, ISPICFG, CFG_WRITE); /* Cmmmand enable */
+ eneispif_write_reg(bank, ISPICMD, SPIFLASH_WRITE_ENABLE); /* Write enable */
+ retval = eneispif_write_reg(bank, ISPICMD, eneispif_info->dev->erase_cmd); /* Erase page */
+ if (retval != ERROR_OK)
+ goto done;
+
+ retval = eneispif_wait(bank);
+ if (retval != ERROR_OK)
+ goto done;
+
+done:
+ eneispif_write_reg(bank, ISPICFG, conf); /* restore */
+ return retval;
+}
+
+static int eneispif_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
+{
+ struct target *target = bank->target;
+ struct eneispif_flash_bank *eneispif_info = bank->driver_priv;
+ int retval = ERROR_OK;
+
+ LOG_DEBUG("%s: from sector %u to sector %u", __func__, first, last);
+
+ if (target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ if (last < first || last >= bank->num_sectors) {
+ LOG_ERROR("Flash sector invalid");
+ return ERROR_FLASH_SECTOR_INVALID;
+ }
+
+ if (!(eneispif_info->probed)) {
+ LOG_ERROR("Flash bank not probed");
+ return ERROR_FLASH_BANK_NOT_PROBED;
+ }
+
+ for (unsigned int sector = first; sector <= last; sector++) {
+ if (bank->sectors[sector].is_protected) {
+ LOG_ERROR("Flash sector %u protected", sector);
+ return ERROR_FAIL;
+ }
+ }
+
+ if (eneispif_info->dev->erase_cmd == 0x00)
+ return ERROR_FLASH_OPER_UNSUPPORTED;
+
+ for (unsigned int sector = first; sector <= last; sector++) {
+ retval = eneispi_erase_sector(bank, sector);
+ if (retval != ERROR_OK)
+ break;
+ }
+
+ return retval;
+}
+
+static int eneispif_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int last)
+{
+ for (unsigned int sector = first; sector <= last; sector++)
+ bank->sectors[sector].is_protected = set;
+
+ return ERROR_OK;
+}
+
+static int eneispif_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset,
+ uint32_t count)
+{
+ struct target *target = bank->target;
+ struct eneispif_flash_bank *eneispif_info = bank->driver_priv;
+ uint32_t page_size;
+ uint32_t conf;
+ int retval = ERROR_OK;
+
+ LOG_DEBUG("bank->size=0x%x offset=0x%08" PRIx32 " count=0x%08" PRIx32, bank->size, offset,
+ count);
+
+ if (target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ if (offset + count > eneispif_info->dev->size_in_bytes) {
+ LOG_WARNING("Write past end of flash. Extra data discarded.");
+ count = eneispif_info->dev->size_in_bytes - offset;
+ }
+
+ /* Check sector protection */
+ for (unsigned int sector = 0; sector < bank->num_sectors; sector++) {
+ /* Start offset in or before this sector? */
+ /* End offset in or behind this sector? */
+ if ((offset < (bank->sectors[sector].offset + bank->sectors[sector].size)) &&
+ ((offset + count - 1) >= bank->sectors[sector].offset) &&
+ bank->sectors[sector].is_protected) {
+ LOG_ERROR("Flash sector %u protected", sector);
+ return ERROR_FAIL;
+ }
+ }
+
+ retval = eneispif_read_reg(bank, &conf, ISPICFG);
+ if (retval != ERROR_OK)
+ return retval;
+
+ eneispif_write_reg(bank, ISPICFG, CFG_WRITE); // Cmmmand enable
+
+ /* If no valid page_size, use reasonable default. */
+ page_size =
+ eneispif_info->dev->pagesize ? eneispif_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
+ uint32_t page_offset = offset % page_size;
+
+ while (count > 0) {
+ uint32_t cur_count;
+
+ /* clip block at page boundary */
+ if (page_offset + count > page_size)
+ cur_count = page_size - page_offset;
+ else
+ cur_count = count;
+
+ eneispif_write_reg(bank, ISPICMD, SPIFLASH_WRITE_ENABLE); /* Write enable */
+ target_write_buffer(target, eneispif_info->ctrl_base + ISPIDAT, cur_count, buffer);
+ eneispif_write_reg(bank, ISPIADDR, offset);
+ retval = eneispif_write_reg(bank, ISPICMD,
+ (cur_count << 16) | eneispif_info->dev->pprog_cmd);
+ if (retval != ERROR_OK)
+ goto err;
+
+ page_offset = 0;
+ buffer += cur_count;
+ offset += cur_count;
+ count -= cur_count;
+ retval = eneispif_wait(bank);
+ if (retval != ERROR_OK)
+ goto err;
+ }
+
+err:
+ eneispif_write_reg(bank, ISPICFG, conf); /* restore */
+ return retval;
+}
+
+/* Return ID of flash device */
+/* On exit, SW mode is kept */
+static int eneispif_read_flash_id(struct flash_bank *bank, uint32_t *id)
+{
+ struct eneispif_flash_bank *eneispif_info = bank->driver_priv;
+ struct target *target = bank->target;
+ int retval;
+ uint32_t conf, value;
+ uint8_t buffer[4];
+
+ if (target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ retval = eneispif_read_reg(bank, &conf, ISPICFG);
+ if (retval != ERROR_OK)
+ return retval;
+
+ LOG_DEBUG("ISPCFG = (0x%08" PRIx32 ")", conf);
+
+ /* read ID from Receive Register */
+ eneispif_write_reg(bank, ISPICFG, CFG_WRITE); /* Cmmmand enable */
+ retval = eneispif_write_reg(bank, ISPICMD, (3 << 16) | SPIFLASH_READ_ID);
+ if (retval != ERROR_OK)
+ goto done;
+
+ retval = eneispif_wait(bank);
+ if (retval != ERROR_OK)
+ goto done;
+
+ retval = target_read_buffer(target, eneispif_info->ctrl_base + ISPIDAT, 3, buffer);
+ if (retval != ERROR_OK)
+ goto done;
+ value = (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
+ LOG_DEBUG("ISPDAT = (0x%08" PRIx32 ")", value);
+
+ *id = value;
+done:
+ eneispif_write_reg(bank, ISPICFG, conf); // restore
+ return retval;
+}
+
+static int eneispif_probe(struct flash_bank *bank)
+{
+ struct eneispif_flash_bank *eneispif_info = bank->driver_priv;
+ struct flash_sector *sectors;
+ uint32_t id;
+ int retval;
+ uint32_t sectorsize;
+
+ if (eneispif_info->probed)
+ free(bank->sectors);
+
+ eneispif_info->probed = false;
+
+ LOG_INFO("Assuming ISPI flash at address " TARGET_ADDR_FMT
+ " with controller at " TARGET_ADDR_FMT,
+ bank->base, eneispif_info->ctrl_base);
+
+ eneispif_write_reg(bank, ISPICFG, CFG_READ); /* RAM map enable */
+
+ retval = eneispif_read_flash_id(bank, &id);
+ if (retval != ERROR_OK)
+ return retval;
+
+ eneispif_info->dev_id = id;
+ eneispif_info->dev = &ene_flash_device;
+
+ LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")", eneispif_info->dev->name,
+ eneispif_info->dev_id);
+
+ /* Set correct size value */
+ bank->size = eneispif_info->dev->size_in_bytes;
+
+ if (bank->size <= (1UL << 16))
+ LOG_WARNING("device needs 2-byte addresses - not implemented");
+
+ /* if no sectors, treat whole bank as single sector */
+ sectorsize = eneispif_info->dev->sectorsize ? eneispif_info->dev->sectorsize
+ : eneispif_info->dev->size_in_bytes;
+
+ /* create and fill sectors array */
+ bank->num_sectors = eneispif_info->dev->size_in_bytes / sectorsize;
+ sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
+ if (!sectors) {
+ LOG_ERROR("not enough memory");
+ return ERROR_FAIL;
+ }
+
+ for (unsigned int sector = 0; sector < bank->num_sectors; sector++) {
+ sectors[sector].offset = sector * sectorsize;
+ sectors[sector].size = sectorsize;
+ sectors[sector].is_erased = -1;
+ sectors[sector].is_protected = 0;
+ }
+
+ bank->sectors = sectors;
+ eneispif_info->probed = true;
+ return ERROR_OK;
+}
+
+static int eneispif_auto_probe(struct flash_bank *bank)
+{
+ struct eneispif_flash_bank *eneispif_info = bank->driver_priv;
+ if (eneispif_info->probed)
+ return ERROR_OK;
+ return eneispif_probe(bank);
+}
+
+static int eneispif_protect_check(struct flash_bank *bank)
+{
+ /* Nothing to do. Protection is only handled in SW. */
+ return ERROR_OK;
+}
+
+static int get_eneispif_info(struct flash_bank *bank, struct command_invocation *cmd)
+{
+ struct eneispif_flash_bank *eneispif_info = bank->driver_priv;
+
+ if (!(eneispif_info->probed)) {
+ command_print(cmd, "ENE ISPI flash bank not probed yet.");
+ return ERROR_OK;
+ }
+
+ command_print(cmd,
+ "ENE ISPI flash information:\n"
+ " Device \'%s\' (ID 0x%08" PRIx32 ")",
+ eneispif_info->dev->name, eneispif_info->dev_id);
+
+ return ERROR_OK;
+}
+
+const struct flash_driver eneispif_flash = {
+ .name = "eneispif",
+ .usage = "flash bank <name> 'eneispif' <base_address> <size> 0 0 <target> <ctrl_base>",
+ .flash_bank_command = eneispif_flash_bank_command,
+ .erase = eneispif_erase,
+ .protect = eneispif_protect,
+ .write = eneispif_write,
+ .read = default_flash_read,
+ .probe = eneispif_probe,
+ .auto_probe = eneispif_auto_probe,
+ .erase_check = default_flash_blank_check,
+ .protect_check = eneispif_protect_check,
+ .info = get_eneispif_info,
+ .free_driver_priv = default_flash_free_driver_priv,
+};
-----------------------------------------------------------------------
Summary of changes:
doc/openocd.texi | 18 ++
src/flash/nor/Makefile.am | 1 +
src/flash/nor/driver.h | 1 +
src/flash/nor/drivers.c | 1 +
src/flash/nor/eneispif.c | 433 ++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 454 insertions(+)
create mode 100644 src/flash/nor/eneispif.c
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-03-24 13:42:56
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via a35e254c5383008cdacf7838a777f7f17af5eeb1 (commit)
from c02cf9404dc9dba2a6bc60c4db65c0287168a338 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit a35e254c5383008cdacf7838a777f7f17af5eeb1
Author: Tomas Vanek <va...@fb...>
Date: Fri Feb 16 17:17:05 2024 +0100
target/adi_v5_swd: move setting of do_reconnect one level up
Move setting of do_reconnect flag from swd_run_inner()
to swd_run(). Reconnect is not used at the inner level
and the flag had to be cleared after swd_run_inner()
to prevent recursion.
Signed-off-by: Tomas Vanek <va...@fb...>
Change-Id: Ib1de80bbdf10d1cbfb1dd351c6a5658e50d12af2
Reviewed-on: https://review.openocd.org/c/openocd/+/8155
Reviewed-by: Antonio Borneo <bor...@gm...>
Tested-by: jenkins
diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c
index 67706f35b..123100588 100644
--- a/src/target/adi_v5_swd.c
+++ b/src/target/adi_v5_swd.c
@@ -84,16 +84,8 @@ static void swd_clear_sticky_errors(struct adiv5_dap *dap)
static int swd_run_inner(struct adiv5_dap *dap)
{
const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
- int retval;
-
- retval = swd->run();
-
- if (retval != ERROR_OK) {
- /* fault response */
- dap->do_reconnect = true;
- }
- return retval;
+ return swd->run();
}
static inline int check_sync(struct adiv5_dap *dap)
@@ -288,15 +280,15 @@ static int swd_multidrop_select(struct adiv5_dap *dap)
swd_multidrop_selected_dap = NULL;
if (retry > 3) {
LOG_ERROR("Failed to select multidrop %s", adiv5_dap_name(dap));
+ dap->do_reconnect = true;
return retval;
}
LOG_DEBUG("Failed to select multidrop %s, retrying...",
adiv5_dap_name(dap));
- /* we going to retry localy, do not ask for full reconnect */
- dap->do_reconnect = false;
}
+ dap->do_reconnect = false;
return retval;
}
@@ -635,7 +627,13 @@ static int swd_run(struct adiv5_dap *dap)
swd_finish_read(dap);
- return swd_run_inner(dap);
+ retval = swd_run_inner(dap);
+ if (retval != ERROR_OK) {
+ /* fault response */
+ dap->do_reconnect = true;
+ }
+
+ return retval;
}
/** Put the SWJ-DP back to JTAG mode */
-----------------------------------------------------------------------
Summary of changes:
src/target/adi_v5_swd.c | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-03-24 13:41:32
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via c02cf9404dc9dba2a6bc60c4db65c0287168a338 (commit)
via a213afad09e50402be8d02298f48757ff4e2e1cf (commit)
from 35e4c4616f5a924313e85290f56f84f7a8534801 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit c02cf9404dc9dba2a6bc60c4db65c0287168a338
Author: Antonio Borneo <bor...@gm...>
Date: Sat Mar 9 18:12:36 2024 +0100
helper/list: include the correct header file
The file 'list.h', copied from FreeBSD, does not depend from any
OpenOCD specific include file, but only needs 'stddef.h' for the
type 'size_t'.
Let 'list.h' to include the correct header file, then fix the now
broken dependencies in the other files that were incorrectly
relying on 'list.h' to include 'helper/types.h'
Change-Id: Idd31b5bf607e226cac44ef41b2aa335ae4dbf519
Signed-off-by: Antonio Borneo <bor...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8173
Tested-by: jenkins
diff --git a/src/helper/binarybuffer.h b/src/helper/binarybuffer.h
index a8a5ef8f3..344629681 100644
--- a/src/helper/binarybuffer.h
+++ b/src/helper/binarybuffer.h
@@ -11,7 +11,8 @@
#ifndef OPENOCD_HELPER_BINARYBUFFER_H
#define OPENOCD_HELPER_BINARYBUFFER_H
-#include "list.h"
+#include <helper/list.h>
+#include <helper/types.h>
/** @file
* Support functions to access arbitrary bits in a byte array
diff --git a/src/helper/list.h b/src/helper/list.h
index eb8858e74..47290c260 100644
--- a/src/helper/list.h
+++ b/src/helper/list.h
@@ -35,7 +35,7 @@
/* begin OpenOCD changes */
-#include <helper/types.h>
+#include <stddef.h>
struct list_head {
struct list_head *next;
diff --git a/src/target/target.h b/src/target/target.h
index 1713448ce..d5c0e0e8c 100644
--- a/src/target/target.h
+++ b/src/target/target.h
@@ -23,6 +23,7 @@
#include <helper/list.h>
#include "helper/replacements.h"
#include "helper/system.h"
+#include <helper/types.h>
#include <jim.h>
struct reg;
commit a213afad09e50402be8d02298f48757ff4e2e1cf
Author: Antonio Borneo <bor...@gm...>
Date: Sat Mar 9 17:53:16 2024 +0100
helper/list: Replace Linux code with FreeBSD one
The file list.h was originally taken from the Linux kernel code,
thus under license GPL-2.0-only. This locks OpenOCD to follow the
same license, even if the majority of OpenOCD files are licensed
as GPL-2.0-or-later.
A similar file is also present in FreeBSD code base under the more
permissive license BSD-2-Clause.
Drop the code from Linux kernel and replace it with the code from
FreeBSD 13.3.0.
Adapt the code to OpenOCD coding style by fixing the majority of
issues identified by checkpatch.
Add the OpenOCD specific macros and comments.
Unfortunately this causes the lost of all the doxygen comments.
Checkpatch-ignore: MACRO_ARG_REUSE, MACRO_ARG_PRECEDENCE
Change-Id: I6d86752c50158f3174c4e8c4add81e9998d01e0e
Signed-off-by: Antonio Borneo <bor...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8172
Tested-by: jenkins
diff --git a/src/helper/list.h b/src/helper/list.h
index c9de0569b..eb8858e74 100644
--- a/src/helper/list.h
+++ b/src/helper/list.h
@@ -1,15 +1,31 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: BSD-2-Clause */
/*
- * The content of this file is mainly copied/inspired from Linux kernel
- * code in include/linux/list.h, include/linux/types.h
- * Last aligned with kernel v5.12:
- * - skip the functions hlist_unhashed_lockless() and __list_del_clearprev()
- * that are relevant only in kernel;
- * - Remove non-standard GCC extension "omitted conditional operand" from
- * list_prepare_entry;
- * - expand READ_ONCE, WRITE_ONCE, smp_load_acquire, smp_store_release;
- * - make comments compatible with doxygen.
+ * Copyright (c) 2010 Isilon Systems, Inc.
+ * Copyright (c) 2010 iX Systems, Inc.
+ * Copyright (c) 2010 Panasas, Inc.
+ * Copyright (c) 2013-2016 Mellanox Technologies, Ltd.
+ * Copyright (c) 2021-2024 by Antonio Borneo <bor...@gm...>
+ * All rights reserved.
+ */
+
+/*
+ * Circular doubly linked list implementation.
+ *
+ * The content of this file is mainly copied/inspired from FreeBSD code in:
+ * https://cgit.freebsd.org/src/tree/
+ * files:
+ * sys/compat/linuxkpi/common/include/linux/list.h
+ * sys/compat/linuxkpi/common/include/linux/types.h
+ *
+ * Last aligned with release/13.3.0:
+ *
+ * - Skip 'hlist_*' double linked lists with a single pointer list head.
+ * - Expand WRITE_ONCE().
+ * - Use TAB for indentation.
+ * - Put macro arguments within parenthesis.
+ * - Remove blank lines after an open brace '{'.
+ * - Remove multiple assignment.
*
* There is an example of using this file in contrib/list_example.c.
*/
@@ -17,155 +33,64 @@
#ifndef OPENOCD_HELPER_LIST_H
#define OPENOCD_HELPER_LIST_H
-/* begin local changes */
-#include <helper/types.h>
+/* begin OpenOCD changes */
-#define LIST_POISON1 NULL
-#define LIST_POISON2 NULL
+#include <helper/types.h>
struct list_head {
- struct list_head *next, *prev;
+ struct list_head *next;
+ struct list_head *prev;
};
-/* end local changes */
-
-/*
- * Circular doubly linked list implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
+/* end OpenOCD changes */
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
-/**
- * INIT_LIST_HEAD - Initialize a list_head structure
- * @param list list_head structure to be initialized.
- *
- * Initializes the list_head to point to itself. If it is a list header,
- * the result is an empty list.
- */
-static inline void INIT_LIST_HEAD(struct list_head *list)
+static inline void
+INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
-#ifdef CONFIG_DEBUG_LIST
-extern bool __list_add_valid(struct list_head *new,
- struct list_head *prev,
- struct list_head *next);
-extern bool __list_del_entry_valid(struct list_head *entry);
-#else
-static inline bool __list_add_valid(struct list_head *new,
- struct list_head *prev,
- struct list_head *next)
-{
- return true;
-}
-static inline bool __list_del_entry_valid(struct list_head *entry)
+static inline int
+list_empty(const struct list_head *head)
{
- return true;
+ return (head->next == head);
}
-#endif
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_add(struct list_head *new,
- struct list_head *prev,
- struct list_head *next)
-{
- if (!__list_add_valid(new, prev, next))
- return;
-
- next->prev = new;
- new->next = next;
- new->prev = prev;
- prev->next = new;
-}
-
-/**
- * list_add - add a new entry
- * @param new new entry to be added
- * @param head list head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-static inline void list_add(struct list_head *new, struct list_head *head)
+static inline int
+list_empty_careful(const struct list_head *head)
{
- __list_add(new, head, head->next);
-}
-
+ struct list_head *next = head->next;
-/**
- * list_add_tail - add a new entry
- * @param new new entry to be added
- * @param head list head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-static inline void list_add_tail(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head->prev, head);
+ return ((next == head) && (next == head->prev));
}
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_del(struct list_head *prev, struct list_head *next)
+static inline void
+__list_del(struct list_head *prev, struct list_head *next)
{
next->prev = prev;
prev->next = next;
}
-/* Ignore kernel __list_del_clearprev() */
-
-static inline void __list_del_entry(struct list_head *entry)
+static inline void
+__list_del_entry(struct list_head *entry)
{
- if (!__list_del_entry_valid(entry))
- return;
-
__list_del(entry->prev, entry->next);
}
-/**
- * list_del - deletes entry from list.
- * @param entry the element to delete from the list.
- * Note: list_empty() on entry does not return true after this, the entry is
- * in an undefined state.
- */
-static inline void list_del(struct list_head *entry)
+static inline void
+list_del(struct list_head *entry)
{
- __list_del_entry(entry);
- entry->next = LIST_POISON1;
- entry->prev = LIST_POISON2;
+ __list_del(entry->prev, entry->next);
}
-/**
- * list_replace - replace old entry by new one
- * @param old the element to be replaced
- * @param new the new element to insert
- *
- * If @a old was empty, it will be overwritten.
- */
-static inline void list_replace(struct list_head *old,
- struct list_head *new)
+static inline void
+list_replace(struct list_head *old, struct list_head *new)
{
new->next = old->next;
new->next->prev = new;
@@ -173,205 +98,189 @@ static inline void list_replace(struct list_head *old,
new->prev->next = new;
}
-/**
- * list_replace_init - replace old entry by new one and initialize the old one
- * @param old the element to be replaced
- * @param new the new element to insert
- *
- * If @a old was empty, it will be overwritten.
- */
-static inline void list_replace_init(struct list_head *old,
- struct list_head *new)
+static inline void
+list_replace_init(struct list_head *old, struct list_head *new)
{
list_replace(old, new);
INIT_LIST_HEAD(old);
}
-/**
- * list_swap - replace entry1 with entry2 and re-add entry1 at entry2's position
- * @param entry1 the location to place entry2
- * @param entry2 the location to place entry1
- */
-static inline void list_swap(struct list_head *entry1,
- struct list_head *entry2)
+static inline void
+linux_list_add(struct list_head *new, struct list_head *prev,
+ struct list_head *next)
{
- struct list_head *pos = entry2->prev;
-
- list_del(entry2);
- list_replace(entry1, entry2);
- if (pos == entry1)
- pos = entry2;
- list_add(entry1, pos);
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
}
-/**
- * list_del_init - deletes entry from list and reinitialize it.
- * @param entry the element to delete from the list.
- */
-static inline void list_del_init(struct list_head *entry)
+static inline void
+list_del_init(struct list_head *entry)
{
- __list_del_entry(entry);
+ list_del(entry);
INIT_LIST_HEAD(entry);
}
-/**
- * list_move - delete from one list and add as another's head
- * @param list the entry to move
- * @param head the head that will precede our entry
- */
-static inline void list_move(struct list_head *list, struct list_head *head)
+#define list_entry(ptr, type, field) container_of(ptr, type, field)
+
+#define list_first_entry(ptr, type, member) \
+ list_entry((ptr)->next, type, member)
+
+#define list_last_entry(ptr, type, member) \
+ list_entry((ptr)->prev, type, member)
+
+#define list_first_entry_or_null(ptr, type, member) \
+ (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
+
+#define list_next_entry(ptr, member) \
+ list_entry(((ptr)->member.next), typeof(*(ptr)), member)
+
+#define list_safe_reset_next(ptr, n, member) \
+ (n) = list_next_entry(ptr, member)
+
+#define list_prev_entry(ptr, member) \
+ list_entry(((ptr)->member.prev), typeof(*(ptr)), member)
+
+#define list_for_each(p, head) \
+ for (p = (head)->next; p != (head); p = (p)->next)
+
+#define list_for_each_safe(p, n, head) \
+ for (p = (head)->next, n = (p)->next; p != (head); p = n, n = (p)->next)
+
+#define list_for_each_entry(p, h, field) \
+ for (p = list_entry((h)->next, typeof(*p), field); &(p)->field != (h); \
+ p = list_entry((p)->field.next, typeof(*p), field))
+
+#define list_for_each_entry_safe(p, n, h, field) \
+ for (p = list_entry((h)->next, typeof(*p), field), \
+ n = list_entry((p)->field.next, typeof(*p), field); &(p)->field != (h);\
+ p = n, n = list_entry(n->field.next, typeof(*n), field))
+
+#define list_for_each_entry_from(p, h, field) \
+ for ( ; &(p)->field != (h); \
+ p = list_entry((p)->field.next, typeof(*p), field))
+
+#define list_for_each_entry_continue(p, h, field) \
+ for (p = list_next_entry((p), field); &(p)->field != (h); \
+ p = list_next_entry((p), field))
+
+#define list_for_each_entry_safe_from(pos, n, head, member) \
+ for (n = list_entry((pos)->member.next, typeof(*pos), member); \
+ &(pos)->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+#define list_for_each_entry_reverse(p, h, field) \
+ for (p = list_entry((h)->prev, typeof(*p), field); &(p)->field != (h); \
+ p = list_entry((p)->field.prev, typeof(*p), field))
+
+#define list_for_each_entry_safe_reverse(p, n, h, field) \
+ for (p = list_entry((h)->prev, typeof(*p), field), \
+ n = list_entry((p)->field.prev, typeof(*p), field); &(p)->field != (h); \
+ p = n, n = list_entry(n->field.prev, typeof(*n), field))
+
+#define list_for_each_entry_continue_reverse(p, h, field) \
+ for (p = list_entry((p)->field.prev, typeof(*p), field); &(p)->field != (h); \
+ p = list_entry((p)->field.prev, typeof(*p), field))
+
+#define list_for_each_prev(p, h) for (p = (h)->prev; p != (h); p = (p)->prev)
+
+#define list_for_each_entry_from_reverse(p, h, field) \
+ for (; &p->field != (h); \
+ p = list_prev_entry(p, field))
+
+static inline void
+list_add(struct list_head *new, struct list_head *head)
{
- __list_del_entry(list);
- list_add(list, head);
+ linux_list_add(new, head, head->next);
}
-/**
- * list_move_tail - delete from one list and add as another's tail
- * @param list the entry to move
- * @param head the head that will follow our entry
- */
-static inline void list_move_tail(struct list_head *list,
- struct list_head *head)
+static inline void
+list_add_tail(struct list_head *new, struct list_head *head)
{
- __list_del_entry(list);
- list_add_tail(list, head);
+ linux_list_add(new, head->prev, head);
}
-/**
- * list_bulk_move_tail - move a subsection of a list to its tail
- * @param head the head that will follow our entry
- * @param first the first entry to move
- * @param last the last entry to move, can be the same as first
- *
- * Move all entries between @a first and including @a last before @a head.
- * All three entries must belong to the same linked list.
- */
-static inline void list_bulk_move_tail(struct list_head *head,
- struct list_head *first,
- struct list_head *last)
+static inline void
+list_move(struct list_head *list, struct list_head *head)
{
- first->prev->next = last->next;
- last->next->prev = first->prev;
-
- head->prev->next = first;
- first->prev = head->prev;
-
- last->next = head;
- head->prev = last;
+ list_del(list);
+ list_add(list, head);
}
-/**
- * list_is_first -- tests whether @a list is the first entry in list @a head
- * @param list the entry to test
- * @param head the head of the list
- */
-static inline int list_is_first(const struct list_head *list, const struct list_head *head)
+static inline void
+list_move_tail(struct list_head *entry, struct list_head *head)
{
- return list->prev == head;
+ list_del(entry);
+ list_add_tail(entry, head);
}
-/**
- * list_is_last - tests whether @a list is the last entry in list @a head
- * @param list the entry to test
- * @param head the head of the list
- */
-static inline int list_is_last(const struct list_head *list, const struct list_head *head)
+static inline void
+list_rotate_to_front(struct list_head *entry, struct list_head *head)
{
- return list->next == head;
+ list_move_tail(entry, head);
}
-/**
- * list_is_head - tests whether @a list is the list @a head
- * @param list the entry to test
- * @param head the head of the list
- */
-static inline int list_is_head(const struct list_head *list, const struct list_head *head)
+static inline void
+list_bulk_move_tail(struct list_head *head, struct list_head *first,
+ struct list_head *last)
{
- return list == head;
+ first->prev->next = last->next;
+ last->next->prev = first->prev;
+ head->prev->next = first;
+ first->prev = head->prev;
+ last->next = head;
+ head->prev = last;
}
-/**
- * list_empty - tests whether a list is empty
- * @param head the list to test.
- */
-static inline int list_empty(const struct list_head *head)
+static inline void
+linux_list_splice(const struct list_head *list, struct list_head *prev,
+ struct list_head *next)
{
- return head->next == head;
+ struct list_head *first;
+ struct list_head *last;
+
+ if (list_empty(list))
+ return;
+ first = list->next;
+ last = list->prev;
+ first->prev = prev;
+ prev->next = first;
+ last->next = next;
+ next->prev = last;
}
-/**
- * list_del_init_careful - deletes entry from list and reinitialize it.
- * @param entry the element to delete from the list.
- *
- * This is the same as list_del_init(), except designed to be used
- * together with list_empty_careful() in a way to guarantee ordering
- * of other memory operations.
- *
- * Any memory operations done before a list_del_init_careful() are
- * guaranteed to be visible after a list_empty_careful() test.
- */
-static inline void list_del_init_careful(struct list_head *entry)
+static inline void
+list_splice(const struct list_head *list, struct list_head *head)
{
- __list_del_entry(entry);
- entry->prev = entry;
- entry->next = entry;
+ linux_list_splice(list, head, head->next);
}
-/**
- * list_empty_careful - tests whether a list is empty and not being modified
- * @param head the list to test
- *
- * Description:
- * tests whether a list is empty _and_ checks that no other CPU might be
- * in the process of modifying either member (next or prev)
- *
- * NOTE: using list_empty_careful() without synchronization
- * can only be safe if the only activity that can happen
- * to the list entry is list_del_init(). Eg. it cannot be used
- * if another CPU could re-list_add() it.
- */
-static inline int list_empty_careful(const struct list_head *head)
+static inline void
+list_splice_tail(struct list_head *list, struct list_head *head)
{
- struct list_head *next = head->next;
- return (next == head) && (next == head->prev);
+ linux_list_splice(list, head->prev, head);
}
-/**
- * list_rotate_left - rotate the list to the left
- * @param head the head of the list
- */
-static inline void list_rotate_left(struct list_head *head)
+static inline void
+list_splice_init(struct list_head *list, struct list_head *head)
{
- struct list_head *first;
-
- if (!list_empty(head)) {
- first = head->next;
- list_move_tail(first, head);
- }
+ linux_list_splice(list, head, head->next);
+ INIT_LIST_HEAD(list);
}
-/**
- * list_rotate_to_front() - Rotate list to specific item.
- * @param list The desired new front of the list.
- * @param head The head of the list.
- *
- * Rotates list so that @a list becomes the new front of the list.
- */
-static inline void list_rotate_to_front(struct list_head *list,
- struct list_head *head)
+static inline void
+list_splice_tail_init(struct list_head *list, struct list_head *head)
{
- /*
- * Deletes the list head from the list denoted by @a head and
- * places it as the tail of @a list, this effectively rotates the
- * list so that @a list is at the front.
- */
- list_move_tail(head, list);
+ linux_list_splice(list, head->prev, head);
+ INIT_LIST_HEAD(list);
}
-/**
- * list_is_singular - tests whether a list has just one entry.
- * @param head the list to test.
+/*
+ * Double linked lists with a single pointer list head.
+ * IGNORED
*/
+
static inline int list_is_singular(const struct list_head *head)
{
return !list_empty(head) && (head->next == head->prev);
@@ -389,472 +298,79 @@ static inline void __list_cut_position(struct list_head *list,
new_first->prev = head;
}
-/**
- * list_cut_position - cut a list into two
- * @param list a new list to add all removed entries
- * @param head a list with entries
- * @param entry an entry within head, could be the head itself
- * and if so we won't cut the list
- *
- * This helper moves the initial part of @a head, up to and
- * including @a entry, from @a head to @a list. You should
- * pass on @a entry an element you know is on @a head. @a list
- * should be an empty list or a list you do not care about
- * losing its data.
- *
- */
static inline void list_cut_position(struct list_head *list,
struct list_head *head, struct list_head *entry)
{
if (list_empty(head))
return;
- if (list_is_singular(head) && !list_is_head(entry, head) && (entry != head->next))
+ if (list_is_singular(head) &&
+ (head->next != entry && head != entry))
return;
- if (list_is_head(entry, head))
+ if (entry == head)
INIT_LIST_HEAD(list);
else
__list_cut_position(list, head, entry);
}
-/**
- * list_cut_before - cut a list into two, before given entry
- * @param list a new list to add all removed entries
- * @param head a list with entries
- * @param entry an entry within head, could be the head itself
- *
- * This helper moves the initial part of @a head, up to but
- * excluding @a entry, from @a head to @a list. You should pass
- * in @a entry an element you know is on @a head. @a list should
- * be an empty list or a list you do not care about losing
- * its data.
- * If @a entry == @a head, all entries on @a head are moved to
- * @a list.
- */
-static inline void list_cut_before(struct list_head *list,
- struct list_head *head,
- struct list_head *entry)
+static inline int list_is_first(const struct list_head *list,
+ const struct list_head *head)
{
- if (head->next == entry) {
- INIT_LIST_HEAD(list);
- return;
- }
- list->next = head->next;
- list->next->prev = list;
- list->prev = entry->prev;
- list->prev->next = list;
- head->next = entry;
- entry->prev = head;
+ return (list->prev == head);
}
-static inline void __list_splice(const struct list_head *list,
- struct list_head *prev,
- struct list_head *next)
+static inline int list_is_last(const struct list_head *list,
+ const struct list_head *head)
{
- struct list_head *first = list->next;
- struct list_head *last = list->prev;
-
- first->prev = prev;
- prev->next = first;
-
- last->next = next;
- next->prev = last;
-}
-
-/**
- * list_splice - join two lists, this is designed for stacks
- * @param list the new list to add.
- * @param head the place to add it in the first list.
- */
-static inline void list_splice(const struct list_head *list,
- struct list_head *head)
-{
- if (!list_empty(list))
- __list_splice(list, head, head->next);
+ return list->next == head;
}
-/**
- * list_splice_tail - join two lists, each list being a queue
- * @param list the new list to add.
- * @param head the place to add it in the first list.
- */
-static inline void list_splice_tail(struct list_head *list,
- struct list_head *head)
+static inline size_t
+list_count_nodes(const struct list_head *list)
{
- if (!list_empty(list))
- __list_splice(list, head->prev, head);
-}
+ const struct list_head *lh;
+ size_t count;
-/**
- * list_splice_init - join two lists and reinitialise the emptied list.
- * @param list the new list to add.
- * @param head the place to add it in the first list.
- *
- * The list at @a list is reinitialised
- */
-static inline void list_splice_init(struct list_head *list,
- struct list_head *head)
-{
- if (!list_empty(list)) {
- __list_splice(list, head, head->next);
- INIT_LIST_HEAD(list);
+ count = 0;
+ list_for_each(lh, list) {
+ count++;
}
-}
-/**
- * list_splice_tail_init - join two lists and reinitialise the emptied list
- * @param list the new list to add.
- * @param head the place to add it in the first list.
- *
- * Each of the lists is a queue.
- * The list at @a list is reinitialised
- */
-static inline void list_splice_tail_init(struct list_head *list,
- struct list_head *head)
-{
- if (!list_empty(list)) {
- __list_splice(list, head->prev, head);
- INIT_LIST_HEAD(list);
- }
+ return (count);
}
-/**
- * list_entry - get the struct for this entry
- * @param ptr the &struct list_head pointer.
- * @param type the type of the struct this is embedded in.
- * @param member the name of the list_head within the struct.
- */
-#define list_entry(ptr, type, member) \
- container_of(ptr, type, member)
-
-/**
- * list_first_entry - get the first element from a list
- * @param ptr the list head to take the element from.
- * @param type the type of the struct this is embedded in.
- * @param member the name of the list_head within the struct.
- *
- * Note, that list is expected to be not empty.
- */
-#define list_first_entry(ptr, type, member) \
- list_entry((ptr)->next, type, member)
-
-/**
- * list_last_entry - get the last element from a list
- * @param ptr the list head to take the element from.
- * @param type the type of the struct this is embedded in.
- * @param member the name of the list_head within the struct.
- *
- * Note, that list is expected to be not empty.
- */
-#define list_last_entry(ptr, type, member) \
- list_entry((ptr)->prev, type, member)
-
-/**
- * list_first_entry_or_null - get the first element from a list
- * @param ptr the list head to take the element from.
- * @param type the type of the struct this is embedded in.
- * @param member the name of the list_head within the struct.
- *
- * Note that if the list is empty, it returns NULL.
- */
-#define list_first_entry_or_null(ptr, type, member) ({ \
- struct list_head *head__ = (ptr); \
- struct list_head *pos__ = head__->next; \
- pos__ != head__ ? list_entry(pos__, type, member) : NULL; \
-})
-
-/**
- * list_next_entry - get the next element in list
- * @param pos the type * to cursor
- * @param member the name of the list_head within the struct.
- */
-#define list_next_entry(pos, member) \
- list_entry((pos)->member.next, typeof(*(pos)), member)
-
-/**
- * list_next_entry_circular - get the next element in list
- * @param pos the type * to cursor.
- * @param head the list head to take the element from.
- * @param member the name of the list_head within the struct.
- *
- * Wraparound if pos is the last element (return the first element).
- * Note, that list is expected to be not empty.
- */
-#define list_next_entry_circular(pos, head, member) \
- (list_is_last(&(pos)->member, head) ? \
- list_first_entry(head, typeof(*(pos)), member) : list_next_entry(pos, member))
-
-/**
- * list_prev_entry - get the prev element in list
- * @param pos the type * to cursor
- * @param member the name of the list_head within the struct.
- */
-#define list_prev_entry(pos, member) \
- list_entry((pos)->member.prev, typeof(*(pos)), member)
-
-/**
- * list_prev_entry_circular - get the prev element in list
- * @param pos the type * to cursor.
- * @param head the list head to take the element from.
- * @param member the name of the list_head within the struct.
- *
- * Wraparound if pos is the first element (return the last element).
- * Note, that list is expected to be not empty.
- */
-#define list_prev_entry_circular(pos, head, member) \
- (list_is_first(&(pos)->member, head) ? \
- list_last_entry(head, typeof(*(pos)), member) : list_prev_entry(pos, member))
-
-/**
- * list_for_each - iterate over a list
- * @param pos the &struct list_head to use as a loop cursor.
- * @param head the head for your list.
- */
-#define list_for_each(pos, head) \
- for (pos = (head)->next; !list_is_head(pos, (head)); pos = pos->next)
-
-/* Ignore kernel list_for_each_rcu() */
-
-/**
- * list_for_each_continue - continue iteration over a list
- * @param pos the &struct list_head to use as a loop cursor.
- * @param head the head for your list.
- *
- * Continue to iterate over a list, continuing after the current position.
+/*
+ * Double linked lists with a single pointer list head.
+ * IGNORED
*/
-#define list_for_each_continue(pos, head) \
- for (pos = pos->next; pos != (head); pos = pos->next)
-/**
- * list_for_each_prev - iterate over a list backwards
- * @param pos the &struct list_head to use as a loop cursor.
- * @param head the head for your list.
- */
-#define list_for_each_prev(pos, head) \
- for (pos = (head)->prev; pos != (head); pos = pos->prev)
+/* begin OpenOCD extensions */
/**
- * list_for_each_safe - iterate over a list safe against removal of list entry
- * @param pos the &struct list_head to use as a loop cursor.
- * @param n another &struct list_head to use as temporary storage
- * @param head the head for your list.
- */
-#define list_for_each_safe(pos, n, head) \
- for (pos = (head)->next, n = pos->next; pos != (head); \
- pos = n, n = pos->next)
-
-/**
- * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
- * @param pos the &struct list_head to use as a loop cursor.
- * @param n another &struct list_head to use as temporary storage
- * @param head the head for your list.
+ * list_for_each_entry_direction - iterate forward/backward over list of given type
+ * @param is_fwd the iterate direction, true for forward, false for backward.
+ * @param p the type * to use as a loop cursor.
+ * @param h the head of the list.
+ * @param field the name of the list_head within the struct.
*/
-#define list_for_each_prev_safe(pos, n, head) \
- for (pos = (head)->prev, n = pos->prev; \
- pos != (head); \
- pos = n, n = pos->prev)
+#define list_for_each_entry_direction(is_fwd, p, h, field) \
+ for (p = list_entry(is_fwd ? (h)->next : (h)->prev, typeof(*p), field); \
+ &(p)->field != (h); \
+ p = list_entry(is_fwd ? (p)->field.next : (p)->field.prev, typeof(*p), field))
/**
- * list_count_nodes - count nodes in the list
- * @param head the head for your list.
+ * list_rotate_left - rotate the list to the left
+ * @param h the head of the list
*/
-static inline size_t list_count_nodes(struct list_head *head)
+static inline void list_rotate_left(struct list_head *h)
{
- struct list_head *pos;
- size_t count = 0;
-
- list_for_each(pos, head)
- count++;
+ struct list_head *first;
- return count;
+ if (!list_empty(h)) {
+ first = h->next;
+ list_move_tail(first, h);
+ }
}
-/**
- * list_entry_is_head - test if the entry points to the head of the list
- * @param pos the type * to cursor
- * @param head the head for your list.
- * @param member the name of the list_head within the struct.
- */
-#define list_entry_is_head(pos, head, member) \
- (&pos->member == (head))
-
-/**
- * list_for_each_entry - iterate over list of given type
- * @param pos the type * to use as a loop cursor.
- * @param head the head for your list.
- * @param member the name of the list_head within the struct.
- */
-#define list_for_each_entry(pos, head, member) \
- for (pos = list_first_entry(head, typeof(*pos), member); \
- !list_entry_is_head(pos, head, member); \
- pos = list_next_entry(pos, member))
-
-/**
- * list_for_each_entry_reverse - iterate backwards over list of given type.
- * @param pos the type * to use as a loop cursor.
- * @param head the head for your list.
- * @param member the name of the list_head within the struct.
- */
-#define list_for_each_entry_reverse(pos, head, member) \
- for (pos = list_last_entry(head, typeof(*pos), member); \
- !list_entry_is_head(pos, head, member); \
- pos = list_prev_entry(pos, member))
-
-/**
- * list_for_each_entry_direction - iterate forward/backward over list of given type
- * @param forward the iterate direction, true for forward, false for backward.
- * @param pos the type * to use as a loop cursor.
- * @param head the head for your list.
- * @param member the name of the list_head within the struct.
- */
-#define list_for_each_entry_direction(forward, pos, head, member) \
- for (pos = forward ? list_first_entry(head, typeof(*pos), member) \
- : list_last_entry(head, typeof(*pos), member); \
- !list_entry_is_head(pos, head, member); \
- pos = forward ? list_next_entry(pos, member) \
- : list_prev_entry(pos, member))
-
-/**
- * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
- * @param pos the type * to use as a start point
- * @param head the head of the list
- * @param member the name of the list_head within the struct.
- *
- * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
- */
-#define list_prepare_entry(pos, head, member) \
- ((pos) ? (pos) : list_entry(head, typeof(*pos), member))
-
-/**
- * list_for_each_entry_continue - continue iteration over list of given type
- * @param pos the type * to use as a loop cursor.
- * @param head the head for your list.
- * @param member the name of the list_head within the struct.
- *
- * Continue to iterate over list of given type, continuing after
- * the current position.
- */
-#define list_for_each_entry_continue(pos, head, member) \
- for (pos = list_next_entry(pos, member); \
- !list_entry_is_head(pos, head, member); \
- pos = list_next_entry(pos, member))
-
-/**
- * list_for_each_entry_continue_reverse - iterate backwards from the given point
- * @param pos the type * to use as a loop cursor.
- * @param head the head for your list.
- * @param member the name of the list_head within the struct.
- *
- * Start to iterate over list of given type backwards, continuing after
- * the current position.
- */
-#define list_for_each_entry_continue_reverse(pos, head, member) \
- for (pos = list_prev_entry(pos, member); \
- !list_entry_is_head(pos, head, member); \
- pos = list_prev_entry(pos, member))
-
-/**
- * list_for_each_entry_from - iterate over list of given type from the current point
- * @param pos the type * to use as a loop cursor.
- * @param head the head for your list.
- * @param member the name of the list_head within the struct.
- *
- * Iterate over list of given type, continuing from current position.
- */
-#define list_for_each_entry_from(pos, head, member) \
- for (; !list_entry_is_head(pos, head, member); \
- pos = list_next_entry(pos, member))
-
-/**
- * list_for_each_entry_from_reverse - iterate backwards over list of given type
- * from the current point
- * @param pos the type * to use as a loop cursor.
- * @param head the head for your list.
- * @param member the name of the list_head within the struct.
- *
- * Iterate backwards over list of given type, continuing from current position.
- */
-#define list_for_each_entry_from_reverse(pos, head, member) \
- for (; !list_entry_is_head(pos, head, member); \
- pos = list_prev_entry(pos, member))
-
-/**
- * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @param pos the type * to use as a loop cursor.
- * @param n another type * to use as temporary storage
- * @param head the head for your list.
- * @param member the name of the list_head within the struct.
- */
-#define list_for_each_entry_safe(pos, n, head, member) \
- for (pos = list_first_entry(head, typeof(*pos), member), \
- n = list_next_entry(pos, member); \
- !list_entry_is_head(pos, head, member); \
- pos = n, n = list_next_entry(n, member))
-
-/**
- * list_for_each_entry_safe_continue - continue list iteration safe against removal
- * @param pos the type * to use as a loop cursor.
- * @param n another type * to use as temporary storage
- * @param head the head for your list.
- * @param member the name of the list_head within the struct.
- *
- * Iterate over list of given type, continuing after current point,
- * safe against removal of list entry.
- */
-#define list_for_each_entry_safe_continue(pos, n, head, member) \
- for (pos = list_next_entry(pos, member), \
- n = list_next_entry(pos, member); \
- !list_entry_is_head(pos, head, member); \
- pos = n, n = list_next_entry(n, member))
-
-/**
- * list_for_each_entry_safe_from - iterate over list from current point safe against removal
- * @param pos the type * to use as a loop cursor.
- * @param n another type * to use as temporary storage
- * @param head the head for your list.
- * @param member the name of the list_head within the struct.
- *
- * Iterate over list of given type from current point, safe against
- * removal of list entry.
- */
-#define list_for_each_entry_safe_from(pos, n, head, member) \
- for (n = list_next_entry(pos, member); \
- !list_entry_is_head(pos, head, member); \
- pos = n, n = list_next_entry(n, member))
-
-/**
- * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
- * @param pos the type * to use as a loop cursor.
- * @param n another type * to use as temporary storage
- * @param head the head for your list.
- * @param member the name of the list_head within the struct.
- *
- * Iterate backwards over list of given type, safe against removal
- * of list entry.
- */
-#define list_for_each_entry_safe_reverse(pos, n, head, member) \
- for (pos = list_last_entry(head, typeof(*pos), member), \
- n = list_prev_entry(pos, member); \
- !list_entry_is_head(pos, head, member); \
- pos = n, n = list_prev_entry(n, member))
-
-/**
- * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
- * @param pos the loop cursor used in the list_for_each_entry_safe loop
- * @param n temporary storage used in list_for_each_entry_safe
- * @param member the name of the list_head within the struct.
- *
- * list_safe_reset_next is not safe to use in general if the list may be
- * modified concurrently (eg. the lock is dropped in the loop body). An
- * exception to this is if the cursor element (pos) is pinned in the list,
- * and list_safe_reset_next is called after re-taking the lock and before
- * completing the current iteration of the loop body.
- */
-#define list_safe_reset_next(pos, n, member) \
- n = list_next_entry(pos, member)
-
-/*
- * Double linked lists with a single pointer list head.
- * IGNORED
- */
+/* end OpenOCD extensions */
#endif /* OPENOCD_HELPER_LIST_H */
-----------------------------------------------------------------------
Summary of changes:
src/helper/binarybuffer.h | 3 +-
src/helper/list.h | 934 +++++++++++-----------------------------------
src/target/target.h | 1 +
3 files changed, 228 insertions(+), 710 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-03-24 13:40:44
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 35e4c4616f5a924313e85290f56f84f7a8534801 (commit)
via 0c0243228cb958b7c12c2e5a81c84d35734fce25 (commit)
from 01a797af143398c6f3aa1eb6f8949deff4ccf044 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 35e4c4616f5a924313e85290f56f84f7a8534801
Author: Antonio Borneo <bor...@gm...>
Date: Sun Feb 25 23:03:27 2024 +0100
gdb_server: drop useless check in gdb_keep_client_alive()
OpenOCD can send it's log to gdb, and gdb replies with 'OK'.
Calls to LOG_XXX() are also present in the code that communicates
with gdb. This can cause infinite nested calls.
OpenOCD uses the flag 'gdb_con->busy' to protect the communication
with gdb and prevent nested calls.
There is no reason to check for 'gdb_con->busy' in the code for
keep-alive, as keep_alive() is never called in this gdb server;
the flag would eventually be set if the current keep_alive() will
send something to gdb.
Drop the flag 'gdb_con->busy' in gdb_keep_client_alive().
While there, document the use of 'gdb_con->busy'.
Change-Id: I1ea20bf96abb5d2f1fcdba1e3861df257c396bb6
Signed-off-by: Antonio Borneo <bor...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8166
Tested-by: jenkins
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index 00e43cfe9..c1ee4aa2a 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -73,6 +73,8 @@ struct gdb_connection {
enum target_state frontend_state;
struct image *vflash_image;
bool closed;
+ /* set to prevent re-entrance from log messages during gdb_get_packet()
+ * and gdb_put_packet(). */
bool busy;
int noack_mode;
/* set flag to true if you want the next stepi to return immediately.
@@ -3794,11 +3796,6 @@ static void gdb_keep_client_alive(struct connection *connection)
{
struct gdb_connection *gdb_con = connection->priv;
- if (gdb_con->busy) {
- /* do not send packets, retry asap */
- return;
- }
-
switch (gdb_con->output_flag) {
case GDB_OUTPUT_NO:
/* no need for keep-alive */
commit 0c0243228cb958b7c12c2e5a81c84d35734fce25
Author: Antonio Borneo <bor...@gm...>
Date: Sun Feb 25 22:55:35 2024 +0100
gdb_server: add async-notif keep-alive during memory read/write
To avoid gdb to timeout, OpenOCD implements a keep-alive mechanism
that consists in sending periodically to gdb empty strings embedded
in the "O" remote reply packet.
The main purpose of "O" packets is to forward in the gdb console
the output of the remote execution; the gdb-remote puts in the "O"
packet the string that gdb will print. It's use is restricted to
few "running/execution" contexts listed in
http://sourceware.org/gdb/onlinedocs/gdb/Stop-Reply-Packets.html
and this currently limits the keep-alive capabilities of OpenOCD.
Long data transfer (memory R/W) can also cause gdb to timeout if
the interface is too slow. In this case the usual keep-alive based
on "O" packet cannot be used and, if used, would trigger a protocol
error that causes the transfer to be dropped.
The slow transfer rate can be simulated by adding some delay in the
main loop of mem_ap_write() and mem_ap_read(), then using the gdb
commands "dump" and "restore".
In the wait loop during a memory R/W, gdb drops any extra character
received from the gdb-remote that is not recognized as a valid
reply to the memory command. Every dropped character re-initializes
the timeout counter and could be used as keep-alive.
From gdb 7.0 (released 2009-10-06), an asynchronous notification
can also be received from gdb-remote during a memory R/W and has
the effect to reset the timeout counter, thus can be used as
keep-alive.
The notification would be treated as "junk" extra characters by any
gdb older than 7.0, being still valid as keep-alive.
Check putpkt_binary() and getpkt_sane() in gdb commit
74531fed1f2d662debc2c209b8b3faddceb55960
Currently, only one notification packet ("Stop") is recognized by
gdb, and gdb documentation reports that notification packets that
are not recognized should be silently dropped.
Use 'set debug remote 1' in gdb to dump the received notifications
and the junk extra characters.
Add a new level in enum gdb_output_flag for using the asynchronous
notifications.
Activate this new level during memory transfers.
Send a custom "oocd_keepalive" notification packet as keep_alive.
While there, drop a useless return in the switch/case, already
managed in case of break.
After this commit, the proper calls to keep_alive() have to be
added in the loops that code the memory transfers. Of course, the
keep_alive() should be placed during the wait for JTAG flush, not
while locally queuing the JTAG elementary transfers.
Change-Id: I9ca8e78630611597d15984bd0e8634c8fc3c32b9
Signed-off-by: Antonio Borneo <bor...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8165
Tested-by: jenkins
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index ae288de1c..00e43cfe9 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -53,6 +53,8 @@
enum gdb_output_flag {
/* GDB doesn't accept 'O' packets */
GDB_OUTPUT_NO,
+ /* GDB doesn't accept 'O' packets but accepts notifications */
+ GDB_OUTPUT_NOTIF,
/* GDB accepts 'O' packets */
GDB_OUTPUT_ALL,
};
@@ -1486,9 +1488,6 @@ static int gdb_error(struct connection *connection, int retval)
return ERROR_OK;
}
-/* We don't have to worry about the default 2 second timeout for GDB packets,
- * because GDB breaks up large memory reads into smaller reads.
- */
static int gdb_read_memory_packet(struct connection *connection,
char const *packet, int packet_size)
{
@@ -3477,7 +3476,7 @@ static void gdb_log_callback(void *priv, const char *file, unsigned line,
struct connection *connection = priv;
struct gdb_connection *gdb_con = connection->priv;
- if (gdb_con->output_flag == GDB_OUTPUT_NO)
+ if (gdb_con->output_flag != GDB_OUTPUT_ALL)
/* No out allowed */
return;
@@ -3562,10 +3561,14 @@ static int gdb_input_inner(struct connection *connection)
retval = gdb_set_register_packet(connection, packet, packet_size);
break;
case 'm':
+ gdb_con->output_flag = GDB_OUTPUT_NOTIF;
retval = gdb_read_memory_packet(connection, packet, packet_size);
+ gdb_con->output_flag = GDB_OUTPUT_NO;
break;
case 'M':
+ gdb_con->output_flag = GDB_OUTPUT_NOTIF;
retval = gdb_write_memory_packet(connection, packet, packet_size);
+ gdb_con->output_flag = GDB_OUTPUT_NO;
break;
case 'z':
case 'Z':
@@ -3656,9 +3659,9 @@ static int gdb_input_inner(struct connection *connection)
retval = gdb_detach(connection);
break;
case 'X':
+ gdb_con->output_flag = GDB_OUTPUT_NOTIF;
retval = gdb_write_memory_binary_packet(connection, packet, packet_size);
- if (retval != ERROR_OK)
- return retval;
+ gdb_con->output_flag = GDB_OUTPUT_NO;
break;
case 'k':
if (gdb_con->extended_protocol) {
@@ -3754,6 +3757,39 @@ static int gdb_input(struct connection *connection)
return ERROR_OK;
}
+/*
+ * Send custom notification packet as keep-alive during memory read/write.
+ *
+ * From gdb 7.0 (released 2009-10-06) an unknown notification received during
+ * memory read/write would be silently dropped.
+ * Before gdb 7.0 any character, with exclusion of "+-$", would be considered
+ * as junk and ignored.
+ * In both cases the reception will reset the timeout counter in gdb, thus
+ * working as a keep-alive.
+ * Check putpkt_binary() and getpkt_sane() in gdb commit
+ * 74531fed1f2d662debc2c209b8b3faddceb55960
+ *
+ * Enable remote debug in gdb with 'set debug remote 1' to either dump the junk
+ * characters in gdb pre-7.0 and the notification from gdb 7.0.
+ */
+static void gdb_async_notif(struct connection *connection)
+{
+ static unsigned char count;
+ unsigned char checksum = 0;
+ char buf[22];
+
+ int len = sprintf(buf, "%%oocd_keepalive:%2.2x", count++);
+ for (int i = 1; i < len; i++)
+ checksum += buf[i];
+ len += sprintf(buf + len, "#%2.2x", checksum);
+
+#ifdef _DEBUG_GDB_IO_
+ LOG_DEBUG("sending packet '%s'", buf);
+#endif
+
+ gdb_write(connection, buf, len);
+}
+
static void gdb_keep_client_alive(struct connection *connection)
{
struct gdb_connection *gdb_con = connection->priv;
@@ -3767,6 +3803,10 @@ static void gdb_keep_client_alive(struct connection *connection)
case GDB_OUTPUT_NO:
/* no need for keep-alive */
break;
+ case GDB_OUTPUT_NOTIF:
+ /* send asynchronous notification */
+ gdb_async_notif(connection);
+ break;
case GDB_OUTPUT_ALL:
/* send an empty O packet */
gdb_output_con(connection, "");
-----------------------------------------------------------------------
Summary of changes:
src/server/gdb_server.c | 59 ++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 48 insertions(+), 11 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-03-16 14:47:43
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 01a797af143398c6f3aa1eb6f8949deff4ccf044 (commit)
from a88db9b1211ea71b5795b91d11d94fb0f37cc905 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 01a797af143398c6f3aa1eb6f8949deff4ccf044
Author: Walter Ji <wal...@os...>
Date: Fri Nov 17 16:46:55 2023 +0800
target/mips32: add fpu access support
Add access to fpr and cp1 registers.
GDB can now check the FPRs with `info reg f` and change them.
Checkpatch-ignore: MACRO_ARG_REUSE
Change-Id: I63896ab6f6737054d8108db105a13a58e1446fbc
Signed-off-by: Walter Ji <wal...@os...>
Reviewed-on: https://review.openocd.org/c/openocd/+/7866
Tested-by: jenkins
Reviewed-by: Oleksij Rempel <li...@re...>
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/src/target/mips32.c b/src/target/mips32.c
index ec2bfb7d0..6bbf71bd8 100644
--- a/src/target/mips32.c
+++ b/src/target/mips32.c
@@ -262,6 +262,61 @@ static int mips32_set_core_reg(struct reg *reg, uint8_t *buf)
return ERROR_OK;
}
+/**
+ * mips32_set_all_fpr_width - Set the width of all floating-point registers
+ * @param[in] mips32: MIPS32 common structure
+ * @param[in] fp64: Flag indicating whether to set the width to 64 bits (double precision)
+ *
+ * @brief Sets the width of all floating-point registers based on the specified flag.
+ */
+static void mips32_set_all_fpr_width(struct mips32_common *mips32, bool fp64)
+{
+ struct reg_cache *cache = mips32->core_cache;
+ struct reg *reg_list = cache->reg_list;
+ int i;
+
+ for (i = MIPS32_REGLIST_FP_INDEX; i < (MIPS32_REGLIST_FP_INDEX + MIPS32_REG_FP_COUNT); i++) {
+ reg_list[i].size = fp64 ? 64 : 32;
+ reg_list[i].reg_data_type->type = fp64 ? REG_TYPE_IEEE_DOUBLE : REG_TYPE_IEEE_SINGLE;
+ }
+}
+
+/**
+ * mips32_detect_fpr_mode_change - Detect changes in floating-point register mode
+ * @param[in] mips32: MIPS32 common structure
+ * @param[in] cp0_status: Value of the CP0 status register
+ *
+ * @brief Detects changes in the floating-point register mode based on the CP0 status register.
+ * If changes are detected, it updates the internal state
+ * and logs a warning message indicating the mode change.
+ */
+static void mips32_detect_fpr_mode_change(struct mips32_common *mips32, uint32_t cp0_status)
+{
+ if (!mips32->fp_imp)
+ return;
+
+ /* CP0.Status.FR indicates the working mode of floating-point register.
+ * When FP = 0, fpr can contain any 32bit data type,
+ * 64bit data types are stored in even-odd register pairs.
+ * When FP = 1, fpr can contain any data types.*/
+ bool fpu_in_64bit = ((cp0_status & BIT(MIPS32_CP0_STATUS_FR_SHIFT)) != 0);
+
+ /* CP0.Status.CU1 indicated whether CoProcessor1(which is FPU) is present. */
+ bool fp_enabled = ((cp0_status & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0);
+
+ if (mips32->fpu_in_64bit != fpu_in_64bit) {
+ mips32->fpu_in_64bit = fpu_in_64bit;
+ mips32_set_all_fpr_width(mips32, fpu_in_64bit);
+ LOG_WARNING("** FP mode changed to %sbit, you must reconnect GDB **", fpu_in_64bit ? "64" : "32");
+ }
+
+ if (mips32->fpu_enabled != fp_enabled) {
+ mips32->fpu_enabled = fp_enabled;
+ const char *s = fp_enabled ? "enabled" : "disabled";
+ LOG_WARNING("** FP is %s, register update %s **", s, s);
+ }
+}
+
static int mips32_read_core_reg(struct target *target, unsigned int num)
{
unsigned int cnum;
@@ -278,6 +333,8 @@ static int mips32_read_core_reg(struct target *target, unsigned int num)
cnum = num - MIPS32_REGLIST_C0_INDEX;
reg_value = mips32->core_regs.cp0[cnum];
buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
+ if (cnum == MIPS32_REG_C0_STATUS_INDEX)
+ mips32_detect_fpr_mode_change(mips32, reg_value);
} else if (num >= MIPS32_REGLIST_FPC_INDEX) {
/* FPCR */
cnum = num - MIPS32_REGLIST_FPC_INDEX;
@@ -319,6 +376,8 @@ static int mips32_write_core_reg(struct target *target, unsigned int num)
cnum = num - MIPS32_REGLIST_C0_INDEX;
reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
mips32->core_regs.cp0[cnum] = (uint32_t)reg_value;
+ if (cnum == MIPS32_REG_C0_STATUS_INDEX)
+ mips32_detect_fpr_mode_change(mips32, reg_value);
} else if (num >= MIPS32_REGLIST_FPC_INDEX) {
/* FPCR */
cnum = num - MIPS32_REGLIST_FPC_INDEX;
@@ -987,8 +1046,8 @@ static int mips32_read_config_fpu(struct mips32_common *mips32, struct mips_ejta
mips32->fp_imp = MIPS32_FP_IMP_NONE;
return ERROR_OK;
}
- uint32_t status_value;
- bool status_fr, status_cu1;
+ uint32_t fir_value, status_value;
+ bool fpu_in_64bit, fp_enabled;
retval = mips32_cp0_read(ejtag_info, &status_value, MIPS32_C0_STATUS, 0);
if (retval != ERROR_OK) {
@@ -996,20 +1055,34 @@ static int mips32_read_config_fpu(struct mips32_common *mips32, struct mips_ejta
return retval;
}
- status_fr = (status_value >> MIPS32_CP0_STATUS_FR_SHIFT) & 0x1;
- status_cu1 = (status_value >> MIPS32_CP0_STATUS_CU1_SHIFT) & 0x1;
- if (status_cu1) {
- /* TODO: read fpu(cp1) config register for current operating mode.
- * Now its set to 32 bits by default. */
- snprintf(buf, sizeof(buf), "yes");
- fp_imp = MIPS32_FP_IMP_32;
+ fpu_in_64bit = (status_value & BIT(MIPS32_CP0_STATUS_FR_SHIFT)) != 0;
+ fp_enabled = (status_value & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0;
+ if (fp_enabled) {
+ retval = mips32_cp1_control_read(ejtag_info, &fir_value, 0);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to read cp1 FIR register");
+ return retval;
+ }
+
+ if ((fir_value >> MIPS32_CP1_FIR_F64_SHIFT) & 0x1)
+ fp_imp++;
} else {
+ /* This is the only condition that writes to buf */
snprintf(buf, sizeof(buf), "yes, disabled");
fp_imp = MIPS32_FP_IMP_UNKNOWN;
}
- mips32->fpu_in_64bit = status_fr;
- mips32->fpu_enabled = status_cu1;
+ mips32->fpu_in_64bit = fpu_in_64bit;
+ mips32->fpu_enabled = fp_enabled;
+
+ mips32_set_all_fpr_width(mips32, fpu_in_64bit);
+
+ /* If fpu is not disabled, print out more information */
+ if (!buf[0])
+ snprintf(buf, sizeof(buf), "yes, %sbit (%s, working in %sbit)",
+ fp_imp == MIPS32_FP_IMP_64 ? "64" : "32",
+ fp_enabled ? "enabled" : "disabled",
+ fpu_in_64bit ? "64" : "32");
LOG_USER("FPU implemented: %s", buf);
mips32->fp_imp = fp_imp;
diff --git a/src/target/mips32.h b/src/target/mips32.h
index d512e4970..a557f3117 100644
--- a/src/target/mips32.h
+++ b/src/target/mips32.h
@@ -459,10 +459,13 @@ struct mips32_algorithm {
#define MIPS32_OP_AND 0x24u
#define MIPS32_OP_CACHE 0x2Fu
#define MIPS32_OP_COP0 0x10u
+#define MIPS32_OP_COP1 0x11u
#define MIPS32_OP_J 0x02u
#define MIPS32_OP_JR 0x08u
#define MIPS32_OP_LUI 0x0Fu
#define MIPS32_OP_LW 0x23u
+#define MIPS32_OP_LWC1 0x31u
+#define MIPS32_OP_LDC1 0x35u
#define MIPS32_OP_LB 0x20u
#define MIPS32_OP_LBU 0x24u
#define MIPS32_OP_LHU 0x25u
@@ -470,6 +473,7 @@ struct mips32_algorithm {
#define MIPS32_OP_MTHI 0x11u
#define MIPS32_OP_MFLO 0x12u
#define MIPS32_OP_MTLO 0x13u
+#define MIPS32_OP_MUL 0x02u
#define MIPS32_OP_RDHWR 0x3Bu
#define MIPS32_OP_SB 0x28u
#define MIPS32_OP_SH 0x29u
@@ -485,6 +489,8 @@ struct mips32_algorithm {
#define MIPS32_OP_SLLV 0x04u
#define MIPS32_OP_SLTI 0x0Au
#define MIPS32_OP_MOVN 0x0Bu
+#define MIPS32_OP_SWC1 0x39u
+#define MIPS32_OP_SDC1 0x3Du
#define MIPS32_OP_REGIMM 0x01u
#define MIPS32_OP_SDBBP 0x3Fu
@@ -517,6 +523,7 @@ struct mips32_algorithm {
#define MIPS32_ISA_BGTZ(reg, off) MIPS32_I_INST(MIPS32_OP_BGTZ, reg, 0, off)
#define MIPS32_ISA_BNE(src, tar, off) MIPS32_I_INST(MIPS32_OP_BNE, src, tar, off)
#define MIPS32_ISA_CACHE(op, off, base) MIPS32_I_INST(MIPS32_OP_CACHE, base, op, off)
+#define MIPS32_ISA_CFC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_CF, gpr, cpr, 0, 0)
#define MIPS32_ISA_J(tar) MIPS32_J_INST(MIPS32_OP_J, (0x0FFFFFFFu & (tar)) >> 2)
#define MIPS32_ISA_JR(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_JR)
#define MIPS32_ISA_JRHB(reg) MIPS32_R_INST(0, reg, 0, 0, 0x10, MIPS32_OP_JR)
@@ -526,9 +533,15 @@ struct mips32_algorithm {
#define MIPS32_ISA_LHU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LHU, base, reg, off)
#define MIPS32_ISA_LUI(reg, val) MIPS32_I_INST(MIPS32_OP_LUI, 0, reg, val)
#define MIPS32_ISA_LW(reg, off, base) MIPS32_I_INST(MIPS32_OP_LW, base, reg, off)
+#define MIPS32_ISA_LWC1(reg, off, base) MIPS32_I_INST(MIPS32_OP_LWC1, base, reg, off)
+#define MIPS32_ISA_LDC1(reg, off, base) MIPS32_I_INST(MIPS32_OP_LDC1, base, reg, off)
#define MIPS32_ISA_MFC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP_MF, gpr, cpr, 0, sel)
#define MIPS32_ISA_MTC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP_MT, gpr, cpr, 0, sel)
+#define MIPS32_ISA_MFC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_MF, gpr, cpr, 0, 0)
+#define MIPS32_ISA_MFHC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_MFH, gpr, cpr, 0, 0)
+#define MIPS32_ISA_MTC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_MT, gpr, cpr, 0, 0)
+#define MIPS32_ISA_MTHC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_MTH, gpr, cpr, 0, 0)
#define MIPS32_ISA_MFLO(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFLO)
#define MIPS32_ISA_MFHI(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFHI)
#define MIPS32_ISA_MTLO(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTLO)
@@ -542,6 +555,8 @@ struct mips32_algorithm {
#define MIPS32_ISA_SB(reg, off, base) MIPS32_I_INST(MIPS32_OP_SB, base, reg, off)
#define MIPS32_ISA_SH(reg, off, base) MIPS32_I_INST(MIPS32_OP_SH, base, reg, off)
#define MIPS32_ISA_SW(reg, off, base) MIPS32_I_INST(MIPS32_OP_SW, base, reg, off)
+#define MIPS32_ISA_SWC1(reg, off, base) MIPS32_I_INST(MIPS32_OP_SWC1, base, reg, off)
+#define MIPS32_ISA_SDC1(reg, off, base) MIPS32_I_INST(MIPS32_OP_SDC1, base, reg, off)
#define MIPS32_ISA_SLL(dst, src, sa) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, dst, sa, MIPS32_OP_SLL)
#define MIPS32_ISA_SLLV(dst, src, sa) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, dst, sa, MIPS32_OP_SLLV)
@@ -588,6 +603,7 @@ struct mips32_algorithm {
#define MMIPS32_OP_BGTZ 0x06u
#define MMIPS32_OP_BNE 0x2Du
#define MMIPS32_OP_CACHE 0x06u
+#define MMIPS32_OP_CFC1 0x40u
#define MMIPS32_OP_J 0x35u
#define MMIPS32_OP_JALR 0x03Cu
#define MMIPS32_OP_JALRHB 0x07Cu
@@ -596,8 +612,14 @@ struct mips32_algorithm {
#define MMIPS32_OP_LHU 0x0Du
#define MMIPS32_OP_LUI 0x0Du
#define MMIPS32_OP_LW 0x3Fu
+#define MMIPS32_OP_LWC1 0x27u
+#define MMIPS32_OP_LDC1 0x2Fu
#define MMIPS32_OP_MFC0 0x03u
+#define MMIPS32_OP_MFC1 0x80u
+#define MMIPS32_OP_MFHC1 0xC0u
#define MMIPS32_OP_MTC0 0x0Bu
+#define MMIPS32_OP_MTC1 0xA0u
+#define MMIPS32_OP_MTHC1 0xE0u
#define MMIPS32_OP_MFLO 0x075u
#define MMIPS32_OP_MFHI 0x035u
#define MMIPS32_OP_MTLO 0x0F5u
@@ -608,6 +630,8 @@ struct mips32_algorithm {
#define MMIPS32_OP_SB 0x06u
#define MMIPS32_OP_SH 0x0Eu
#define MMIPS32_OP_SW 0x3Eu
+#define MMIPS32_OP_SWC1 0x26u
+#define MMIPS32_OP_SDC1 0x2Eu
#define MMIPS32_OP_SLTU 0x390u
#define MMIPS32_OP_SLL 0x000u
#define MMIPS32_OP_SLTI 0x24u
@@ -627,6 +651,7 @@ struct mips32_algorithm {
#define MMIPS32_BGTZ(reg, off) MIPS32_I_INST(MMIPS32_POOL32I, MMIPS32_OP_BGTZ, reg, off)
#define MMIPS32_BNE(src, tar, off) MIPS32_I_INST(MMIPS32_OP_BNE, tar, src, off)
#define MMIPS32_CACHE(op, off, base) MIPS32_R_INST(MMIPS32_POOL32B, op, base, MMIPS32_OP_CACHE << 1, 0, off)
+#define MMIPS32_CFC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_CFC1, MMIPS32_POOL32FXF)
#define MMIPS32_J(tar) MIPS32_J_INST(MMIPS32_OP_J, ((0x07FFFFFFu & ((tar) >> 1))))
#define MMIPS32_JR(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_JALR, MMIPS32_POOL32AXF)
@@ -636,13 +661,19 @@ struct mips32_algorithm {
#define MMIPS32_LHU(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LHU, reg, base, off)
#define MMIPS32_LUI(reg, val) MIPS32_I_INST(MMIPS32_POOL32I, MMIPS32_OP_LUI, reg, val)
#define MMIPS32_LW(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LW, reg, base, off)
+#define MMIPS32_LWC1(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LWC1, reg, base, off)
+#define MMIPS32_LDC1(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LDC1, reg, base, off)
#define MMIPS32_MFC0(gpr, cpr, sel) MIPS32_R_INST(MMIPS32_POOL32A, gpr, cpr, sel,\
MMIPS32_OP_MFC0, MMIPS32_POOL32AXF)
+#define MMIPS32_MFC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_MFC1, MMIPS32_POOL32FXF)
+#define MMIPS32_MFHC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_MFHC1, MMIPS32_POOL32FXF)
#define MMIPS32_MFLO(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MFLO, MMIPS32_POOL32AXF)
#define MMIPS32_MFHI(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MFHI, MMIPS32_POOL32AXF)
#define MMIPS32_MTC0(gpr, cpr, sel) MIPS32_R_INST(MMIPS32_POOL32A, gpr, cpr, sel,\
MMIPS32_OP_MTC0, MMIPS32_POOL32AXF)
+#define MMIPS32_MTC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_MTC1, MMIPS32_POOL32FXF)
+#define MMIPS32_MTHC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_MTHC1, MMIPS32_POOL32FXF)
#define MMIPS32_MTLO(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MTLO, MMIPS32_POOL32AXF)
#define MMIPS32_MTHI(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MTHI, MMIPS32_POOL32AXF)
@@ -653,6 +684,8 @@ struct mips32_algorithm {
#define MMIPS32_SB(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SB, reg, base, off)
#define MMIPS32_SH(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SH, reg, base, off)
#define MMIPS32_SW(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SW, reg, base, off)
+#define MMIPS32_SWC1(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SWC1, reg, base, off)
+#define MMIPS32_SDC1(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SDC1, reg, base, off)
#define MMIPS32_SRL(reg, src, off) MIPS32_R_INST(MMIPS32_POOL32A, reg, src, off, 0, MMIPS32_OP_SRL)
#define MMIPS32_SLTU(dst, src, tar) MIPS32_R_INST(MMIPS32_POOL32A, tar, src, dst, 0, MMIPS32_OP_SLTU)
@@ -686,6 +719,7 @@ struct mips32_algorithm {
#define MIPS32_BGTZ(isa, reg, off) (isa ? MMIPS32_BGTZ(reg, off) : MIPS32_ISA_BGTZ(reg, off))
#define MIPS32_BNE(isa, src, tar, off) (isa ? MMIPS32_BNE(src, tar, off) : MIPS32_ISA_BNE(src, tar, off))
#define MIPS32_CACHE(isa, op, off, base) (isa ? MMIPS32_CACHE(op, off, base) : MIPS32_ISA_CACHE(op, off, base))
+#define MIPS32_CFC1(isa, gpr, cpr) (isa ? MMIPS32_CFC1(gpr, cpr) : MIPS32_ISA_CFC1(gpr, cpr))
#define MIPS32_J(isa, tar) (isa ? MMIPS32_J(tar) : MIPS32_ISA_J(tar))
#define MIPS32_JR(isa, reg) (isa ? MMIPS32_JR(reg) : MIPS32_ISA_JR(reg))
@@ -694,10 +728,15 @@ struct mips32_algorithm {
#define MIPS32_LBU(isa, reg, off, base) (isa ? MMIPS32_LBU(reg, off, base) : MIPS32_ISA_LBU(reg, off, base))
#define MIPS32_LHU(isa, reg, off, base) (isa ? MMIPS32_LHU(reg, off, base) : MIPS32_ISA_LHU(reg, off, base))
#define MIPS32_LW(isa, reg, off, base) (isa ? MMIPS32_LW(reg, off, base) : MIPS32_ISA_LW(reg, off, base))
+#define MIPS32_LWC1(isa, reg, off, base) (isa ? MMIPS32_LWC1(reg, off, base) : MIPS32_ISA_LWC1(reg, off, base))
#define MIPS32_LUI(isa, reg, val) (isa ? MMIPS32_LUI(reg, val) : MIPS32_ISA_LUI(reg, val))
#define MIPS32_MFC0(isa, gpr, cpr, sel) (isa ? MMIPS32_MFC0(gpr, cpr, sel) : MIPS32_ISA_MFC0(gpr, cpr, sel))
#define MIPS32_MTC0(isa, gpr, cpr, sel) (isa ? MMIPS32_MTC0(gpr, cpr, sel) : MIPS32_ISA_MTC0(gpr, cpr, sel))
+#define MIPS32_MFC1(isa, gpr, cpr) (isa ? MMIPS32_MFC1(gpr, cpr) : MIPS32_ISA_MFC1(gpr, cpr))
+#define MIPS32_MFHC1(isa, gpr, cpr) (isa ? MMIPS32_MFHC1(gpr, cpr) : MIPS32_ISA_MFHC1(gpr, cpr))
+#define MIPS32_MTC1(isa, gpr, cpr) (isa ? MMIPS32_MTC1(gpr, cpr) : MIPS32_ISA_MTC1(gpr, cpr))
+#define MIPS32_MTHC1(isa, gpr, cpr) (isa ? MMIPS32_MTHC1(gpr, cpr) : MIPS32_ISA_MTHC1(gpr, cpr))
#define MIPS32_MFLO(isa, reg) (isa ? MMIPS32_MFLO(reg) : MIPS32_ISA_MFLO(reg))
#define MIPS32_MFHI(isa, reg) (isa ? MMIPS32_MFHI(reg) : MIPS32_ISA_MFHI(reg))
#define MIPS32_MTLO(isa, reg) (isa ? MMIPS32_MTLO(reg) : MIPS32_ISA_MTLO(reg))
@@ -710,6 +749,8 @@ struct mips32_algorithm {
#define MIPS32_SB(isa, reg, off, base) (isa ? MMIPS32_SB(reg, off, base) : MIPS32_ISA_SB(reg, off, base))
#define MIPS32_SH(isa, reg, off, base) (isa ? MMIPS32_SH(reg, off, base) : MIPS32_ISA_SH(reg, off, base))
#define MIPS32_SW(isa, reg, off, base) (isa ? MMIPS32_SW(reg, off, base) : MIPS32_ISA_SW(reg, off, base))
+#define MIPS32_SWC1(isa, reg, off, base) (isa ? MMIPS32_SWC1(reg, off, base) : MIPS32_ISA_SWC1(reg, off, base))
+#define MIPS32_SDC1(isa, reg, off, base) (isa ? MMIPS32_SDC1(reg, off, base) : MIPS32_ISA_SDC1(reg, off, base))
#define MIPS32_SLL(isa, dst, src, sa) (isa ? MMIPS32_SLL(dst, src, sa) : MIPS32_ISA_SLL(dst, src, sa))
#define MIPS32_EHB(isa) (isa ? MMIPS32_SLL(0, 0, 3) : MIPS32_ISA_SLL(0, 0, 3))
diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c
index 22edf6a41..aaf3875fb 100644
--- a/src/target/mips32_pracc.c
+++ b/src/target/mips32_pracc.c
@@ -588,6 +588,26 @@ int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_r
return ctx.retval;
}
+int mips32_cp1_control_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp1_c_reg)
+{
+ struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
+ pracc_queue_init(&ctx);
+
+ pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
+ pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa));
+ pracc_add(&ctx, 0, MIPS32_CFC1(ctx.isa, 8, cp1_c_reg)); /* move cp1c reg to $8 */
+ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
+ MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */
+ pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */
+ pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */
+ pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */
+ pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */
+
+ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val, 1);
+ pracc_queue_free(&ctx);
+ return ctx.retval;
+}
+
/**
* \b mips32_pracc_sync_cache
*
@@ -856,6 +876,9 @@ int mips32_pracc_write_regs(struct mips32_common *mips32)
struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
uint32_t *gprs = mips32->core_regs.gpr;
uint32_t *c0rs = mips32->core_regs.cp0;
+ bool fpu_in_64bit = ((c0rs[0] & BIT(MIPS32_CP0_STATUS_FR_SHIFT)) != 0);
+ bool fp_enabled = ((c0rs[0] & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0);
+ uint32_t rel = (ejtag_info->config[0] & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT;
pracc_queue_init(&ctx);
@@ -895,6 +918,31 @@ int mips32_pracc_write_regs(struct mips32_common *mips32)
if (mips32_cpu_support_hazard_barrier(ejtag_info))
pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa));
+
+ /* store FPRs */
+ if (mips32->fp_imp && fp_enabled) {
+ uint64_t *fprs = mips32->core_regs.fpr;
+ if (fpu_in_64bit) {
+ for (int i = 0; i != MIPS32_REG_FP_COUNT; i++) {
+ uint32_t fp_lo = fprs[i] & 0xffffffff;
+ uint32_t fp_hi = (fprs[i] >> 32) & 0xffffffff;
+ pracc_add_li32(&ctx, 2, fp_lo, 0);
+ pracc_add_li32(&ctx, 3, fp_hi, 0);
+ pracc_add(&ctx, 0, MIPS32_MTC1(ctx.isa, 2, i));
+ pracc_add(&ctx, 0, MIPS32_MTHC1(ctx.isa, 3, i));
+ }
+ } else {
+ for (int i = 0; i != MIPS32_REG_FP_COUNT; i++) {
+ uint32_t fp_lo = fprs[i] & 0xffffffff;
+ pracc_add_li32(&ctx, 2, fp_lo, 0);
+ pracc_add(&ctx, 0, MIPS32_MTC1(ctx.isa, 2, i));
+ }
+ }
+
+ if (rel > MIPS32_RELEASE_1)
+ pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa));
+ }
+
/* load registers 2 to 31 with li32, optimize */
for (int i = 2; i < 32; i++)
pracc_add_li32(&ctx, i, gprs[i], 1);
@@ -1014,6 +1062,9 @@ int mips32_pracc_read_regs(struct mips32_common *mips32)
struct mips32_core_regs *core_regs = &mips32->core_regs;
unsigned int offset_gpr = ((uint8_t *)&core_regs->gpr[0]) - (uint8_t *)core_regs;
unsigned int offset_cp0 = ((uint8_t *)&core_regs->cp0[0]) - (uint8_t *)core_regs;
+ unsigned int offset_fpr = ((uint8_t *)&core_regs->fpr[0]) - (uint8_t *)core_regs;
+ unsigned int offset_fpcr = ((uint8_t *)&core_regs->fpcr[0]) - (uint8_t *)core_regs;
+ bool fp_enabled;
/*
* This procedure has to be in 2 distinctive steps, because we can
@@ -1040,11 +1091,64 @@ int mips32_pracc_read_regs(struct mips32_common *mips32)
ejtag_info->reg8 = mips32->core_regs.gpr[8];
ejtag_info->reg9 = mips32->core_regs.gpr[9];
+ if (ctx.retval != ERROR_OK)
+ return ctx.retval;
+
/* we only care if FP is actually impl'd and if cp1 is enabled */
/* since we already read cp0 in the prev step */
/* now we know what's in cp0.status */
- /* TODO: Read FPRs */
+ fp_enabled = (mips32->core_regs.cp0[0] & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0;
+ if (mips32->fp_imp && fp_enabled) {
+ pracc_queue_init(&ctx);
+ mips32_pracc_store_regs_set_base_addr(&ctx);
+
+ /* FCSR */
+ pracc_add(&ctx, 0, MIPS32_CFC1(ctx.isa, 8, 31));
+ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset_fpcr,
+ MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset_fpcr, 1));
+
+ /* FIR */
+ pracc_add(&ctx, 0, MIPS32_CFC1(ctx.isa, 8, 0));
+ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset_fpcr + 4,
+ MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset_fpcr + 4, 1));
+
+ /* f0 to f31 */
+ if (mips32->fpu_in_64bit) {
+ for (int i = 0; i != 32; i++) {
+ size_t offset = offset_fpr + (i * 8);
+ /* current pracc implementation (or EJTAG itself) only supports 32b access */
+ /* so there is no way to use SDC1 */
+
+ /* lower half */
+ pracc_add(&ctx, 0, MIPS32_MFC1(ctx.isa, 8, i));
+ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset,
+ MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset, 1));
+
+ /* upper half */
+ pracc_add(&ctx, 0, MIPS32_MFHC1(ctx.isa, 8, i));
+ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset + 4,
+ MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset + 4, 1));
+ }
+ } else {
+ for (int i = 0; i != 32; i++) {
+ size_t offset = offset_fpr + (i * 8);
+ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset,
+ MIPS32_SWC1(ctx.isa, i, PRACC_OUT_OFFSET + offset, 1));
+ }
+ }
+
+ mips32_pracc_store_regs_restore(&ctx);
+
+ /* jump to start */
+ pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));
+ /* load $15 in DeSave */
+ pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0));
+
+ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, (uint32_t *)&mips32->core_regs, 1);
+
+ pracc_queue_free(&ctx);
+ }
return ctx.retval;
}
diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h
index 78d087213..f78f89153 100644
--- a/src/target/mips32_pracc.h
+++ b/src/target/mips32_pracc.h
@@ -103,6 +103,21 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info,
int mips32_cp0_write(struct mips_ejtag *ejtag_info,
uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel);
+/**
+ * mips32_cp1_control_read
+ *
+ * @brief Simulates cfc1 ASM instruction (Move Control Word From Floating Point),
+ * i.e. implements copro C1 Control Register read.
+ *
+ * @param[in] ejtag_info
+ * @param[in] val Storage to hold read value
+ * @param[in] cp1_c_reg Number of copro C1 control register we want to read
+ *
+ * @return ERROR_OK on Success, ERROR_FAIL otherwise
+ */
+int mips32_cp1_control_read(struct mips_ejtag *ejtag_info,
+ uint32_t *val, uint32_t cp1_c_reg);
+
static inline void pracc_swap16_array(struct mips_ejtag *ejtag_info, uint32_t *buf, int count)
{
if (ejtag_info->isa && ejtag_info->endianness)
-----------------------------------------------------------------------
Summary of changes:
src/target/mips32.c | 95 ++++++++++++++++++++++++++++++++++++-----
src/target/mips32.h | 41 ++++++++++++++++++
src/target/mips32_pracc.c | 106 +++++++++++++++++++++++++++++++++++++++++++++-
src/target/mips32_pracc.h | 15 +++++++
4 files changed, 245 insertions(+), 12 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-03-16 14:45:01
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via a88db9b1211ea71b5795b91d11d94fb0f37cc905 (commit)
from 7a77355a3ea574dc5b7fc0a6ea8be413589ef847 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit a88db9b1211ea71b5795b91d11d94fb0f37cc905
Author: Daniel Anselmi <dan...@gm...>
Date: Mon Jan 1 16:05:07 2024 +0100
ipdbg: configurable queue size used between JTAG-Host and JTAG-Hub
Change-Id: I7941de02a968ccab730bfebd3483b8c3b84d7e53
Signed-off-by: Daniel Anselmi <dan...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/7980
Reviewed-by: Antonio Borneo <bor...@gm...>
Tested-by: jenkins
diff --git a/doc/openocd.texi b/doc/openocd.texi
index 651cc53bb..6b71fe869 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -12198,6 +12198,20 @@ xc7.ipdbghub ipdbg start -port 5555 -tool 0
Starts a server listening on tcp-port 5555 which connects to tool 0 (data_up_0/data_down_0).
The TAP and ir value used to reach the JTAG Hub is given by the pld driver.
+@deffn {Command} {$hub_name queuing} @option{-size @var{size}}
+Configure the queuing between IPDBG JTAG-Host and Hub.
+The maximum possible queue size is 1024 which is also the default.
+
+@itemize @bullet
+@item @option{-size @var{size}} max number of transfers in the queue.
+@end itemize
+@end deffn
+
+@example
+bitbang.ibdbghub queuing -size 32
+@end example
+Send a maximum of 32 transfers to the queue before executing them.
+
@node Utility Commands
@chapter Utility Commands
diff --git a/src/server/ipdbg.c b/src/server/ipdbg.c
index e218b8244..e7eb96e13 100644
--- a/src/server/ipdbg.c
+++ b/src/server/ipdbg.c
@@ -19,20 +19,11 @@
#define IPDBG_MAX_NUM_OF_CREATE_OPTIONS 10
#define IPDBG_NUM_OF_START_OPTIONS 4
#define IPDBG_NUM_OF_STOP_OPTIONS 2
+#define IPDBG_NUM_OF_QUEUE_OPTIONS 2
#define IPDBG_MIN_DR_LENGTH 11
#define IPDBG_MAX_DR_LENGTH 13
#define IPDBG_TCP_PORT_STR_MAX_LENGTH 6
#define IPDBG_SCRATCH_MEMORY_SIZE 1024
-#define IPDBG_EMPTY_DOWN_TRANSFERS 1024
-#define IPDBG_CONSECUTIVE_UP_TRANSFERS 1024
-
-#if IPDBG_SCRATCH_MEMORY_SIZE < IPDBG_EMPTY_DOWN_TRANSFERS
-#error "scratch Memory must be at least IPDBG_EMPTY_DOWN_TRANSFERS"
-#endif
-
-#if IPDBG_SCRATCH_MEMORY_SIZE < IPDBG_CONSECUTIVE_UP_TRANSFERS
-#error "scratch Memory must be at least IPDBG_CONSECUTIVE_UP_TRANSFERS"
-#endif
/* private connection data for IPDBG */
struct ipdbg_fifo {
@@ -78,6 +69,7 @@ struct ipdbg_hub {
uint32_t tool_mask;
uint32_t last_dn_tool;
char *name;
+ size_t using_queue_size;
struct ipdbg_hub *next;
struct jtag_tap *tap;
struct connection **connections;
@@ -461,7 +453,7 @@ static int ipdbg_shift_empty_data(struct ipdbg_hub *hub)
const size_t dreg_buffer_size = DIV_ROUND_UP(hub->data_register_length, 8);
memset(hub->scratch_memory.dr_out_vals, 0, dreg_buffer_size);
- for (size_t i = 0; i < IPDBG_EMPTY_DOWN_TRANSFERS; ++i) {
+ for (size_t i = 0; i < hub->using_queue_size; ++i) {
ipdbg_init_scan_field(hub->scratch_memory.fields + i,
hub->scratch_memory.dr_in_vals + i * dreg_buffer_size,
hub->data_register_length,
@@ -473,7 +465,7 @@ static int ipdbg_shift_empty_data(struct ipdbg_hub *hub)
if (retval == ERROR_OK) {
uint32_t up_data;
- for (size_t i = 0; i < IPDBG_EMPTY_DOWN_TRANSFERS; ++i) {
+ for (size_t i = 0; i < hub->using_queue_size; ++i) {
up_data = buf_get_u32(hub->scratch_memory.dr_in_vals +
i * dreg_buffer_size, 0,
hub->data_register_length);
@@ -522,8 +514,8 @@ static int ipdbg_jtag_transfer_bytes(struct ipdbg_hub *hub,
return ERROR_FAIL;
const size_t dreg_buffer_size = DIV_ROUND_UP(hub->data_register_length, 8);
- size_t num_tx = (connection->dn_fifo.count < IPDBG_CONSECUTIVE_UP_TRANSFERS) ?
- connection->dn_fifo.count : IPDBG_CONSECUTIVE_UP_TRANSFERS;
+ size_t num_tx = (connection->dn_fifo.count < hub->using_queue_size) ?
+ connection->dn_fifo.count : hub->using_queue_size;
for (size_t i = 0; i < num_tx; ++i) {
uint32_t dn_data = hub->valid_mask | ((tool & hub->tool_mask) << 8) |
@@ -906,6 +898,46 @@ static const struct command_registration ipdbg_hostserver_subcommand_handlers[]
COMMAND_REGISTRATION_DONE
};
+static COMMAND_HELPER(ipdbg_config_queuing, struct ipdbg_hub *hub, unsigned int size)
+{
+ if (!hub)
+ return ERROR_FAIL;
+
+ if (hub->active_connections) {
+ command_print(CMD, "Configuration change not allowed when hub has active connections");
+ return ERROR_FAIL;
+ }
+
+ if (size == 0 || size > IPDBG_SCRATCH_MEMORY_SIZE) {
+ command_print(CMD, "queuing size out of range! Must be 0 < size <= %d", IPDBG_SCRATCH_MEMORY_SIZE);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ hub->using_queue_size = size;
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_ipdbg_cfg_queuing_command)
+{
+ struct ipdbg_hub *hub = CMD_DATA;
+
+ unsigned int size;
+
+ if (CMD_ARGC != IPDBG_NUM_OF_QUEUE_OPTIONS)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ for (unsigned int i = 0; i < CMD_ARGC; ++i) {
+ if (strcmp(CMD_ARGV[i], "-size") == 0) {
+ COMMAND_PARSE_ADDITIONAL_NUMBER(uint, i, size, "size");
+ } else {
+ command_print(CMD, "Unknown argument: %s", CMD_ARGV[i]);
+ return ERROR_FAIL;
+ }
+ }
+
+ return CALL_COMMAND_HANDLER(ipdbg_config_queuing, hub, size);
+}
+
static const struct command_registration ipdbg_hub_subcommand_handlers[] = {
{
.name = "ipdbg",
@@ -914,6 +946,13 @@ static const struct command_registration ipdbg_hub_subcommand_handlers[] = {
.usage = "",
.chain = ipdbg_hostserver_subcommand_handlers
},
+ {
+ .name = "queuing",
+ .handler = handle_ipdbg_cfg_queuing_command,
+ .mode = COMMAND_ANY,
+ .help = "configures queuing between IPDBG Host and Hub.",
+ .usage = "-size size",
+ },
COMMAND_REGISTRATION_DONE
};
@@ -960,6 +999,7 @@ static int ipdbg_create_hub(struct jtag_tap *tap, uint32_t user_instruction, uin
new_hub->last_dn_tool = new_hub->tool_mask;
new_hub->virtual_ir = virtual_ir;
new_hub->max_tools = ipdbg_max_tools_from_data_register_length(data_register_length);
+ new_hub->using_queue_size = IPDBG_SCRATCH_MEMORY_SIZE;
int retval = ipdbg_register_hub_command(new_hub, cmd);
if (retval != ERROR_OK) {
-----------------------------------------------------------------------
Summary of changes:
doc/openocd.texi | 14 +++++++++++
src/server/ipdbg.c | 68 +++++++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 68 insertions(+), 14 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2024-03-16 14:44:05
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 7a77355a3ea574dc5b7fc0a6ea8be413589ef847 (commit)
from 1d076d6ce1908d5c154bfc6ee2ccd8a629853ef1 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 7a77355a3ea574dc5b7fc0a6ea8be413589ef847
Author: Daniel Anselmi <dan...@gm...>
Date: Mon Jan 1 16:05:07 2024 +0100
ipdbg: split ipdbg command into multiple commands
To simplify the ipdbg start/stop command and be able to
add additional commands in the future, we introduce the
concept of a hub which has to be created before a
ipdbg server can be started.
The hub was created on the fly in previous versions.
Change-Id: I55f317542d01a7324990b2cacd496a41fa5ff875
Signed-off-by: Daniel Anselmi <dan...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/7979
Reviewed-by: Antonio Borneo <bor...@gm...>
Tested-by: jenkins
diff --git a/doc/openocd.texi b/doc/openocd.texi
index bf4e0ad65..651cc53bb 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -12116,55 +12116,84 @@ waveform generator. These are synthesize-able hardware descriptions of
logic circuits in addition to software for control, visualization and further analysis.
In a session using JTAG for its transport protocol, OpenOCD supports the function
of a JTAG-Host. The JTAG-Host is needed to connect the circuit over JTAG to the
-control-software. For more details see @url{http://ipdbg.org}.
+control-software. The JTAG-Hub is the circuit which transfers the data from JTAG to the
+different tools connected to the Hub. Hub implementations for most major FPGA vendors/families
+are provided. For more details see @url{http://ipdbg.org}.
-@deffn {Command} {ipdbg} [@option{-start|-stop}] @option{-tap @var{tapname}} @option{-hub @var{ir_value} [@var{dr_length}]} [@option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]}] [@option{-port @var{number}}] [@option{-tool @var{number}}]
-Starts or stops a IPDBG JTAG-Host server. Arguments can be specified in any order.
+@deffn {Command} {ipdbg create-hub} @var{hub_name} @option{-tap @var{tapname}} @option{-ir @var{ir_value} [@var{dr_length}]} [@option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]}]
+@deffnx {Command} {ipdbg create-hub} @var{hub_name} @option{-pld @var{pld_name} [@var{user}]} [@option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]}]
+Creates a IPDBG JTAG Hub. The created hub is later used to start, stop and configure IPDBG JTAG Host servers.
+The first argument @var{hub_name} is the name of the created hub. It can be used later as a reference.
+
+The pld drivers are able to provide the tap and ir_value for the IPDBG JTAG-Host server. This will be used with the second variant with option @option{-pld}.
Command options:
@itemize @bullet
-@item @option{-start|-stop} starts or stops a IPDBG JTAG-Host server (default: start).
+@item @var{hub_name} the name of the IPDBG hub.
+This name is also used to create the object's command, referred to here
+as @command{$hub_name}, and in other places where the Hub needs to be identified.
+
@item @option{-tap @var{tapname}} targeting the TAP @var{tapname}.
-@item @option{-hub @var{ir_value}} states that the JTAG hub is
-reachable with dr-scans while the JTAG instruction register has the value @var{ir_value}.
-@item @option{-port @var{number}} tcp port number where the JTAG-Host will listen. The default is 4242 which is used when the option is not given.
-@item @option{-tool @var{number}} number of the tool/feature. These corresponds to the ports "data_(up/down)_(0..6)" at the JtagHub. The default is 1 which is used when the option is not given.
-@item @option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]} On some devices, the user data-register is reachable if there is a
-specific value in a second dr. This second dr is called vir (virtual ir). With this parameter given, the IPDBG satisfies this condition prior an
+
+@item @option{-ir @var{ir_value}} states that the JTAG hub is
+reachable with dr-scans while the JTAG instruction register has the value @var{ir_value}. Also known as @verb{|USERx|} instructions.
+The optional @var{dr_length} is the length of the dr.
+Current JTAG-Hub implementation only supports dr_length=13, which is also the default value.
+
+@item @option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]} To support more Hubs than USER registers in a single FPGA it is possible to
+use a mechanism known as virtual-ir where the user data-register is reachable if there is a specific value in a second dr.
+This second dr is called vir (virtual ir). With this parameter given, the IPDBG satisfies this condition prior an
access to the IPDBG-Hub. The value shifted into the vir is given by the first parameter @var{vir_value} (default: 0x11). The second
parameter @var{length} is the length of the vir data register (default: 5). With the @var{instr_code} (default: 0x00e) parameter the ir value to
shift data through vir can be configured.
+
+@item @option{-pld @var{pld_name} [@var{user}]} The defined driver for the pld @var{pld_name} is used to get the tap and user instruction.
+The pld devices names can be shown by the command @command{pld devices}. With [@var{user}] one can select a different @verb{|USERx|}-Instruction.
+If the IPDBG JTAG-Hub is used without modification the default value of 1 which selects the first @verb{|USERx|} instruction is adequate.
+The @verb{|USERx|} instructions are vendor specific and don't change between families of the same vendor.
+So if there's a pld driver for your vendor it should work with your FPGA even when the driver is not compatible with your device for the remaining features.
+If your device/vendor is not supported you have to use the first variant.
+
@end itemize
+
@end deffn
-or
-@deffn {Command} {ipdbg} [@option{-start|-stop}] @option{-pld @var{name} [@var{user}]} [@option{-port @var{number}}] [@option{-tool @var{number}}]
-Also starts or stops a IPDBG JTAG-Host server. The pld drivers are able to provide the tap and hub/IR for the IPDBG JTAG-Host server.
-With the @option{-pld @var{name} [@var{user}]} the information from the pld-driver is used and the options @option{-tap} and @option{-hub} are not required.
-The defined driver for the pld @var{name} gets selected. (The pld devices names can be shown by the command @command{pld devices}).
-The @verb{|USERx|} instructions are vendor specific and don't change between families of the same vendor.
-So if there's a pld driver for your vendor it should work with your FPGA even when the driver is not compatible with your device for the remaining features. If your device/vendor is not supported you have to use the previous command.
+@deffn {Command} {$hub_name ipdbg start} @option{-tool @var{number}} @option{-port @var{number}}
+Starts a IPDBG JTAG-Host server. The remaining arguments can be specified in any order.
-With [@var{user}] one can select a different @verb{|USERx|}-Instruction. If the IPDBG JTAG-Hub is used without modification the default value of 1 which selects the first @verb{|USERx|} instruction is adequate.
+Command options:
+@itemize @bullet
+@item @option{-port @var{number}} tcp port number where the JTAG-Host will listen. The default is 4242 which is used when the option is not given.
+@item @option{-tool @var{number}} number of the tool/feature. These corresponds to the ports "data_(up/down)_(0..6)" at the JtagHub. The default is 1 which is used when the option is not given.
+@end itemize
+@end deffn
-The remaining options are described in the previous command.
+@deffn {Command} {$hub_name ipdbg stop} @option{-tool @var{number}}
+Stops a IPDBG JTAG-Host server.
+Command options:
+@itemize @bullet
+@item @option{-tool @var{number}} number of the tool/feature. These corresponds to the ports "data_(up/down)_(0..6)" at the JtagHub. The default is 1 which is used when the option is not given.
+@end itemize
@end deffn
Examples:
@example
-ipdbg -start -tap xc6s.tap -hub 0x02 -port 4242 -tool 4
+ipdbg create-hub xc6s.ipdbghub -tap xc6s.tap -hub 0x02
+xc6s.ipdbghub ipdbg start -port 4242 -tool 4
@end example
-Starts a server listening on tcp-port 4242 which connects to tool 4.
+Creates a IPDBG Hub and starts a server listening on tcp-port 4242 which connects to tool 4.
The connection is through the TAP of a Xilinx Spartan 6 on USER1 instruction (tested with a papillion pro board).
@example
-ipdbg -start -tap 10m50.tap -hub 0x00C -vir -port 60000 -tool 1
+ipdbg create-hub max10m50.ipdbghub -tap max10m50.tap -hub 0x00C -vir
+max10m50.ipdbghub ipdbg start -tool 1 -port 60000
@end example
Starts a server listening on tcp-port 60000 which connects to tool 1 (data_up_1/data_down_1).
The connection is through the TAP of a Intel MAX10 virtual jtag component (sld_instance_index is 0; sld_ir_width is smaller than 5).
@example
-ipdbg -start -pld xc7.pld -port 5555 -tool 0
+ipdbg create-hub xc7.ipdbghub -pld xc7.pld
+xc7.ipdbghub ipdbg start -port 5555 -tool 0
@end example
Starts a server listening on tcp-port 5555 which connects to tool 0 (data_up_0/data_down_0).
The TAP and ir value used to reach the JTAG Hub is given by the pld driver.
diff --git a/src/jtag/startup.tcl b/src/jtag/startup.tcl
index 4eca67771..41db38e4a 100644
--- a/src/jtag/startup.tcl
+++ b/src/jtag/startup.tcl
@@ -1146,4 +1146,132 @@ proc "pld device" {driver tap_name {opt 0}} {
}
}
+lappend _telnet_autocomplete_skip "ipdbg -start"
+proc "ipdbg -start" {args} {
+ echo "DEPRECATED! use 'ipdbg create-hub' and 'chip.ipdbghub ipdbg start ...', not 'ipdbg -start ...'"
+ set tap_name ""
+ set pld_name ""
+ set tool_num "1"
+ set port_num "4242"
+ set idx 0
+ set num_args [llength $args]
+ while {$idx < $num_args} {
+ set arg [lindex $args $idx]
+ switch -- $arg {
+ "-tap" {
+ incr idx
+ if {$idx >= $num_args || [string index [lindex $args $idx] 0] == "-"} {
+ echo "no TAP name given"
+ return
+ }
+ set tap_name [lindex $args $idx]
+ }
+ "-pld" {
+ incr idx
+ if {$idx >= $num_args || [string index [lindex $args $idx] 0] == "-"} {
+ echo "no PLD name given"
+ return
+ }
+ set pld_name [lindex $args $idx]
+ }
+ "-tool" {
+ if {[expr {$idx + 1}] < $num_args && [string index [lindex $args [expr {$idx + 1}]] 0] != "-"} {
+ set tool_num [lindex $args [expr {$idx + 1}]]
+ set args [lreplace $args [expr {$idx + 1}] [expr {$idx + 1}]]
+ incr num_args -1
+ }
+ set args [lreplace $args $idx $idx]
+ incr num_args -1
+ incr idx -1
+ }
+ "-port" {
+ if {[expr {$idx + 1}] < $num_args && [string index [lindex $args [expr {$idx + 1}]] 0] != "-"} {
+ set port_num [lindex $args [expr {$idx + 1}]]
+ set args [lreplace $args [expr {$idx + 1}] [expr {$idx + 1}]]
+ incr num_args -1
+ }
+ set args [lreplace $args $idx $idx]
+ incr num_args -1
+ incr idx -1
+ }
+ "-hub" {
+ set args [lreplace $args $idx $idx "-ir" ]
+ }
+ default {
+# don't touch remaining arguments
+ }
+ }
+ incr idx
+ }
+
+ set hub_name ""
+ if {$tap_name != ""} {
+ set hub_name [lindex [split $tap_name .] 0].ipdbghub
+ } elseif {$pld_name != ""} {
+ set hub_name [lindex [split $pld_name .] 0].ipdbghub
+ } else {
+ echo "parsing arguments failed: no tap and no pld given."
+ return
+ }
+
+ echo "name: $hub_name"
+ echo "ipdbg create-hub $hub_name $args"
+
+ catch {eval ipdbg create-hub $hub_name $args}
+
+ eval $hub_name ipdbg start -tool $tool_num -port $port_num
+}
+
+lappend _telnet_autocomplete_skip "ipdbg -stop"
+proc "ipdbg -stop" {args} {
+ echo "DEPRECATED! use 'chip.ipdbghub ipdbg stop ...', not 'ipdbg -stop ...'"
+ set tap_name ""
+ set pld_name ""
+ set tool_num "1"
+ set idx 0
+ set num_args [llength $args]
+ while {$idx < $num_args} {
+ set arg [lindex $args $idx]
+ switch -- $arg {
+ "-tap" {
+ incr idx
+ if {$idx >= $num_args || [string index [lindex $args $idx] 0] == "-"} {
+ echo "no TAP name given"
+ return
+ }
+ set tap_name [lindex $args $idx]
+ }
+ "-pld" {
+ incr idx
+ if {$idx >= $num_args || [string index [lindex $args $idx] 0] == "-"} {
+ echo "no PLD name given"
+ return
+ }
+ set pld_name [lindex $args $idx]
+ }
+ "-tool" {
+ if {[expr {$idx + 1}] < $num_args && [string index [lindex $args [expr {$idx + 1}]] 0] != "-"} {
+ set tool_num [lindex $args [expr {$idx + 1}]]
+ }
+ }
+ default {
+# don't touch remaining arguments
+ }
+ }
+ incr idx
+ }
+
+ set hub_name ""
+ if {$tap_name != ""} {
+ set hub_name [lindex [split $tap_name .] 0].ipdbghub
+ } elseif {$pld_name != ""} {
+ set hub_name [lindex [split $pld_name .] 0].ipdbghub
+ } else {
+ echo "parsing arguments failed: no tap and no pld given."
+ return
+ }
+
+ eval $hub_name ipdbg stop -tool $tool_num
+}
+
# END MIGRATION AIDS
diff --git a/src/server/ipdbg.c b/src/server/ipdbg.c
index 073323032..e218b8244 100644
--- a/src/server/ipdbg.c
+++ b/src/server/ipdbg.c
@@ -15,8 +15,10 @@
#include "ipdbg.h"
#define IPDBG_BUFFER_SIZE 16384
-#define IPDBG_MIN_NUM_OF_OPTIONS 2
-#define IPDBG_MAX_NUM_OF_OPTIONS 14
+#define IPDBG_MIN_NUM_OF_CREATE_OPTIONS 3
+#define IPDBG_MAX_NUM_OF_CREATE_OPTIONS 10
+#define IPDBG_NUM_OF_START_OPTIONS 4
+#define IPDBG_NUM_OF_STOP_OPTIONS 2
#define IPDBG_MIN_DR_LENGTH 11
#define IPDBG_MAX_DR_LENGTH 13
#define IPDBG_TCP_PORT_STR_MAX_LENGTH 6
@@ -75,6 +77,7 @@ struct ipdbg_hub {
uint32_t xoff_mask;
uint32_t tool_mask;
uint32_t last_dn_tool;
+ char *name;
struct ipdbg_hub *next;
struct jtag_tap *tap;
struct connection **connections;
@@ -247,59 +250,27 @@ static void ipdbg_add_hub(struct ipdbg_hub *hub)
for (ihub = ipdbg_first_hub; ihub->next; ihub = ihub->next)
;
ihub->next = hub;
- } else
+ } else {
ipdbg_first_hub = hub;
+ }
}
-static int ipdbg_create_hub(struct jtag_tap *tap, uint32_t user_instruction, uint8_t data_register_length,
- struct ipdbg_virtual_ir_info *virtual_ir, struct ipdbg_hub **hub)
+static int ipdbg_remove_hub(struct ipdbg_hub *hub)
{
- *hub = NULL;
- struct ipdbg_hub *new_hub = calloc(1, sizeof(struct ipdbg_hub));
- if (!new_hub)
- goto mem_err_hub;
-
- const size_t dreg_buffer_size = DIV_ROUND_UP(data_register_length, 8);
- new_hub->max_tools = ipdbg_max_tools_from_data_register_length(data_register_length);
-
- new_hub->scratch_memory.dr_out_vals = calloc(IPDBG_SCRATCH_MEMORY_SIZE, dreg_buffer_size);
- new_hub->scratch_memory.dr_in_vals = calloc(IPDBG_SCRATCH_MEMORY_SIZE, dreg_buffer_size);
- new_hub->scratch_memory.fields = calloc(IPDBG_SCRATCH_MEMORY_SIZE, sizeof(struct scan_field));
- new_hub->connections = calloc(new_hub->max_tools, sizeof(struct connection *));
-
- if (virtual_ir)
- new_hub->scratch_memory.vir_out_val = calloc(1, DIV_ROUND_UP(virtual_ir->length, 8));
-
- if (!new_hub->scratch_memory.dr_out_vals || !new_hub->scratch_memory.dr_in_vals ||
- !new_hub->scratch_memory.fields || (virtual_ir && !new_hub->scratch_memory.vir_out_val) ||
- !new_hub->connections)
- goto mem_err2;
-
- if (virtual_ir)
- buf_set_u32(new_hub->scratch_memory.vir_out_val, 0, virtual_ir->length, virtual_ir->value);
-
- new_hub->tap = tap;
- new_hub->user_instruction = user_instruction;
- new_hub->data_register_length = data_register_length;
- new_hub->valid_mask = BIT(data_register_length - 1);
- new_hub->xoff_mask = BIT(data_register_length - 2);
- new_hub->tool_mask = (new_hub->xoff_mask - 1) >> 8;
- new_hub->last_dn_tool = new_hub->tool_mask;
- new_hub->virtual_ir = virtual_ir;
+ if (!ipdbg_first_hub)
+ return ERROR_FAIL;
+ if (hub == ipdbg_first_hub) {
+ ipdbg_first_hub = ipdbg_first_hub->next;
+ return ERROR_OK;
+ }
- *hub = new_hub;
- return ERROR_OK;
+ for (struct ipdbg_hub *ihub = ipdbg_first_hub; ihub->next; ihub = ihub->next) {
+ if (hub == ihub->next) {
+ ihub->next = hub->next;
+ return ERROR_OK;
+ }
+ }
-mem_err2:
- free(new_hub->scratch_memory.vir_out_val);
- free(new_hub->connections);
- free(new_hub->scratch_memory.fields);
- free(new_hub->scratch_memory.dr_in_vals);
- free(new_hub->scratch_memory.dr_out_vals);
- free(new_hub);
-mem_err_hub:
- free(virtual_ir);
- LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
@@ -309,6 +280,7 @@ static void ipdbg_free_hub(struct ipdbg_hub *hub)
return;
free(hub->connections);
free(hub->virtual_ir);
+ free(hub->name);
free(hub->scratch_memory.dr_out_vals);
free(hub->scratch_memory.dr_in_vals);
free(hub->scratch_memory.fields);
@@ -316,23 +288,42 @@ static void ipdbg_free_hub(struct ipdbg_hub *hub)
free(hub);
}
-static int ipdbg_remove_hub(struct ipdbg_hub *hub)
+static struct ipdbg_hub *ipdbg_allocate_hub(uint8_t data_register_length, struct ipdbg_virtual_ir_info *virtual_ir,
+ const char *name)
{
- if (!ipdbg_first_hub)
- return ERROR_FAIL;
- if (hub == ipdbg_first_hub) {
- ipdbg_first_hub = ipdbg_first_hub->next;
- return ERROR_OK;
+ struct ipdbg_hub *new_hub = calloc(1, sizeof(struct ipdbg_hub));
+ if (!new_hub) {
+ LOG_ERROR("Out of memory");
+ return NULL;
}
- for (struct ipdbg_hub *ihub = ipdbg_first_hub; ihub->next; ihub = ihub->next) {
- if (hub == ihub->next) {
- ihub->next = hub->next;
- return ERROR_OK;
- }
+ new_hub->name = strdup(name);
+ if (!new_hub->name) {
+ free(new_hub);
+ LOG_ERROR("Out of memory");
+ return NULL;
}
- return ERROR_FAIL;
+ const size_t dreg_buffer_size = DIV_ROUND_UP(data_register_length, 8);
+ uint32_t max_tools = ipdbg_max_tools_from_data_register_length(data_register_length);
+
+ new_hub->scratch_memory.dr_out_vals = calloc(IPDBG_SCRATCH_MEMORY_SIZE, dreg_buffer_size);
+ new_hub->scratch_memory.dr_in_vals = calloc(IPDBG_SCRATCH_MEMORY_SIZE, dreg_buffer_size);
+ new_hub->scratch_memory.fields = calloc(IPDBG_SCRATCH_MEMORY_SIZE, sizeof(struct scan_field));
+ new_hub->connections = calloc(max_tools, sizeof(struct connection *));
+
+ if (virtual_ir)
+ new_hub->scratch_memory.vir_out_val = calloc(1, DIV_ROUND_UP(virtual_ir->length, 8));
+
+ if (!new_hub->scratch_memory.dr_out_vals || !new_hub->scratch_memory.dr_in_vals ||
+ !new_hub->scratch_memory.fields || (virtual_ir && !new_hub->scratch_memory.vir_out_val) ||
+ !new_hub->connections) {
+ ipdbg_free_hub(new_hub);
+ LOG_ERROR("Out of memory");
+ return NULL;
+ }
+
+ return new_hub;
}
static void ipdbg_init_scan_field(struct scan_field *fields, uint8_t *in_value, int num_bits, const uint8_t *out_value)
@@ -760,23 +751,62 @@ static const struct service_driver ipdbg_service_driver = {
.keep_client_alive_handler = NULL,
};
-static int ipdbg_start(uint16_t port, struct jtag_tap *tap, uint32_t user_instruction,
- uint8_t data_register_length, struct ipdbg_virtual_ir_info *virtual_ir, uint8_t tool)
+static struct ipdbg_hub *ipdbg_get_hub_by_name(const char *name)
{
- LOG_INFO("starting ipdbg service on port %d for tool %d", port, tool);
+ struct ipdbg_hub *hub = NULL;
+ for (hub = ipdbg_first_hub; hub; hub = hub->next) {
+ if (strcmp(hub->name, name) == 0)
+ break;
+ }
+ return hub;
+};
- struct ipdbg_hub *hub = ipdbg_find_hub(tap, user_instruction, virtual_ir);
- if (hub) {
- free(virtual_ir);
- if (hub->data_register_length != data_register_length) {
- LOG_DEBUG("hub must have the same data_register_length for all tools");
- return ERROR_FAIL;
+static int ipdbg_stop_service(struct ipdbg_service *service)
+{
+ int retval = ipdbg_remove_service(service);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("BUG: ipdbg_remove_service failed");
+ return retval;
+ }
+
+ char port_str_buffer[IPDBG_TCP_PORT_STR_MAX_LENGTH];
+ snprintf(port_str_buffer, IPDBG_TCP_PORT_STR_MAX_LENGTH, "%u", service->port);
+ retval = remove_service("ipdbg", port_str_buffer);
+ /* The ipdbg_service structure is freed by server.c:remove_service().
+ There the "priv" pointer is freed.*/
+ if (retval != ERROR_OK) {
+ LOG_ERROR("BUG: remove_service failed");
+ return retval;
+ }
+ return ERROR_OK;
+}
+
+int ipdbg_server_free(void)
+{
+ int retval = ERROR_OK;
+ for (struct ipdbg_hub *hub = ipdbg_first_hub; hub;) {
+ for (uint8_t tool = 0; tool < hub->max_tools; ++tool) {
+ struct ipdbg_service *service = ipdbg_find_service(hub, tool);
+ if (service) {
+ int new_retval = ipdbg_stop_service(service);
+ if (new_retval != ERROR_OK)
+ retval = new_retval;
+ hub->active_services--;
+ }
}
- } else {
- int retval = ipdbg_create_hub(tap, user_instruction, data_register_length, virtual_ir, &hub);
- if (retval != ERROR_OK)
- return retval;
+ struct ipdbg_hub *next_hub = hub->next;
+ int new_retval = ipdbg_remove_hub(hub);
+ if (new_retval != ERROR_OK)
+ retval = new_retval;
+ ipdbg_free_hub(hub);
+ hub = next_hub;
}
+ return retval;
+}
+
+static int ipdbg_start(struct ipdbg_hub *hub, uint16_t port, uint8_t tool)
+{
+ LOG_INFO("starting ipdbg service on port %d for tool %d", port, tool);
struct ipdbg_service *service = NULL;
int retval = ipdbg_create_service(hub, tool, &service, port);
@@ -790,82 +820,181 @@ static int ipdbg_start(uint16_t port, struct jtag_tap *tap, uint32_t user_instru
char port_str_buffer[IPDBG_TCP_PORT_STR_MAX_LENGTH];
snprintf(port_str_buffer, IPDBG_TCP_PORT_STR_MAX_LENGTH, "%u", port);
retval = add_service(&ipdbg_service_driver, port_str_buffer, 1, service);
- if (retval == ERROR_OK) {
- ipdbg_add_service(service);
- if (hub->active_services == 0 && hub->active_connections == 0)
- ipdbg_add_hub(hub);
- hub->active_services++;
- } else {
- if (hub->active_services == 0 && hub->active_connections == 0)
- ipdbg_free_hub(hub);
+ if (retval != ERROR_OK) {
free(service);
+ return retval;
}
+ ipdbg_add_service(service);
+ hub->active_services++;
+ return ERROR_OK;
+}
+COMMAND_HANDLER(handle_ipdbg_start_command)
+{
+ struct ipdbg_hub *hub = CMD_DATA;
+
+ uint16_t port = 4242;
+ uint8_t tool = 1;
+
+ if (CMD_ARGC > IPDBG_NUM_OF_START_OPTIONS)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ for (unsigned int i = 0; i < CMD_ARGC; ++i) {
+ if (strcmp(CMD_ARGV[i], "-port") == 0) {
+ COMMAND_PARSE_ADDITIONAL_NUMBER(u16, i, port, "port number");
+ } else if (strcmp(CMD_ARGV[i], "-tool") == 0) {
+ COMMAND_PARSE_ADDITIONAL_NUMBER(u8, i, tool, "tool");
+ } else {
+ command_print(CMD, "Unknown argument: %s", CMD_ARGV[i]);
+ return ERROR_FAIL;
+ }
+ }
+
+ return ipdbg_start(hub, port, tool);
+}
+
+static int ipdbg_stop(struct ipdbg_hub *hub, uint8_t tool)
+{
+ struct ipdbg_service *service = ipdbg_find_service(hub, tool);
+ if (!service) {
+ LOG_ERROR("No service for hub '%s'/tool %d found", hub->name, tool);
+ return ERROR_FAIL;
+ }
+
+ int retval = ipdbg_stop_service(service);
+ hub->active_services--;
+
+ LOG_INFO("stopped ipdbg service for tool %d", tool);
return retval;
}
-static int ipdbg_stop(struct jtag_tap *tap, uint32_t user_instruction,
- struct ipdbg_virtual_ir_info *virtual_ir, uint8_t tool)
+COMMAND_HANDLER(handle_ipdbg_stop_command)
{
- struct ipdbg_hub *hub = ipdbg_find_hub(tap, user_instruction, virtual_ir);
- free(virtual_ir);
- if (!hub)
+ struct ipdbg_hub *hub = CMD_DATA;
+
+ uint8_t tool = 1;
+
+ if (CMD_ARGC > IPDBG_NUM_OF_STOP_OPTIONS)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ for (unsigned int i = 0; i < CMD_ARGC; ++i) {
+ if (strcmp(CMD_ARGV[i], "-tool") == 0) {
+ COMMAND_PARSE_ADDITIONAL_NUMBER(u8, i, tool, "tool");
+ } else {
+ command_print(CMD, "Unknown argument: %s", CMD_ARGV[i]);
+ return ERROR_FAIL;
+ }
+ }
+
+ return ipdbg_stop(hub, tool);
+}
+
+static const struct command_registration ipdbg_hostserver_subcommand_handlers[] = {
+ {
+ .name = "start",
+ .mode = COMMAND_EXEC,
+ .handler = handle_ipdbg_start_command,
+ .help = "Starts a IPDBG Host server.",
+ .usage = "-tool number -port port"
+ }, {
+ .name = "stop",
+ .mode = COMMAND_EXEC,
+ .handler = handle_ipdbg_stop_command,
+ .help = "Stops a IPDBG Host server.",
+ .usage = "-tool number"
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration ipdbg_hub_subcommand_handlers[] = {
+ {
+ .name = "ipdbg",
+ .mode = COMMAND_EXEC,
+ .help = "IPDBG Hub commands.",
+ .usage = "",
+ .chain = ipdbg_hostserver_subcommand_handlers
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static int ipdbg_register_hub_command(struct ipdbg_hub *hub, struct command_invocation *cmd)
+{
+ Jim_Interp *interp = CMD_CTX->interp;
+
+ /* does this command exist? */
+ Jim_Cmd *jcmd = Jim_GetCommand(interp, Jim_NewStringObj(interp, hub->name, -1), JIM_NONE);
+ if (jcmd) {
+ LOG_ERROR("cannot create Hub because a command with name '%s' already exists", hub->name);
return ERROR_FAIL;
+ }
- struct ipdbg_service *service = ipdbg_find_service(hub, tool);
- if (!service)
+ const struct command_registration obj_commands[] = {
+ {
+ .name = hub->name,
+ .mode = COMMAND_EXEC,
+ .help = "IPDBG Hub command group.",
+ .usage = "",
+ .chain = ipdbg_hub_subcommand_handlers
+ },
+ COMMAND_REGISTRATION_DONE
+ };
+
+ return register_commands_with_data(CMD_CTX, NULL, obj_commands, hub);
+}
+
+static int ipdbg_create_hub(struct jtag_tap *tap, uint32_t user_instruction, uint8_t data_register_length,
+ struct ipdbg_virtual_ir_info *virtual_ir, const char *name, struct command_invocation *cmd)
+{
+ struct ipdbg_hub *new_hub = ipdbg_allocate_hub(data_register_length, virtual_ir, name);
+ if (!new_hub)
return ERROR_FAIL;
- int retval = ipdbg_remove_service(service);
- if (retval != ERROR_OK) {
- LOG_ERROR("BUG: ipdbg_remove_service failed");
- return retval;
- }
+ if (virtual_ir)
+ buf_set_u32(new_hub->scratch_memory.vir_out_val, 0, virtual_ir->length, virtual_ir->value);
+ new_hub->tap = tap;
+ new_hub->user_instruction = user_instruction;
+ new_hub->data_register_length = data_register_length;
+ new_hub->valid_mask = BIT(data_register_length - 1);
+ new_hub->xoff_mask = BIT(data_register_length - 2);
+ new_hub->tool_mask = (new_hub->xoff_mask - 1) >> 8;
+ new_hub->last_dn_tool = new_hub->tool_mask;
+ new_hub->virtual_ir = virtual_ir;
+ new_hub->max_tools = ipdbg_max_tools_from_data_register_length(data_register_length);
- char port_str_buffer[IPDBG_TCP_PORT_STR_MAX_LENGTH];
- snprintf(port_str_buffer, IPDBG_TCP_PORT_STR_MAX_LENGTH, "%u", service->port);
- retval = remove_service("ipdbg", port_str_buffer);
- /* The ipdbg_service structure is freed by server.c:remove_service().
- There the "priv" pointer is freed.*/
+ int retval = ipdbg_register_hub_command(new_hub, cmd);
if (retval != ERROR_OK) {
- LOG_ERROR("BUG: remove_service failed");
- return retval;
- }
- hub->active_services--;
- if (hub->active_connections == 0 && hub->active_services == 0) {
- retval = ipdbg_remove_hub(hub);
- if (retval != ERROR_OK) {
- LOG_ERROR("BUG: ipdbg_remove_hub failed");
- return retval;
- }
- ipdbg_free_hub(hub);
+ LOG_ERROR("Creating hub failed");
+ ipdbg_free_hub(new_hub);
+ return ERROR_FAIL;
}
+
+ ipdbg_add_hub(new_hub);
+
return ERROR_OK;
}
-COMMAND_HANDLER(handle_ipdbg_command)
+COMMAND_HANDLER(handle_ipdbg_create_hub_command)
{
struct jtag_tap *tap = NULL;
- uint16_t port = 4242;
- uint8_t tool = 1;
uint32_t user_instruction = 0x00;
uint8_t data_register_length = IPDBG_MAX_DR_LENGTH;
- bool start = true;
- bool hub_configured = false;
bool has_virtual_ir = false;
uint32_t virtual_ir_instruction = 0x00e;
uint32_t virtual_ir_length = 5;
uint32_t virtual_ir_value = 0x11;
struct ipdbg_virtual_ir_info *virtual_ir = NULL;
int user_num = 1;
+ bool hub_configured = false;
- if ((CMD_ARGC < IPDBG_MIN_NUM_OF_OPTIONS) || (CMD_ARGC > IPDBG_MAX_NUM_OF_OPTIONS))
+ if (CMD_ARGC < IPDBG_MIN_NUM_OF_CREATE_OPTIONS || CMD_ARGC > IPDBG_MAX_NUM_OF_CREATE_OPTIONS)
return ERROR_COMMAND_SYNTAX_ERROR;
- for (unsigned int i = 0; i < CMD_ARGC; ++i) {
+ const char *hub_name = CMD_ARGV[0];
+
+ for (unsigned int i = 1; i < CMD_ARGC; ++i) {
if (strcmp(CMD_ARGV[i], "-tap") == 0) {
if (i + 1 >= CMD_ARGC || CMD_ARGV[i + 1][0] == '-') {
- command_print(CMD, "no TAP given");
+ command_print(CMD, "no TAP name given");
return ERROR_FAIL;
}
tap = jtag_tap_by_string(CMD_ARGV[i + 1]);
@@ -874,7 +1003,7 @@ COMMAND_HANDLER(handle_ipdbg_command)
return ERROR_FAIL;
}
++i;
- } else if (strcmp(CMD_ARGV[i], "-hub") == 0) {
+ } else if (strcmp(CMD_ARGV[i], "-ir") == 0) {
COMMAND_PARSE_ADDITIONAL_NUMBER(u32, i, user_instruction, "ir_value to select hub");
hub_configured = true;
COMMAND_PARSE_OPTIONAL_NUMBER(u8, i, data_register_length);
@@ -917,20 +1046,11 @@ COMMAND_HANDLER(handle_ipdbg_command)
COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_length);
COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_instruction);
has_virtual_ir = true;
- } else if (strcmp(CMD_ARGV[i], "-port") == 0) {
- COMMAND_PARSE_ADDITIONAL_NUMBER(u16, i, port, "port number");
- } else if (strcmp(CMD_ARGV[i], "-tool") == 0) {
- COMMAND_PARSE_ADDITIONAL_NUMBER(u8, i, tool, "tool");
- } else if (strcmp(CMD_ARGV[i], "-stop") == 0) {
- start = false;
- } else if (strcmp(CMD_ARGV[i], "-start") == 0) {
- start = true;
} else {
command_print(CMD, "Unknown argument: %s", CMD_ARGV[i]);
return ERROR_FAIL;
}
}
-
if (!tap) {
command_print(CMD, "no valid tap selected");
return ERROR_FAIL;
@@ -941,8 +1061,8 @@ COMMAND_HANDLER(handle_ipdbg_command)
return ERROR_FAIL;
}
- if (tool >= ipdbg_max_tools_from_data_register_length(data_register_length)) {
- command_print(CMD, "Tool: %d is invalid", tool);
+ if (ipdbg_get_hub_by_name(hub_name)) {
+ LOG_ERROR("IPDBG hub with name '%s' already exists", hub_name);
return ERROR_FAIL;
}
@@ -957,20 +1077,38 @@ COMMAND_HANDLER(handle_ipdbg_command)
virtual_ir->value = virtual_ir_value;
}
- if (start)
- return ipdbg_start(port, tap, user_instruction, data_register_length, virtual_ir, tool);
- else
- return ipdbg_stop(tap, user_instruction, virtual_ir, tool);
+ if (ipdbg_find_hub(tap, user_instruction, virtual_ir)) {
+ LOG_ERROR("IPDBG hub for given TAP and user-instruction already exists");
+ free(virtual_ir);
+ return ERROR_FAIL;
+ }
+
+ int retval = ipdbg_create_hub(tap, user_instruction, data_register_length, virtual_ir, hub_name, cmd);
+ if (retval != ERROR_OK)
+ free(virtual_ir);
+
+ return retval;
}
+static const struct command_registration ipdbg_config_command_handlers[] = {
+ {
+ .name = "create-hub",
+ .mode = COMMAND_ANY,
+ .handler = handle_ipdbg_create_hub_command,
+ .help = "create a IPDBG Hub",
+ .usage = "name.ipdbghub (-tap device.tap -ir ir_value [dr_length] |"
+ " -pld name.pld [user]) [-vir [vir_value [length [instr_code]]]]",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
static const struct command_registration ipdbg_command_handlers[] = {
{
.name = "ipdbg",
- .handler = handle_ipdbg_command,
- .mode = COMMAND_EXEC,
- .help = "Starts or stops an IPDBG JTAG-Host server.",
- .usage = "[-start|-stop] -tap device.tap -hub ir_value [dr_length]"
- " [-port number] [-tool number] [-vir [vir_value [length [instr_code]]]]",
+ .mode = COMMAND_ANY,
+ .help = "IPDBG Hub/Host commands.",
+ .usage = "",
+ .chain = ipdbg_config_command_handlers,
},
COMMAND_REGISTRATION_DONE
};
diff --git a/src/server/ipdbg.h b/src/server/ipdbg.h
index 6b7054584..1f4156b7a 100644
--- a/src/server/ipdbg.h
+++ b/src/server/ipdbg.h
@@ -7,5 +7,6 @@
#include <helper/command.h>
int ipdbg_register_commands(struct command_context *cmd_ctx);
+int ipdbg_server_free(void);
#endif /* OPENOCD_IPDBG_IPDBG_H */
diff --git a/src/server/server.c b/src/server/server.c
index 2be90451f..0649ec942 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -23,6 +23,7 @@
#include "openocd.h"
#include "tcl_server.h"
#include "telnet_server.h"
+#include "ipdbg.h"
#include <signal.h>
@@ -714,6 +715,7 @@ void server_free(void)
tcl_service_free();
telnet_service_free();
jsp_service_free();
+ ipdbg_server_free();
free(bindto_name);
}
diff --git a/tcl/board/bemicro_cycloneiii.cfg b/tcl/board/bemicro_cycloneiii.cfg
index bd1459adc..3c92b500c 100644
--- a/tcl/board/bemicro_cycloneiii.cfg
+++ b/tcl/board/bemicro_cycloneiii.cfg
@@ -17,7 +17,8 @@ source [find fpga/altera-cycloneiii.cfg]
#quartus_cpf --option=bitstream_compression=off -c output_files\cycloneiii_blinker.sof cycloneiii_blinker.rbf
#openocd -f board/bemicro_cycloneiii.cfg -c "init" -c "pld load cycloneiii.pld cycloneiii_blinker.rbf"
-# "ipdbg -start -tap cycloneiii.tap -hub 0x00e -tool 0 -port 5555"
+# "ipdbg create-hub cycloneiii.ipdbghub -tap cycloneiii.tap -ir 0x00e"
+# "cycloneiii.ipdbghub ipdbg start -tool 0 -port 5555"
set JTAGSPI_CHAIN_ID cycloneiii.pld
diff --git a/tcl/board/digilent_cmod_s7.cfg b/tcl/board/digilent_cmod_s7.cfg
index c52ee9505..4fa45a17a 100644
--- a/tcl/board/digilent_cmod_s7.cfg
+++ b/tcl/board/digilent_cmod_s7.cfg
@@ -15,7 +15,8 @@ adapter speed 10000
source [find cpld/xilinx-xc7.cfg]
-# "ipdbg -start -tap xc7.tap -hub 0x02 -tool 0 -port 5555"
+# "ipdbg create-hub xc7.ipdbghub -tap xc7.tap -ir 0x02"
+# "xc7.ipdbghub ipdbg start -tool 0 -port 5555"
#openocd -f board/digilent_cmod_s7.cfg -c "init" -c "pld load xc7.pld shared_folder/cmod_s7_fast.bit"
set JTAGSPI_CHAIN_ID xc7.pld
diff --git a/tcl/board/ecp5_evaluation.cfg b/tcl/board/ecp5_evaluation.cfg
index dd663f79d..71769f607 100644
--- a/tcl/board/ecp5_evaluation.cfg
+++ b/tcl/board/ecp5_evaluation.cfg
@@ -16,7 +16,8 @@ adapter speed 6000
source [find fpga/lattice_ecp5.cfg]
#openocd -f board/ecp5_evaluation.cfg -c "init" -c "pld load ecp5.pld shared_folder/ecp5_blinker_impl1.bit"
-#ipdbg -start -tap ecp5.tap -hub 0x32 -port 5555 -tool 0
+#ipdbg create-hub ecp5.ipdbghub -tap ecp5.tap -ir 0x32
+#ecp5.ipdbghub ipdbg start -tool 0 -port 5555
set JTAGSPI_CHAIN_ID ecp5.pld
source [find cpld/jtagspi.cfg]
diff --git a/tcl/board/gowin_runber.cfg b/tcl/board/gowin_runber.cfg
index 9496c6f00..6cb07362b 100644
--- a/tcl/board/gowin_runber.cfg
+++ b/tcl/board/gowin_runber.cfg
@@ -16,4 +16,5 @@ source [find fpga/gowin_gw1n.cfg]
#openocd -f board/gowin_runber.cfg -c "init" -c "pld load 0 impl/pnr/gw1n_blinker.fs"
-#ipdbg -start -tap gw1n.tap -hub 0x42 -port 5555 -tool 0
+#ipdbg create-hub gw1n.ipdbghub -tap gw1n.tap -ir 0x42
+#gw1n.ipdbghubipdbg start -tool 0 -port 5555
diff --git a/tcl/board/trion_t20_bga256.cfg b/tcl/board/trion_t20_bga256.cfg
index dc76d3910..ca44f0b8c 100644
--- a/tcl/board/trion_t20_bga256.cfg
+++ b/tcl/board/trion_t20_bga256.cfg
@@ -20,7 +20,8 @@ adapter speed 6000
source [find fpga/efinix_trion.cfg]
#openocd -f board/trion_t20_bga256.cfg -c "init" -c "pld load trion.pld outflow/trion_blinker.bit"
-#ipdbg -start -tap trion.tap -hub 0x8 -port 5555 -tool 0
+#ipdbg create-hub trion.ipdbghub -tap trion.tap -ir 0x8
+#trion.ipdbghub ipdbg start -tool 0 -port 5555
set JTAGSPI_CHAIN_ID trion.pld
source [find cpld/jtagspi.cfg]
-----------------------------------------------------------------------
Summary of changes:
doc/openocd.texi | 75 ++++---
src/jtag/startup.tcl | 128 ++++++++++++
src/server/ipdbg.c | 416 ++++++++++++++++++++++++++-------------
src/server/ipdbg.h | 1 +
src/server/server.c | 2 +
tcl/board/bemicro_cycloneiii.cfg | 3 +-
tcl/board/digilent_cmod_s7.cfg | 3 +-
tcl/board/ecp5_evaluation.cfg | 3 +-
tcl/board/gowin_runber.cfg | 3 +-
tcl/board/trion_t20_bga256.cfg | 3 +-
10 files changed, 470 insertions(+), 167 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|