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
(68) |
Dec
(18) |
| 2026 |
Jan
(30) |
Feb
(31) |
Mar
(9) |
Apr
(44) |
May
(51) |
Jun
(20) |
Jul
(37) |
Aug
(18) |
Sep
(63) |
Oct
(51) |
Nov
|
Dec
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-23 04:26: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 c3cda13d215b1679817a492f54ef194212e01752 (commit)
from 87075a144bad4404a9d70884ce0b469575b9f0ae (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 c3cda13d215b1679817a492f54ef194212e01752
Author: Farid Khaydari <kha...@gm...>
Date: Tue Aug 18 16:55:01 2026 +0300
target/riscv: clear a stale MPRV on a physical progbuf access
Unless dcsr.mprven is reset, a physical request can be accidentally
translated due to stale mstatus.MPRV.
Change-Id: I849f8a655e1fbee10a728cdc0974af1d6390189d
Signed-off-by: Farid Khaydari <kha...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/9935
Tested-by: jenkins
Reviewed-by: Evgeniy Naydanov <eu...@gm...>
diff --git a/doc/openocd.texi b/doc/openocd.texi
index 7c8d36f06..faf65c8e6 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -12120,6 +12120,7 @@ read the respective entries). This is the default mode.
(Virtual memory access will fail with an error if the hardware doesn't
support the necessary functionality.)
@item @option{off} - Virtual addresses are not translated (identity mapping is assumed).
+An access in this mode behaves exactly like an explicitly physical one.
@end itemize
Returns current translation mode if called without arguments.
@end deffn
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index 9205d6ae3..48ea26b09 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -3319,23 +3319,22 @@ static int modify_privilege_progbuf(struct target *target, riscv_reg_t *mstatus,
assert(mstatush_old);
assert(dcsr);
assert(dcsr_old);
- if (mode == RISCV_MODE_M)
- return ERROR_OK;
if (riscv_reg_get(target, dcsr, GDB_REGNO_DCSR) != ERROR_OK)
return ERROR_FAIL;
*dcsr_old = *dcsr;
- if (set_mpp_mpv(target, mstatus, mstatus_old, mstatush, mstatush_old, mode) != ERROR_OK)
- return ERROR_FAIL;
-
- *dcsr = set_field(*dcsr, CSR_DCSR_MPRVEN, CSR_DCSR_MPRVEN_ENABLED);
+ *dcsr = set_field(*dcsr, CSR_DCSR_MPRVEN, mode == RISCV_MODE_M ?
+ CSR_DCSR_MPRVEN_DISABLED : CSR_DCSR_MPRVEN_ENABLED);
if (*dcsr != *dcsr_old &&
riscv_reg_set(target, GDB_REGNO_DCSR, *dcsr) != ERROR_OK)
return ERROR_FAIL;
- return ERROR_OK;
+ if (mode == RISCV_MODE_M)
+ return ERROR_OK;
+
+ return set_mpp_mpv(target, mstatus, mstatus_old, mstatush, mstatush_old, mode);
}
static int restore_privilege_progbuf(struct target *target, riscv_reg_t mstatus, riscv_reg_t mstatus_old,
-----------------------------------------------------------------------
Summary of changes:
doc/openocd.texi | 1 +
src/target/riscv/riscv-013.c | 13 ++++++-------
2 files changed, 7 insertions(+), 7 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-23 04:25:53
|
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 87075a144bad4404a9d70884ce0b469575b9f0ae (commit)
from d74275c08fbc87b13c85d0e2a9ad92784cdacb92 (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 87075a144bad4404a9d70884ce0b469575b9f0ae
Author: Farid Khaydari <kha...@gm...>
Date: Tue Aug 18 16:51:08 2026 +0300
target/riscv: fix progbuf privilege context setup
mstatus.MPV belongs to that context too. If not reset, can result in
host address being interpreted as the guest one.
mstatus update/restore separated into a helper for future reuse by
abstract command memory access.
Change-Id: I440b5ab6979afd6bba3931a9e01a091cb3571c26
Signed-off-by: Farid Khaydari <kha...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/9934
Reviewed-by: Evgeniy Naydanov <eu...@gm...>
Tested-by: jenkins
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index d1885786f..9205d6ae3 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -3255,46 +3255,82 @@ static int read_sbcs_nonbusy(struct target *target, uint32_t *sbcs)
}
}
+static int set_mpp_mpv(struct target *target, riscv_reg_t *mstatus,
+ riscv_reg_t *mstatus_old, riscv_reg_t *mstatush,
+ riscv_reg_t *mstatush_old, enum riscv_priv_mode mode)
+{
+ assert(mstatus);
+ assert(mstatus_old);
+ assert(mstatush);
+ assert(mstatush_old);
+
+ if (riscv_reg_get(target, mstatus, GDB_REGNO_MSTATUS) != ERROR_OK)
+ return ERROR_FAIL;
+ *mstatus_old = *mstatus;
+
+ *mstatus = set_field(*mstatus, MSTATUS_MPRV, 1);
+ *mstatus = set_field(*mstatus, MSTATUS_MPP, riscv_priv_mode_to_prv(mode));
+
+ /* The caller refuses a guest access, so MPV is cleared. */
+ if (riscv_supports_extension(target, 'H')) {
+ if (riscv_xlen(target) == 32) {
+ if (riscv_reg_get(target, mstatush, GDB_REGNO_MSTATUSH) != ERROR_OK)
+ return ERROR_FAIL;
+ *mstatush_old = *mstatush;
+ *mstatush = set_field(*mstatush, MSTATUSH_MPV, 0);
+ } else {
+ *mstatus = set_field(*mstatus, MSTATUS_MPV, 0);
+ }
+ }
+
+ if (*mstatus != *mstatus_old &&
+ riscv_reg_set(target, GDB_REGNO_MSTATUS, *mstatus) != ERROR_OK)
+ return ERROR_FAIL;
+
+ if (*mstatush != *mstatush_old &&
+ riscv_reg_set(target, GDB_REGNO_MSTATUSH, *mstatush) != ERROR_OK)
+ return ERROR_FAIL;
+
+ return ERROR_OK;
+}
+
+static int restore_mpp_mpv(struct target *target, riscv_reg_t mstatus,
+ riscv_reg_t mstatus_old, riscv_reg_t mstatush, riscv_reg_t mstatush_old)
+{
+ if (mstatus != mstatus_old &&
+ riscv_reg_set(target, GDB_REGNO_MSTATUS, mstatus_old) != ERROR_OK)
+ return ERROR_FAIL;
+
+ if (mstatush != mstatush_old &&
+ riscv_reg_set(target, GDB_REGNO_MSTATUSH, mstatush_old) != ERROR_OK)
+ return ERROR_FAIL;
+
+ return ERROR_OK;
+}
+
/* TODO: return struct mem_access_result */
-static int modify_privilege_for_virt2phys_mode(struct target *target, riscv_reg_t *mstatus, riscv_reg_t *mstatus_old,
+static int modify_privilege_progbuf(struct target *target, riscv_reg_t *mstatus,
+ riscv_reg_t *mstatus_old, riscv_reg_t *mstatush, riscv_reg_t *mstatush_old,
riscv_reg_t *dcsr, riscv_reg_t *dcsr_old, enum riscv_priv_mode mode)
{
assert(mstatus);
assert(mstatus_old);
+ assert(mstatush);
+ assert(mstatush_old);
assert(dcsr);
assert(dcsr_old);
if (mode == RISCV_MODE_M)
return ERROR_OK;
- /* Read and save DCSR */
if (riscv_reg_get(target, dcsr, GDB_REGNO_DCSR) != ERROR_OK)
return ERROR_FAIL;
*dcsr_old = *dcsr;
- /* Read and save MSTATUS */
- if (riscv_reg_get(target, mstatus, GDB_REGNO_MSTATUS) != ERROR_OK)
+ if (set_mpp_mpv(target, mstatus, mstatus_old, mstatush, mstatush_old, mode) != ERROR_OK)
return ERROR_FAIL;
- *mstatus_old = *mstatus;
- /* If we come from m-mode with mprv set, we want to keep mpp */
- if (get_field(*dcsr, CSR_DCSR_PRV) == PRV_M)
- return ERROR_OK;
-
- /* mstatus.mpp <- dcsr.prv */
- *mstatus = set_field(*mstatus, MSTATUS_MPP, get_field(*dcsr, CSR_DCSR_PRV));
-
- /* mstatus.mprv <- 1 */
- *mstatus = set_field(*mstatus, MSTATUS_MPRV, 1);
-
- /* Write MSTATUS */
- if (*mstatus != *mstatus_old &&
- riscv_reg_set(target, GDB_REGNO_MSTATUS, *mstatus) != ERROR_OK)
- return ERROR_FAIL;
-
- /* dcsr.mprven <- 1 */
*dcsr = set_field(*dcsr, CSR_DCSR_MPRVEN, CSR_DCSR_MPRVEN_ENABLED);
- /* Write DCSR */
if (*dcsr != *dcsr_old &&
riscv_reg_set(target, GDB_REGNO_DCSR, *dcsr) != ERROR_OK)
return ERROR_FAIL;
@@ -3302,15 +3338,12 @@ static int modify_privilege_for_virt2phys_mode(struct target *target, riscv_reg_
return ERROR_OK;
}
-static int restore_privilege_from_virt2phys_mode(struct target *target, riscv_reg_t mstatus, riscv_reg_t mstatus_old,
- riscv_reg_t dcsr, riscv_reg_t dcsr_old)
+static int restore_privilege_progbuf(struct target *target, riscv_reg_t mstatus, riscv_reg_t mstatus_old,
+ riscv_reg_t mstatush, riscv_reg_t mstatush_old, riscv_reg_t dcsr, riscv_reg_t dcsr_old)
{
- /* Restore MSTATUS */
- if (mstatus != mstatus_old &&
- riscv_reg_set(target, GDB_REGNO_MSTATUS, mstatus_old) != ERROR_OK)
+ if (restore_mpp_mpv(target, mstatus, mstatus_old, mstatush, mstatush_old) != ERROR_OK)
return ERROR_FAIL;
- /* Restore DCSR */
if (dcsr != dcsr_old &&
riscv_reg_set(target, GDB_REGNO_DCSR, dcsr_old) != ERROR_OK)
return ERROR_FAIL;
@@ -4555,18 +4588,20 @@ access_memory_progbuf(struct target *target, const struct riscv_mem_access_args
riscv_reg_t mstatus = 0;
riscv_reg_t mstatus_old = 0;
+ riscv_reg_t mstatush = 0;
+ riscv_reg_t mstatush_old = 0;
riscv_reg_t dcsr = 0;
riscv_reg_t dcsr_old = 0;
- if (modify_privilege_for_virt2phys_mode(target,
- &mstatus, &mstatus_old, &dcsr, &dcsr_old, args.mode) != ERROR_OK)
+ if (modify_privilege_progbuf(target, &mstatus, &mstatus_old, &mstatush,
+ &mstatush_old, &dcsr, &dcsr_old, args.mode) != ERROR_OK)
return mem_access_result(MEM_ACCESS_SKIPPED_PRIV_MOD_FAILED);
struct mem_access_result result = is_read ?
read_memory_progbuf(target, args) :
write_memory_progbuf(target, args);
- if (restore_privilege_from_virt2phys_mode(target,
- mstatus, mstatus_old, dcsr, dcsr_old) != ERROR_OK)
+ if (restore_privilege_progbuf(target, mstatus, mstatus_old,
+ mstatush, mstatush_old, dcsr, dcsr_old) != ERROR_OK)
return mem_access_result(MEM_ACCESS_FAILED_PRIV_MOD_FAILED);
return result;
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
index c2e34a548..508d212db 100644
--- a/src/target/riscv/riscv.h
+++ b/src/target/riscv/riscv.h
@@ -376,6 +376,23 @@ struct riscv_info {
bool autofence;
};
+static inline riscv_reg_t riscv_priv_mode_to_prv(enum riscv_priv_mode mode)
+{
+ switch (mode) {
+ case RISCV_MODE_M:
+ return PRV_M;
+ case RISCV_MODE_S:
+ case RISCV_MODE_VS:
+ return PRV_S;
+ case RISCV_MODE_U:
+ case RISCV_MODE_VU:
+ return PRV_U;
+ default:
+ assert(false);
+ return PRV_M;
+ }
+}
+
struct riscv_private_config {
bool dcsr_ebreak_fields[N_RISCV_MODE];
bool dcsr_cetrig;
-----------------------------------------------------------------------
Summary of changes:
src/target/riscv/riscv-013.c | 99 ++++++++++++++++++++++++++++++--------------
src/target/riscv/riscv.h | 17 ++++++++
2 files changed, 84 insertions(+), 32 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-23 04:24: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 d74275c08fbc87b13c85d0e2a9ad92784cdacb92 (commit)
from 54129082562d3d31568df8ba89bfc179add13f7f (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 d74275c08fbc87b13c85d0e2a9ad92784cdacb92
Author: Farid Khaydari <kha...@gm...>
Date: Thu Aug 13 14:34:57 2026 +0300
target/riscv: carry the privilege mode in memory access args
The address space used to be implied by the virt2phys mode, so a
physical request in riscv virt2phys_mode hw was translated and the
system bus served a virtual one untranslated.
Change-Id: I689588ddc79b3427c054a26ac3e4db8ceea3f7df
Signed-off-by: Farid Khaydari <kha...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/9933
Reviewed-by: Evgeniy Naydanov <eu...@gm...>
Tested-by: jenkins
diff --git a/doc/openocd.texi b/doc/openocd.texi
index b89bea0d8..7c8d36f06 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -12069,6 +12069,8 @@ dump_sample_buf}.
Quickly read count words of the given size from address. This can be useful
to read out a buffer that's memory-mapped to be accessed through a single
address, or to sample a changing value in a memory-mapped device.
+
+The address is physical.
@end deffn
@deffn {Command} {riscv info}
diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c
index 8294b82d8..d4aa87947 100644
--- a/src/target/riscv/riscv-011.c
+++ b/src/target/riscv/riscv-011.c
@@ -2341,6 +2341,13 @@ static int access_memory(struct target *target, const struct riscv_mem_access_ar
{
assert(riscv_mem_access_is_valid(args));
const bool is_write = riscv_mem_access_is_write(args);
+
+ if (args.mode != RISCV_MODE_M) {
+ LOG_TARGET_ERROR(target, "Memory %s: hardware address translation is not "
+ "supported for RISC-V Debug Spec v0.11 targets", is_write ? "write" : "read");
+ return ERROR_FAIL;
+ }
+
if (is_write)
return write_memory(target, args);
return read_memory(target, args);
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index 96033af6f..d1885786f 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -1304,6 +1304,7 @@ static int scratch_read64(struct target *target, scratch_mem_t *scratch,
uint8_t buffer[8] = {0};
const struct riscv_mem_access_args args = {
.address = scratch->debug_address,
+ .mode = RISCV_MODE_M,
.read_buffer = buffer,
.size = 4,
.count = 2,
@@ -1346,6 +1347,7 @@ static int scratch_write64(struct target *target, scratch_mem_t *scratch,
};
const struct riscv_mem_access_args args = {
.address = scratch->debug_address,
+ .mode = RISCV_MODE_M,
.write_buffer = buffer,
.size = 4,
.count = 2,
@@ -3255,13 +3257,13 @@ static int read_sbcs_nonbusy(struct target *target, uint32_t *sbcs)
/* TODO: return struct mem_access_result */
static int modify_privilege_for_virt2phys_mode(struct target *target, riscv_reg_t *mstatus, riscv_reg_t *mstatus_old,
- riscv_reg_t *dcsr, riscv_reg_t *dcsr_old)
+ riscv_reg_t *dcsr, riscv_reg_t *dcsr_old, enum riscv_priv_mode mode)
{
assert(mstatus);
assert(mstatus_old);
assert(dcsr);
assert(dcsr_old);
- if (!riscv_virt2phys_mode_is_hw(target))
+ if (mode == RISCV_MODE_M)
return ERROR_OK;
/* Read and save DCSR */
@@ -3303,9 +3305,6 @@ static int modify_privilege_for_virt2phys_mode(struct target *target, riscv_reg_
static int restore_privilege_from_virt2phys_mode(struct target *target, riscv_reg_t mstatus, riscv_reg_t mstatus_old,
riscv_reg_t dcsr, riscv_reg_t dcsr_old)
{
- if (!riscv_virt2phys_mode_is_hw(target))
- return ERROR_OK;
-
/* Restore MSTATUS */
if (mstatus != mstatus_old &&
riscv_reg_set(target, GDB_REGNO_MSTATUS, mstatus_old) != ERROR_OK)
@@ -3627,6 +3626,8 @@ enum mem_access_result_type {
SKIPPED, "skipped (abstract command argument write failed)") \
MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_PRIV_MOD_FAILED, \
SKIPPED, "skipped (privilege modification failed)") \
+ MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_NO_HW_TRANSLATION, \
+ SKIPPED, "skipped (backend cannot translate a virtual address)") \
MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED, FAILED, "failed") \
MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED_DM_ACCESS_FAILED, \
FAILED, "failed (DM register access failed)") \
@@ -3778,6 +3779,12 @@ mem_should_skip_sysbus(struct target *target, const struct riscv_mem_access_args
const bool is_read = riscv_mem_access_is_read(args);
const char *const access_type = is_read ? "read" : "write";
+ if (args.mode != RISCV_MODE_M) {
+ LOG_TARGET_DEBUG(target, "Skipping mem %s via system bus - "
+ "no hardware address translation for a virtual address", access_type);
+ return mem_access_result(MEM_ACCESS_SKIPPED_NO_HW_TRANSLATION);
+ }
+
if (!sba_supports_access(target, args.size)) {
LOG_TARGET_DEBUG(target, "Skipping mem %s via system bus - "
"unsupported size.", access_type);
@@ -3809,6 +3816,12 @@ mem_should_skip_abstract(struct target *target, const struct riscv_mem_access_ar
const bool is_read = riscv_mem_access_is_read(args);
const char *const access_type = is_read ? "read" : "write";
+ if (args.mode != RISCV_MODE_M) {
+ /* Temporary, until aamvirtual support lands. */
+ LOG_TARGET_DEBUG(target, "Skipping mem %s via abstract access - "
+ "virtual access (aamvirtual) not implemented yet", access_type);
+ return mem_access_result(MEM_ACCESS_SKIPPED_NO_HW_TRANSLATION);
+ }
if (args.size > 8) {
/* TODO: Add 128b support if it's ever used. Involves modifying
read/write_abstract_arg() to work on two 64b values. */
@@ -4545,7 +4558,7 @@ access_memory_progbuf(struct target *target, const struct riscv_mem_access_args
riscv_reg_t dcsr = 0;
riscv_reg_t dcsr_old = 0;
if (modify_privilege_for_virt2phys_mode(target,
- &mstatus, &mstatus_old, &dcsr, &dcsr_old) != ERROR_OK)
+ &mstatus, &mstatus_old, &dcsr, &dcsr_old, args.mode) != ERROR_OK)
return mem_access_result(MEM_ACCESS_SKIPPED_PRIV_MOD_FAILED);
struct mem_access_result result = is_read ?
@@ -4618,6 +4631,10 @@ riscv013_access_memory(struct target *target, const struct riscv_mem_access_args
const bool is_read = riscv_mem_access_is_read(args);
const char *const access_type = is_read ? "read" : "write";
+ LOG_TARGET_DEBUG(target, "Memory %s: addr=0x%" TARGET_PRIxADDR
+ " (%s), size=%" PRIu32 ", count=%" PRIu32 ", increment=%" PRIu32,
+ access_type, args.address, args.mode == RISCV_MODE_M ? "physical" : "virtual",
+ args.size, args.count, args.increment);
if (!is_read && args.increment != args.size) {
LOG_TARGET_ERROR(target, "Write increment size has to be equal to element size");
return ERROR_NOT_IMPLEMENTED;
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index f527f9549..3ddd75275 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -142,20 +142,26 @@ struct tdata1_cache {
struct list_head elem_tdata1;
};
-bool riscv_virt2phys_mode_is_hw(const struct target *target)
+static bool riscv_virt2phys_mode_is_hw(const struct target *target)
{
assert(target);
RISCV_INFO(r);
return r->virt2phys_mode == RISCV_VIRT2PHYS_MODE_HW;
}
-bool riscv_virt2phys_mode_is_sw(const struct target *target)
+static bool riscv_virt2phys_mode_is_sw(const struct target *target)
{
assert(target);
RISCV_INFO(r);
return r->virt2phys_mode == RISCV_VIRT2PHYS_MODE_SW;
}
+static bool riscv_virt2phys_mode_is_off(const struct target *target)
+{
+ assert(target);
+ return riscv_info(target)->virt2phys_mode == RISCV_VIRT2PHYS_MODE_OFF;
+}
+
const char *riscv_virt2phys_mode_to_str(enum riscv_virt2phys_mode mode)
{
assert(mode == RISCV_VIRT2PHYS_MODE_OFF
@@ -3109,20 +3115,14 @@ static int riscv_effective_privilege_mode(struct target *target, enum riscv_priv
return ERROR_OK;
}
-static int riscv_mmu(struct target *target, bool *enabled)
+static int riscv_mmu_impl(struct target *target,
+ enum riscv_priv_mode mode, bool *enabled)
{
assert(target);
assert(enabled);
*enabled = false;
- if (!riscv_virt2phys_mode_is_sw(target))
- return ERROR_OK;
-
- enum riscv_priv_mode mode = RISCV_MODE_M;
- if (riscv_effective_privilege_mode(target, &mode) != ERROR_OK)
- return ERROR_FAIL;
-
if (mode == RISCV_MODE_M) {
LOG_TARGET_DEBUG(target, "SATP/MMU ignored in Machine mode");
return ERROR_OK;
@@ -3177,6 +3177,23 @@ static int riscv_mmu(struct target *target, bool *enabled)
return ERROR_OK;
}
+static int riscv_mmu(struct target *target, bool *enabled)
+{
+ assert(target);
+ assert(enabled);
+
+ *enabled = false;
+
+ if (!riscv_virt2phys_mode_is_sw(target))
+ return ERROR_OK;
+
+ enum riscv_priv_mode mode = RISCV_MODE_M;
+ if (riscv_effective_privilege_mode(target, &mode) != ERROR_OK)
+ return ERROR_FAIL;
+
+ return riscv_mmu_impl(target, mode, enabled);
+}
+
/* Translate address from virtual to physical, using info and ppn.
* If extra_info is non-NULL, then translate page table accesses for the primary
* translation using extra_info and extra_ppn. */
@@ -3220,6 +3237,7 @@ static int riscv_address_translate(struct target *target,
assert(info->pte_shift <= 3);
const struct riscv_mem_access_args args = {
.address = pte_address,
+ .mode = RISCV_MODE_M,
.read_buffer = buffer,
.size = 4,
.increment = 4,
@@ -3387,12 +3405,11 @@ static int riscv_virt2phys_v(struct target *target, target_addr_t virtual, targe
static int riscv_virt2phys(struct target *target, target_addr_t virtual, target_addr_t *physical)
{
- bool enabled;
- if (riscv_mmu(target, &enabled) != ERROR_OK)
- return ERROR_FAIL;
- if (!enabled) {
+ /* TODO: translate the address in the other modes as well. */
+ if (!riscv_virt2phys_mode_is_sw(target)) {
*physical = virtual;
- LOG_TARGET_DEBUG(target, "MMU is disabled. 0x%" TARGET_PRIxADDR " -> 0x%" TARGET_PRIxADDR, virtual, *physical);
+ LOG_TARGET_DEBUG(target, "Address translation is off. 0x%" TARGET_PRIxADDR
+ " -> 0x%" TARGET_PRIxADDR, virtual, *physical);
return ERROR_OK;
}
@@ -3400,6 +3417,15 @@ static int riscv_virt2phys(struct target *target, target_addr_t virtual, target_
if (riscv_effective_privilege_mode(target, &mode) != ERROR_OK)
return ERROR_FAIL;
+ bool enabled = false;
+ if (riscv_mmu_impl(target, mode, &enabled) != ERROR_OK)
+ return ERROR_FAIL;
+ if (!enabled) {
+ *physical = virtual;
+ LOG_TARGET_DEBUG(target, "MMU is disabled. 0x%" TARGET_PRIxADDR " -> 0x%" TARGET_PRIxADDR, virtual, *physical);
+ return ERROR_OK;
+ }
+
if (riscv_priv_mode_is_guest(mode))
return riscv_virt2phys_v(target, virtual, physical);
@@ -3461,6 +3487,7 @@ static int riscv_read_phys_memory(struct target *target, target_addr_t phys_addr
{
const struct riscv_mem_access_args args = {
.address = phys_address,
+ .mode = RISCV_MODE_M,
.read_buffer = buffer,
.size = size,
.count = count,
@@ -3475,6 +3502,7 @@ static int riscv_write_phys_memory(struct target *target, target_addr_t phys_add
{
const struct riscv_mem_access_args args = {
.address = phys_address,
+ .mode = RISCV_MODE_M,
.write_buffer = buffer,
.size = size,
.count = count,
@@ -3485,7 +3513,7 @@ static int riscv_write_phys_memory(struct target *target, target_addr_t phys_add
return r->access_memory(target, args);
}
-static int riscv_rw_memory(struct target *target, const struct riscv_mem_access_args args)
+static int riscv_rw_memory(struct target *target, struct riscv_mem_access_args args)
{
assert(riscv_mem_access_is_valid(args));
@@ -3496,12 +3524,34 @@ static int riscv_rw_memory(struct target *target, const struct riscv_mem_access_
return ERROR_OK;
}
- bool mmu_enabled;
- int result = riscv_mmu(target, &mmu_enabled);
+ struct riscv_info *r = riscv_info(target);
+
+ args.mode = RISCV_MODE_M;
+
+ if (riscv_virt2phys_mode_is_off(target))
+ return r->access_memory(target, args);
+
+ enum riscv_priv_mode mode = RISCV_MODE_M;
+ if (riscv_effective_privilege_mode(target, &mode) != ERROR_OK)
+ return ERROR_FAIL;
+
+ if (riscv_virt2phys_mode_is_hw(target)) {
+ if (riscv_priv_mode_is_guest(mode)) {
+ LOG_TARGET_ERROR(target, "Cannot translate a guest access in "
+ "hardware: OpenOCD does not set mstatus.MPV yet. "
+ "Use 'riscv virt2phys_mode sw'.");
+ return ERROR_FAIL;
+ }
+
+ args.mode = mode;
+ return r->access_memory(target, args);
+ }
+
+ bool mmu_enabled = false;
+ int result = riscv_mmu_impl(target, mode, &mmu_enabled);
if (result != ERROR_OK)
return result;
- RISCV_INFO(r);
if (!mmu_enabled)
return r->access_memory(target, args);
@@ -5350,6 +5400,7 @@ COMMAND_HANDLER(handle_repeat_read)
}
const struct riscv_mem_access_args args = {
.address = address,
+ .mode = RISCV_MODE_M,
.read_buffer = buffer,
.size = size,
.count = count,
@@ -5746,7 +5797,7 @@ static const struct command_registration riscv_exec_command_handlers[] = {
.handler = handle_repeat_read,
.mode = COMMAND_ANY,
.usage = "count address [size=4]",
- .help = "Repeatedly read the value at address."
+ .help = "Repeatedly read the value at the given physical address."
},
{
.name = "set_command_timeout_sec",
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
index c2e727fc9..c2e34a548 100644
--- a/src/target/riscv/riscv.h
+++ b/src/target/riscv/riscv.h
@@ -132,8 +132,18 @@ struct reg_name_table {
char **reg_names;
};
+enum riscv_priv_mode {
+ RISCV_MODE_M,
+ RISCV_MODE_S,
+ RISCV_MODE_U,
+ RISCV_MODE_VS,
+ RISCV_MODE_VU,
+ N_RISCV_MODE
+};
+
struct riscv_mem_access_args {
target_addr_t address;
+ enum riscv_priv_mode mode;
const uint8_t *write_buffer;
uint8_t *read_buffer;
@@ -366,15 +376,6 @@ struct riscv_info {
bool autofence;
};
-enum riscv_priv_mode {
- RISCV_MODE_M,
- RISCV_MODE_S,
- RISCV_MODE_U,
- RISCV_MODE_VS,
- RISCV_MODE_VU,
- N_RISCV_MODE
-};
-
struct riscv_private_config {
bool dcsr_ebreak_fields[N_RISCV_MODE];
bool dcsr_cetrig;
@@ -409,9 +410,6 @@ typedef struct {
unsigned int pa_ppn_mask[PG_MAX_LEVEL];
} virt2phys_info_t;
-bool riscv_virt2phys_mode_is_hw(const struct target *target);
-bool riscv_virt2phys_mode_is_sw(const struct target *target);
-
/* Wall-clock timeout for a command/access. Settable via RISC-V Target commands.*/
int riscv_get_command_timeout_sec(void);
-----------------------------------------------------------------------
Summary of changes:
doc/openocd.texi | 2 +
src/target/riscv/riscv-011.c | 7 ++++
src/target/riscv/riscv-013.c | 29 +++++++++++---
src/target/riscv/riscv.c | 91 ++++++++++++++++++++++++++++++++++----------
src/target/riscv/riscv.h | 22 +++++------
5 files changed, 113 insertions(+), 38 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-23 04:23:26
|
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 54129082562d3d31568df8ba89bfc179add13f7f (commit)
from 5088db4c9154ca833c6d558381074b33672e127a (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 54129082562d3d31568df8ba89bfc179add13f7f
Author: Farid Khaydari <kha...@gm...>
Date: Mon Aug 3 01:36:03 2026 +0300
target/riscv: uniform memory access context derivation
The privilege mode was derived twice, and the two disagreed:
the software page walk prioritized mstatus.MPRV and
mstatus.MPP over dcsr.PRV, contrary to the program buffer.
The program buffer rule is adopted.
Change-Id: Icd7a7d7ad41a46f61c678b736aa10c359c26ecb6
Signed-off-by: Farid Khaydari <kha...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/9932
Tested-by: jenkins
Reviewed-by: Evgeniy Naydanov <eu...@gm...>
diff --git a/src/target/riscv/gdb_regs.h b/src/target/riscv/gdb_regs.h
index 79c24367f..cb2b58174 100644
--- a/src/target/riscv/gdb_regs.h
+++ b/src/target/riscv/gdb_regs.h
@@ -101,6 +101,7 @@ enum gdb_regno {
GDB_REGNO_DSCRATCH0 = CSR_DSCRATCH0 + GDB_REGNO_CSR0,
GDB_REGNO_DSCRATCH1 = CSR_DSCRATCH1 + GDB_REGNO_CSR0,
GDB_REGNO_MSTATUS = CSR_MSTATUS + GDB_REGNO_CSR0,
+ GDB_REGNO_MSTATUSH = CSR_MSTATUSH + GDB_REGNO_CSR0,
GDB_REGNO_MEPC = CSR_MEPC + GDB_REGNO_CSR0,
GDB_REGNO_MCAUSE = CSR_MCAUSE + GDB_REGNO_CSR0,
GDB_REGNO_SATP = CSR_SATP + GDB_REGNO_CSR0,
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index 0af412c71..f527f9549 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -3021,59 +3021,121 @@ static int riscv_target_resume(struct target *target, bool current,
debug_execution, false);
}
-static int riscv_effective_privilege_mode(struct target *target, int *v_mode, int *effective_mode)
+static const char *riscv_priv_mode_to_str(enum riscv_priv_mode mode)
{
+ switch (mode) {
+ case RISCV_MODE_M:
+ return "M";
+ case RISCV_MODE_S:
+ return "S";
+ case RISCV_MODE_U:
+ return "U";
+ case RISCV_MODE_VS:
+ return "VS";
+ case RISCV_MODE_VU:
+ return "VU";
+ case N_RISCV_MODE:
+ break;
+ }
+ assert(false && "Unknown privilege mode");
+ return "?";
+}
+
+static bool riscv_priv_mode_is_guest(enum riscv_priv_mode mode)
+{
+ return mode == RISCV_MODE_VS || mode == RISCV_MODE_VU;
+}
+
+static int riscv_effective_privilege_mode(struct target *target, enum riscv_priv_mode *mode)
+{
+ assert(target);
+ assert(mode);
+
riscv_reg_t priv;
if (riscv_reg_get(target, &priv, GDB_REGNO_PRIV) != ERROR_OK) {
LOG_TARGET_ERROR(target, "Failed to read priv register.");
return ERROR_FAIL;
}
- *v_mode = get_field(priv, VIRT_PRIV_V);
- riscv_reg_t mstatus;
- if (riscv_reg_get(target, &mstatus, GDB_REGNO_MSTATUS) != ERROR_OK) {
+ unsigned int dcsr_prv = get_field(priv, VIRT_PRIV_PRV);
+ bool halted_in_m = dcsr_prv == PRV_M;
+
+ /* MPRV only applies in Machine mode, so below it mstatus says nothing
+ * about the mode an access runs in. */
+ riscv_reg_t mstatus = 0;
+ if (halted_in_m
+ && riscv_reg_get(target, &mstatus, GDB_REGNO_MSTATUS) != ERROR_OK) {
LOG_TARGET_ERROR(target, "Failed to read mstatus register.");
return ERROR_FAIL;
}
- if (get_field(mstatus, MSTATUS_MPRV))
- *effective_mode = get_field(mstatus, MSTATUS_MPP);
- else
- *effective_mode = get_field(priv, VIRT_PRIV_PRV);
+ bool mprv = halted_in_m && get_field(mstatus, MSTATUS_MPRV);
+ unsigned int prv = mprv ? get_field(mstatus, MSTATUS_MPP) : dcsr_prv;
- LOG_TARGET_DEBUG(target, "Effective mode=%d; v=%d", *effective_mode, *v_mode);
+ /* MPV is ignored where MPP names Machine mode, so v is not read there. */
+ if (prv == PRV_M) {
+ *mode = RISCV_MODE_M;
+ LOG_TARGET_DEBUG(target, "Effective privilege mode: %s", riscv_priv_mode_to_str(*mode));
+ return ERROR_OK;
+ }
+ bool v = false;
+ if (!mprv) {
+ v = get_field(priv, VIRT_PRIV_V);
+ } else if (!riscv_supports_extension(target, 'H')) {
+ v = false;
+ } else if (riscv_xlen(target) != 32) {
+ v = get_field(mstatus, MSTATUS_MPV);
+ } else {
+ riscv_reg_t mstatush;
+ if (riscv_reg_get(target, &mstatush, GDB_REGNO_MSTATUSH) != ERROR_OK) {
+ LOG_TARGET_ERROR(target, "Failed to read mstatush register");
+ return ERROR_FAIL;
+ }
+ v = get_field(mstatush, MSTATUSH_MPV);
+ }
+
+ if (prv == PRV_S) {
+ *mode = v ? RISCV_MODE_VS : RISCV_MODE_S;
+ } else if (prv == PRV_U) {
+ *mode = v ? RISCV_MODE_VU : RISCV_MODE_U;
+ } else {
+ LOG_TARGET_ERROR(target, "Hart reports a reserved privilege mode %u in %s, "
+ "which is a hardware bug", prv, mprv ? "mstatus.MPP" : "dcsr.prv");
+ return ERROR_FAIL;
+ }
+
+ LOG_TARGET_DEBUG(target, "Effective privilege mode: %s", riscv_priv_mode_to_str(*mode));
return ERROR_OK;
}
static int riscv_mmu(struct target *target, bool *enabled)
{
+ assert(target);
+ assert(enabled);
+
*enabled = false;
if (!riscv_virt2phys_mode_is_sw(target))
return ERROR_OK;
- /* Don't use MMU in explicit or effective M (machine) mode */
- riscv_reg_t priv;
- if (riscv_reg_get(target, &priv, GDB_REGNO_PRIV) != ERROR_OK) {
- LOG_TARGET_ERROR(target, "Failed to read priv register.");
+ enum riscv_priv_mode mode = RISCV_MODE_M;
+ if (riscv_effective_privilege_mode(target, &mode) != ERROR_OK)
return ERROR_FAIL;
- }
- int effective_mode;
- int v_mode;
- if (riscv_effective_privilege_mode(target, &v_mode, &effective_mode) != ERROR_OK)
- return ERROR_FAIL;
+ if (mode == RISCV_MODE_M) {
+ LOG_TARGET_DEBUG(target, "SATP/MMU ignored in Machine mode");
+ return ERROR_OK;
+ }
unsigned int xlen = riscv_xlen(target);
- if (v_mode) {
+ if (riscv_priv_mode_is_guest(mode)) {
/* In VU or VS mode, MMU is considered enabled when
* either hgatp or vsatp mode is not OFF */
riscv_reg_t vsatp;
if (riscv_reg_get(target, &vsatp, GDB_REGNO_VSATP) != ERROR_OK) {
- LOG_TARGET_ERROR(target, "Failed to read vsatp register; priv=0x%" PRIx64,
- priv);
+ LOG_TARGET_ERROR(target, "Failed to read vsatp register");
return ERROR_FAIL;
}
/* vsatp is identical to satp, so we can use the satp macros. */
@@ -3085,8 +3147,7 @@ static int riscv_mmu(struct target *target, bool *enabled)
riscv_reg_t hgatp;
if (riscv_reg_get(target, &hgatp, GDB_REGNO_HGATP) != ERROR_OK) {
- LOG_TARGET_ERROR(target, "Failed to read hgatp register; priv=0x%" PRIx64,
- priv);
+ LOG_TARGET_ERROR(target, "Failed to read hgatp register");
return ERROR_FAIL;
}
if (get_field(hgatp, RISCV_HGATP_MODE(xlen)) != HGATP_MODE_OFF) {
@@ -3099,12 +3160,6 @@ static int riscv_mmu(struct target *target, bool *enabled)
return ERROR_OK;
}
- /* Don't use MMU in explicit or effective M (machine) mode */
- if (effective_mode == PRV_M) {
- LOG_TARGET_DEBUG(target, "SATP/MMU ignored in Machine mode.");
- return ERROR_OK;
- }
-
riscv_reg_t satp;
if (riscv_reg_get(target, &satp, GDB_REGNO_SATP) != ERROR_OK) {
LOG_TARGET_DEBUG(target, "Couldn't read SATP.");
@@ -3341,13 +3396,11 @@ static int riscv_virt2phys(struct target *target, target_addr_t virtual, target_
return ERROR_OK;
}
- riscv_reg_t priv;
- if (riscv_reg_get(target, &priv, GDB_REGNO_PRIV) != ERROR_OK) {
- LOG_TARGET_ERROR(target, "Failed to read priv register.");
+ enum riscv_priv_mode mode = RISCV_MODE_M;
+ if (riscv_effective_privilege_mode(target, &mode) != ERROR_OK)
return ERROR_FAIL;
- }
- if (priv & VIRT_PRIV_V)
+ if (riscv_priv_mode_is_guest(mode))
return riscv_virt2phys_v(target, virtual, physical);
riscv_reg_t satp_value;
-----------------------------------------------------------------------
Summary of changes:
src/target/riscv/gdb_regs.h | 1 +
src/target/riscv/riscv.c | 121 +++++++++++++++++++++++++++++++-------------
2 files changed, 88 insertions(+), 34 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-21 21:27:00
|
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 5088db4c9154ca833c6d558381074b33672e127a (commit)
from d2f72d49efed744eaa489ce931393b6e69122e66 (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 5088db4c9154ca833c6d558381074b33672e127a
Author: Marc Schink <de...@za...>
Date: Tue Sep 15 17:34:51 2026 +0200
flash/nor/tcl: Do not continue on error in 'erase_check'
Currently, 'flash erase_check' continues after an error occurs, such as
when the target is not halted:
> flash erase_check 0
Target not halted
Error: checking erase state of flash bank #0 at 0x00000000
# 0: 0x00000000 (0x400 1kB) not erased
# 1: 0x00000400 (0x400 1kB) not erased
# 2: 0x00000800 (0x400 1kB) not erased
# 3: 0x00000c00 (0x400 1kB) not erased
...
Return an error immediately when checking the erase state fails. While
at it, remove the success message for the underlying flash driver
operation to reduce verbosity.
Because sectors may not be readable, for example, due to read
protection settings, adapt default_flash_mem_blank_check() so that
when a read fails, the sector is marked as "unknown" rather than
triggering a fatal error.
Change-Id: I857e87bf30558974a1c1058345aa6a3baefac031
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/10002
Tested-by: jenkins
Reviewed-by: Tomas Vanek <tom...@gm...>
diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c
index f6ad97aee..d8c7d5c15 100644
--- a/src/flash/nor/core.c
+++ b/src/flash/nor/core.c
@@ -329,12 +329,10 @@ int get_flash_bank_by_addr(struct target *target,
static int default_flash_mem_blank_check(struct flash_bank *bank)
{
- struct target *target = bank->target;
const int buffer_size = 1024;
- uint32_t n_bytes;
- int retval = ERROR_OK;
+ struct target *target = bank->target;
- if (bank->target->state != TARGET_HALTED) {
+ if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
@@ -346,36 +344,44 @@ static int default_flash_mem_blank_check(struct flash_bank *bank)
}
for (unsigned int i = 0; i < bank->num_sectors; i++) {
- uint32_t j;
bank->sectors[i].is_erased = 1;
- for (j = 0; j < bank->sectors[i].size; j += buffer_size) {
+ for (uint32_t j = 0; j < bank->sectors[i].size; j += buffer_size) {
uint32_t chunk;
chunk = buffer_size;
if (chunk > (bank->sectors[i].size - j))
chunk = (bank->sectors[i].size - j);
- retval = target_read_memory(target,
- bank->base + bank->sectors[i].offset + j,
- 4,
- chunk/4,
- buffer);
- if (retval != ERROR_OK)
- goto done;
+ int retval = target_read_buffer(target,
+ bank->base + bank->sectors[i].offset + j,
+ chunk, buffer);
- for (n_bytes = 0; n_bytes < chunk; n_bytes++) {
+ /* A sector that cannot be read cannot be classified.
+ * Mark it 'unknown' and continue with the next sector
+ * rather than failing the whole check.
+ */
+ if (retval != ERROR_OK) {
+ LOG_WARNING("Failed to check erase state on sector %u, "
+ "continuing on next sector", i);
+ bank->sectors[i].is_erased = -1;
+ break;
+ }
+
+ for (uint32_t n_bytes = 0; n_bytes < chunk; n_bytes++) {
if (buffer[n_bytes] != bank->erased_value) {
bank->sectors[i].is_erased = 0;
break;
}
}
+
+ if (bank->sectors[i].is_erased == 0)
+ break;
}
}
-done:
free(buffer);
- return retval;
+ return ERROR_OK;
}
static int flash_blank_check_no_sectors_fast(struct flash_bank *bank)
diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c
index 365a9e2ab..a66b153bf 100644
--- a/src/flash/nor/tcl.c
+++ b/src/flash/nor/tcl.c
@@ -178,7 +178,6 @@ COMMAND_HANDLER(handle_flash_probe_command)
COMMAND_HANDLER(handle_flash_erase_check_command)
{
- bool blank = true;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -191,16 +190,17 @@ COMMAND_HANDLER(handle_flash_erase_check_command)
retval = p->driver->erase_check(p);
else
retval = default_flash_blank_check(p);
- if (retval == ERROR_OK) {
- command_print(CMD, "successfully checked erase state");
- } else {
+
+ if (retval != ERROR_OK) {
command_print(CMD,
- "Error: checking erase state of flash bank #%s at "
- TARGET_ADDR_FMT,
+ "checking erase state of flash bank #%s at "
+ TARGET_ADDR_FMT " failed",
CMD_ARGV[0],
p->base);
+ return retval;
}
+ bool blank = true;
for (unsigned int j = 0; j < p->num_sectors; j++) {
char *erase_state;
-----------------------------------------------------------------------
Summary of changes:
src/flash/nor/core.c | 38 ++++++++++++++++++++++----------------
src/flash/nor/tcl.c | 12 ++++++------
2 files changed, 28 insertions(+), 22 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-19 13:13: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 d2f72d49efed744eaa489ce931393b6e69122e66 (commit)
from 758114a61120c6d615ca37ac2af6a811ea710c9a (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 d2f72d49efed744eaa489ce931393b6e69122e66
Author: Tomas Vanek <tom...@gm...>
Date: Mon Oct 5 11:15:35 2026 +0200
jtag/drivers/ch347: show chip variant in initial info
The CH347 T and F variants differ in GPIO pins and also
in the firmware version numbering. Make clear which variant
is connected.
While on it fix the printf format of chip version.
CH347F 1.01 was printed as 1. 1
Change-Id: Ie6d26926988aac2c7ae4b161cc3b18744579288b
Signed-off-by: Tomas Vanek <tom...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/10088
Tested-by: jenkins
Reviewed-by: Matthias Jentsch <in...@ea...>
Reviewed-by: Paulius Zaleckas <pau...@gm...>
diff --git a/src/jtag/drivers/ch347.c b/src/jtag/drivers/ch347.c
index f505d1569..da67deb8e 100644
--- a/src/jtag/drivers/ch347.c
+++ b/src/jtag/drivers/ch347.c
@@ -1709,7 +1709,8 @@ static int ch347_open_device(void)
strcpy(serial_number, "(unknown)");
}
- LOG_INFO("CH347 %s from vendor %s with serial number %s found. (Chip version=%X.%2X, Firmware=0x%02X)",
+ LOG_INFO("CH347%c %s from vendor %s with serial number %s found. (Chip version=%X.%02X, Firmware=0x%02X)",
+ ch347.chip_variant == CH347T ? 'T' : ch347.chip_variant == CH347F ? 'F' : '?',
product,
manufacturer,
serial_number,
-----------------------------------------------------------------------
Summary of changes:
src/jtag/drivers/ch347.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-19 13:12: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 758114a61120c6d615ca37ac2af6a811ea710c9a (commit)
from 17dd961aeaaeddb69dc7a521b5ef0a778fdcf587 (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 758114a61120c6d615ca37ac2af6a811ea710c9a
Author: Tomas Vanek <tom...@gm...>
Date: Mon Oct 5 10:36:53 2026 +0200
jtag/drivers/ch347: use next lower adapter speed not higher
If an adapter is not able to set the clock speed exactly as requested
it should behave safely and select the next lower speed.
Rework and simplify the table lookup of speed index.
While on it reduce verbosity when the selected speed is lower
than requested. The selected speed is logged by the adapter
infrastructure.
Change-Id: Iae1d680f57ea3f0837ad4ae84b26a3df5ee384e6
Signed-off-by: Tomas Vanek <tom...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/10087
Tested-by: jenkins
Reviewed-by: Matthias Jentsch <in...@ea...>
Reviewed-by: Paulius Zaleckas <pau...@gm...>
diff --git a/src/jtag/drivers/ch347.c b/src/jtag/drivers/ch347.c
index 34c065b7a..f505d1569 100644
--- a/src/jtag/drivers/ch347.c
+++ b/src/jtag/drivers/ch347.c
@@ -1967,23 +1967,13 @@ static int ch347_speed_get_index(int khz, int *speed_idx)
ch347_standard_pack_clock_speeds : ch347_larger_pack_clock_speeds;
int length = ch347.pack_size == STANDARD_PACK ?
ARRAY_SIZE(ch347_standard_pack_clock_speeds) : ARRAY_SIZE(ch347_larger_pack_clock_speeds);
- int idx = -1;
- int lower_bound = 0;
// find the suitable speed index
- for (int i = 0; i < length; i++) {
- if (khz >= lower_bound && khz <= speeds[i]) {
- idx = i;
- break;
- }
- lower_bound = speeds[i];
- }
- // too high! => use max possible speed
- if (idx == -1) {
- LOG_INFO("Speed %d kHz is higher than highest speed of %d kHz. Using %d khz!",
- khz, speeds[length - 1], speeds[length - 1]);
- idx = length - 1;
- } else if (speeds[idx] != khz) {
- LOG_INFO("Requested speed of %d kHz is not possible. Using the next higher speed of %d kHz!",
+ int idx = length - 1;
+ while (idx > 0 && speeds[idx] > khz)
+ idx--;
+
+ if (speeds[idx] > khz) {
+ LOG_WARNING("Requested speed of %d kHz is not possible. Using %d kHz",
khz, speeds[idx]);
}
*speed_idx = idx;
-----------------------------------------------------------------------
Summary of changes:
src/jtag/drivers/ch347.c | 22 ++++++----------------
1 file changed, 6 insertions(+), 16 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-19 13:11:48
|
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 17dd961aeaaeddb69dc7a521b5ef0a778fdcf587 (commit)
from 2893f940012e19cda8ccb6038766b0d77f26bd0e (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 17dd961aeaaeddb69dc7a521b5ef0a778fdcf587
Author: lynch <lyn...@gm...>
Date: Fri Sep 18 11:13:28 2026 +0800
adapter/ch347: enable CH347F dedicated SRST output in JTAG mode
Pin 8 strongly drives low after the adapter powers up, so a wired target
stays in reset until the dedicated output is enabled and driven. Send
PIN_SET on every CH347F JTAG session, whether or not reset_config includes
SRST, then drive the pin high. Leave it low only when both
connect_assert_srst and srst_nogate are set.
Do not send the payload that switches the dedicated mode off. The pin is
not tristate capable and keeps its last level. SWD still does not use this
output; its SRST remains a GPIO. The CH347T has no dedicated JTAG SRST, and
its pin byte still does not carry bit 6.
Warn about the push-pull limitation only when SRST is configured.
Change-Id: I20a14f0c0b70cda70dd72c6ff1b31babc1948235
Signed-off-by: lynch <lyn...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/9703
Reviewed-by: Paulius Zaleckas <pau...@gm...>
Reviewed-by: Tomas Vanek <tom...@gm...>
Tested-by: jenkins
diff --git a/doc/openocd.texi b/doc/openocd.texi
index 323ae4864..b89bea0d8 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -2622,8 +2622,13 @@ In SWD mode the TRST pin is not needed as a JTAG signal, so the driver drives
it as a GPIO to provide SRST. TRST is pin 9 on both chips, but has a different
GPIO number: GPIO5 on the CH347T and GPIO3 on the CH347F. Use
@ref{adapter gpio, @command{adapter gpio srst}} to select a different GPIO or
-to change the polarity. SRST is not available in JTAG mode, where the pin
-carries TRST.
+to change the polarity. On the CH347T, SRST is not available in JTAG mode,
+where the pin carries TRST. On the CH347F, pin 8 is the JTAG interface
+system reset output. It is not shared with a GPIO.
+After the adapter powers up, pin 8 strongly drives low and holds a wired
+target in reset. JTAG initialization therefore always enables this output
+and then drives it high. SWD does not use this output. Pin 8 is active-low
+and push-pull.
Not every GPIO can be used, because the GPIO's share their pins with the
interface signals. Only GPIO3 to GPIO6 are free on the CH347T, and GPIO0 to
@@ -2636,7 +2641,8 @@ same pin, SRST gets disabled.
The SRST GPIO follows the drive mode of @ref{reset_config,,@command{reset_config}}.
The default is open drain, which the driver emulates by switching the pin to an
input instead of driving it to the inactive level, so the reset line needs a
-pull-up. Use @command{reset_config srst_push_pull} if it has none.
+pull-up. Use @command{reset_config srst_push_pull} if it has none. This GPIO
+emulation is not used for the CH347F dedicated output on pin 8.
@end deffn
diff --git a/src/jtag/drivers/ch347.c b/src/jtag/drivers/ch347.c
index 3fa00d3b8..34c065b7a 100644
--- a/src/jtag/drivers/ch347.c
+++ b/src/jtag/drivers/ch347.c
@@ -69,6 +69,8 @@
#define TCK_L 0
#define TRST_H BIT(5)
#define TRST_L 0
+#define SRST_H BIT(6)
+#define SRST_L 0
#define LED_ON 1
#define LED_OFF 0
#define GPIO_CNT 8 // the CH347 has 8 GPIO's
@@ -103,7 +105,7 @@
#define UCMDPKT_DATA_MAX_BYTES_USBHS 507
#define USBC_PACKET_USBHS 512 // Maximum data length per packet at USB high speed
#define CH347_CMD_HEADER 3 // Protocol header length (1 byte command type + 2 bytes data length)
-#define CH347_CMD_INIT_READ_LEN 1 // for JTAG_INIT/SWD_INIT we have only one data byte
+#define CH347_CMD_INIT_READ_LEN 1 // JTAG_INIT/SWD_INIT/PIN_SET read one data byte
// if we send 9 in the init command we get the STANDARD mode or LARGER_PACK mode flag
#define CH347_CMD_INIT_GET_MODE_CLOCK_INDEX_VALUE 9
// No more bits are allowed per CH347_CMD_JTAG_BIT_OP command; this should be dividable by 8
@@ -118,6 +120,7 @@
#define CH347_CMD_JTAG_BIT_OP_RD 0xD2 // JTAG interface pin bit control and read commands
#define CH347_CMD_JTAG_DATA_SHIFT 0xD3 // JTAG interface data shift command
#define CH347_CMD_JTAG_DATA_SHIFT_RD 0xD4 // JTAG interface data shift and read command
+#define CH347_CMD_PIN_SET 0xE2 // set pin functions (CH347F)
// for a single command these amount of data can be read at max
#define CH347_SINGLE_CMD_MAX_READ MAX(GPIO_CNT, CH347_CMD_INIT_READ_LEN)
@@ -216,6 +219,7 @@ struct ch347_info {
int tdi_pin;
int tck_pin;
int trst_pin;
+ int srst_pin;
enum ch347_variant chip_variant; // ch347_variant for explanation
// if true then we can't us the bytewise commands due to a bug of the chip; depends on BYTEWISE_MODE_VERSION
@@ -271,6 +275,10 @@ static bool ch347_activity_led_active_high;
// GPIO driving SRST in SWD mode, defaults to the otherwise unused TRST pin
static uint8_t ch347_srst_gpio_pin = 0xFF;
static bool ch347_srst_active_high;
+/* Set after the CH347F dedicated SRST output is enabled and its pin byte
+ * has been transmitted. JTAG pin bytes carry bit 6 only then. SWD leaves
+ * this clear. */
+static bool ch347_dedicated_srst_enabled;
static struct ch347_info ch347;
static struct libusb_device_handle *ch347_handle;
@@ -278,7 +286,8 @@ static struct libusb_device_handle *ch347_handle;
need to be send as single command and need a read after write */
static inline bool ch347_is_single_cmd_type(uint8_t type)
{
- return type == CH347_CMD_GPIO || type == CH347_CMD_JTAG_INIT || type == CH347_CMD_SWD_INIT;
+ return type == CH347_CMD_GPIO || type == CH347_CMD_JTAG_INIT || type == CH347_CMD_SWD_INIT ||
+ type == CH347_CMD_PIN_SET;
}
static void log_buf_dump(const uint8_t *data, unsigned int size, bool recv)
@@ -468,7 +477,8 @@ static void ch347_cmd_calc_reads(struct ch347_cmd *cmd)
break;
case CH347_CMD_JTAG_INIT:
case CH347_CMD_SWD_INIT:
- // for JTAG_INIT/SWD_INIT the amount is fixed
+ case CH347_CMD_PIN_SET:
+ // for JTAG_INIT/SWD_INIT/PIN_SET the amount is fixed
cmd->read_len = CH347_CMD_INIT_READ_LEN;
break;
case CH347_CMD_JTAG_BIT_OP_RD:
@@ -572,6 +582,7 @@ static int ch347_read_scan(uint8_t *decoded_buf, int decoded_buf_len, int raw_re
case CH347_CMD_GPIO:
case CH347_CMD_JTAG_INIT:
case CH347_CMD_SWD_INIT:
+ case CH347_CMD_PIN_SET:
case CH347_CMD_JTAG_DATA_SHIFT_RD:
// for all bytewise commands: copy the data bytes
memcpy(&decoded_buf[decoded_buf_idx], &read_buf[rd_idx], data_len);
@@ -924,7 +935,12 @@ static int ch347_scratchpad_add_byte(uint8_t byte)
*/
static int ch347_scratchpad_add_pin_byte(void)
{
- return ch347_scratchpad_add_byte(ch347.tms_pin | ch347.tdi_pin | ch347.tck_pin | ch347.trst_pin);
+ uint8_t pins = ch347.tms_pin | ch347.tdi_pin | ch347.tck_pin | ch347.trst_pin;
+
+ if (ch347_dedicated_srst_enabled)
+ pins |= ch347.srst_pin;
+
+ return ch347_scratchpad_add_byte(pins);
}
/**
@@ -964,6 +980,68 @@ static int ch347_scratchpad_add_bytes(uint8_t *bytes, int count)
return ERROR_OK;
}
+/* Drive SRST low at init only when the target is connected under reset.
+ * srst_nogate is required as well: without it, JTAG is gated while SRST
+ * is asserted. */
+static bool ch347_dedicated_srst_assert_at_init(void)
+{
+ enum reset_types cfg = jtag_get_reset_config();
+
+ return (cfg & (RESET_CNCT_UNDER_SRST | RESET_SRST_NO_GATING))
+ == (RESET_CNCT_UNDER_SRST | RESET_SRST_NO_GATING);
+}
+
+/**
+ * @brief Enable the dedicated SRST output on CH347F devices.
+ *
+ * The 0xE2 command and its payload come from WCH's fork, commit 4fd5026aabb6
+ * ("feat: Add CH347F SRST configuration"):
+ * https://github.com/WCHSoftGroup/ch347/commit/4fd5026aabb62b941317b5d156d0eeaef4c43108
+ * That packet is {0xe2, 0x08, 0x00, 0x00, 0x81, ...}. The command queue adds
+ * the command and the length, so only the eight payload bytes are sent here.
+ * Bit 0 of the second payload byte selects the mode: 0x81 enables it and
+ * 0x80 disables it. Disabling does not tristate pin 8, so 0x80 is never sent.
+ *
+ * The byte read back from PIN_SET has no documented meaning, so it is logged
+ * and does not decide whether initialization succeeded.
+ *
+ * Pin 8 strongly drives low after the adapter powers up. PIN_SET only selects
+ * the dedicated output; the following JTAG pin byte sets the level. WCH drives
+ * it high here. It stays low only when reset_config sets both
+ * connect_assert_srst and srst_nogate.
+ *
+ * @return ERROR_OK on success, or the original error code when the command
+ * cannot be transmitted
+ */
+static int ch347_srst_enable(void)
+{
+ int retval = ch347_cmd_start_next(CH347_CMD_PIN_SET);
+ if (retval != ERROR_OK)
+ return retval;
+
+ uint8_t cmd_data[] = {0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ retval = ch347_scratchpad_add_bytes(cmd_data, ARRAY_SIZE(cmd_data));
+ if (retval != ERROR_OK)
+ return retval;
+
+ uint8_t init_result;
+ retval = ch347_single_read_get_byte(0, &init_result);
+ if (retval != ERROR_OK)
+ return retval;
+
+ LOG_DEBUG("CH347F PIN_SET result %02" PRIx8, init_result);
+
+ ch347.srst_pin = ch347_dedicated_srst_assert_at_init() ? SRST_L : SRST_H;
+ /* The pin byte merges bit 6 only while this flag is set. */
+ ch347_dedicated_srst_enabled = true;
+ retval = ch347_cmd_start_next(CH347_CMD_JTAG_BIT_OP);
+ if (retval == ERROR_OK)
+ retval = ch347_scratchpad_add_pin_byte();
+ if (retval == ERROR_OK)
+ retval = ch347_cmd_transmit_queue();
+ return retval;
+}
+
/**
* @brief Function used to change the TMS value at the
* rising edge of TCK to switch its TAP state
@@ -1375,21 +1453,50 @@ static int ch347_activity_led_set(int led_state)
return ERROR_OK;
}
+/**
+ * @brief Warn once when the dedicated CH347F SRST cannot follow reset_config.
+ *
+ * Pin 8 is push-pull. Open-drain and open-source are not emulated.
+ * 'reset_config none' still leaves the drive mode at open drain, so warn
+ * only when SRST is actually configured.
+ */
+static void ch347_warn_dedicated_srst_drive(void)
+{
+ static bool warned;
+ enum adapter_gpio_drive_mode drive =
+ adapter_gpio_get_config()[ADAPTER_GPIO_IDX_SRST].drive;
+
+ if (warned || !(jtag_get_reset_config() & RESET_HAS_SRST))
+ return;
+ if (drive == ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL)
+ return;
+
+ warned = true;
+ LOG_WARNING("CH347F dedicated SRST is push-pull and ignores "
+ "the reset_config drive mode; use 'reset_config srst_push_pull'");
+}
+
/**
* @brief Control (assert/deassert) the signals SRST and TRST on the interface.
*
* In SWD mode TRST is not used as a JTAG signal, so the pin is driven as a
- * GPIO to provide SRST. In JTAG mode the pin is TRST and SRST is unavailable.
+ * GPIO to provide SRST. In JTAG mode CH347T has no SRST. The CH347F dedicated
+ * output is enabled at JTAG init, including when reset_config does not include
+ * SRST, because pin 8 drives strong low after adapter power-up. It is
+ * active-low and push-pull; it ignores 'adapter gpio srst' polarity and the
+ * 'reset_config' drive mode. There is no command here to return pin 8 to Hi-Z.
*
* The SRST GPIO follows the drive mode configured with 'reset_config'.
*
* @param trst 1 to assert TRST, 0 to deassert TRST.
* @param srst 1 to assert SRST, 0 to deassert SRST.
- * @return ERROR_FAIL for asserting SRST in JTAG mode.
- * ERROR_OK for assert/deassert in JTAG mode for TRST and in SWD mode for SRST
+ * @return ERROR_FAIL when asserting SRST in JTAG mode on a non-CH347F
+ * (CH347T or another variant). ERROR_OK for TRST in JTAG mode, SRST on the
+ * CH347F dedicated output, and SRST in SWD mode.
*/
static int ch347_reset(int trst, int srst)
{
+ int retval;
LOG_DEBUG_IO("reset trst: %i srst %i", trst, srst);
if (swd_mode) {
@@ -1417,16 +1524,20 @@ static int ch347_reset(int trst, int srst)
return ch347_gpio_cmd(ch347_srst_gpio_pin, value, &state);
}
- if (srst) {
+ if (srst && !ch347_dedicated_srst_enabled) {
LOG_ERROR("Asserting SRST not supported");
return ERROR_FAIL;
}
- int retval = ch347_cmd_start_next(CH347_CMD_JTAG_BIT_OP);
+ retval = ch347_cmd_start_next(CH347_CMD_JTAG_BIT_OP);
if (retval != ERROR_OK)
return retval;
ch347.trst_pin = trst ? TRST_L : TRST_H;
+ if (ch347_dedicated_srst_enabled) {
+ ch347_warn_dedicated_srst_drive();
+ ch347.srst_pin = srst ? SRST_L : SRST_H;
+ }
retval = ch347_scratchpad_add_pin_byte();
if (retval != ERROR_OK)
return retval;
@@ -1968,14 +2079,34 @@ static int ch347_init(void)
ch347.tms_pin = TMS_H;
ch347.tdi_pin = TDI_L;
ch347.trst_pin = TRST_H;
+ ch347.srst_pin = SRST_H;
+ ch347_dedicated_srst_enabled = false;
INIT_LIST_HEAD(&ch347.cmd_queue);
INIT_LIST_HEAD(&ch347.scan_queue);
+ /* Static initial pack_size is STANDARD_PACK (0), which would look already
+ * probed. max_len stays 0 until the probe, and PIN_SET uses this queue. */
ch347.pack_size = UNSET;
ch347_configure_activity_led(&adapter_gpio_get_config()[ADAPTER_GPIO_IDX_LED]);
if (!swd_mode) {
+ /* Pin 8 drives strong low after adapter power-up. On CH347F, enable the
+ * dedicated SRST output and release it, even when reset_config
+ * does not include SRST. Leave it asserted only for connect_assert_srst
+ * together with srst_nogate. */
+ if (ch347.chip_variant == CH347F) {
+ retval = ch347_init_pack_size();
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = ch347_srst_enable();
+ if (retval != ERROR_OK) {
+ LOG_ERROR("CH347F dedicated SRST enable failed");
+ return retval;
+ }
+ ch347_warn_dedicated_srst_drive();
+ }
tap_set_state(TAP_RESET);
} else {
ch347_configure_srst_gpio(&adapter_gpio_get_config()[ADAPTER_GPIO_IDX_SRST]);
-----------------------------------------------------------------------
Summary of changes:
doc/openocd.texi | 12 +++-
src/jtag/drivers/ch347.c | 149 ++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 149 insertions(+), 12 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-18 16:26: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 2893f940012e19cda8ccb6038766b0d77f26bd0e (commit)
from 67957fb77e06c634d310a8732f7aef5b86cc1583 (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 2893f940012e19cda8ccb6038766b0d77f26bd0e
Author: Ryan QIAN <jia...@hp...>
Date: Tue Oct 13 08:16:51 2026 +0800
tcl: fix broken datasheet link in hpm6360 config
- drop a stray ":w" accidentally left in the datasheet url
Change-Id: Idfb1eaa5a9de703a95f3bf0eaab74aa05380c49f
Signed-off-by: Ryan QIAN <jia...@hp...>
Reviewed-on: https://review.openocd.org/c/openocd/+/10122
Tested-by: jenkins
Reviewed-by: Tomas Vanek <tom...@gm...>
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/tcl/target/hpmicro/hpm6360.cfg b/tcl/target/hpmicro/hpm6360.cfg
index b7ab912a6..c38c29556 100644
--- a/tcl/target/hpmicro/hpm6360.cfg
+++ b/tcl/target/hpmicro/hpm6360.cfg
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2021 HPMicro
#
-# datasheet: https://www.hpmicro.com/Public/Uploads/uploadfile/files/20251124/HPM6300DSV28-779.pdf:w
+# datasheet: https://www.hpmicro.com/Public/Uploads/uploadfile/files/20251124/HPM6300DSV28-779.pdf
if { [info exists CHIPNAME] } {
set _CHIP $CHIPNAME
-----------------------------------------------------------------------
Summary of changes:
tcl/target/hpmicro/hpm6360.cfg | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-18 16:26: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 67957fb77e06c634d310a8732f7aef5b86cc1583 (commit)
from bb5a52da599c3dac61ddc51d2fa8c1166ee795d0 (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 67957fb77e06c634d310a8732f7aef5b86cc1583
Author: Ryan QIAN <jia...@hp...>
Date: Tue Oct 13 08:13:22 2026 +0800
tcl: add hpm5e00 and hpm5e00evk configs
- add target and board config files for hpm5e00
- the board declares two flash banks for the xpi0 nor: the standard
0x80000000 window and the hybrid 0xB0000000 window, both mapping
the same physical flash
Change-Id: I7b5abf02bcd4d4eef885063d3bfce04194182446
Signed-off-by: Ryan QIAN <jia...@hp...>
Reviewed-on: https://review.openocd.org/c/openocd/+/10120
Reviewed-by: Antonio Borneo <bor...@gm...>
Tested-by: jenkins
Reviewed-by: Tomas Vanek <tom...@gm...>
diff --git a/tcl/board/hpmicro/hpm5e00evk.cfg b/tcl/board/hpmicro/hpm5e00evk.cfg
new file mode 100644
index 000000000..1c65acc5d
--- /dev/null
+++ b/tcl/board/hpmicro/hpm5e00evk.cfg
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright (c) 2026 HPMicro
+
+adapter speed 10000
+source [find interface/hpmicro/hpmicro_evk.cfg]
+source [find target/hpmicro/hpm5e00.cfg]
+# openocd flash driver argument:
+# - option0:
+# [31:28] Flash probe type
+# 0 - SFDP SDR / 1 - SFDP DDR
+# 2 - 1-4-4 Read (0xEB, 24-bit address) / 3 - 1-2-2 Read(0xBB, 24-bit address)
+# 4 - HyperFLASH 1.8V / 5 - HyperFLASH 3V
+# 6 - OctaBus DDR (SPI -> OPI DDR)
+# 8 - Xccela DDR (SPI -> OPI DDR)
+# 10 - EcoXiP DDR (SPI -> OPI DDR)
+# [27:24] Command Pads after Power-on Reset
+# 0 - SPI / 1 - DPI / 2 - QPI / 3 - OPI
+# [23:20] Command Pads after Configuring FLASH
+# 0 - SPI / 1 - DPI / 2 - QPI / 3 - OPI
+# [19:16] Quad Enable Sequence (for the device support SFDP 1.0 only)
+# 0 - Not needed
+# 1 - QE bit is at bit6 in Status Register 1
+# 2 - QE bit is at bit1 in Status Register 2
+# 3 - QE bit is at bit7 in Status Register 2
+# 4 - QE bit is at bit1 in Status Register 2 and should be programmed by 0x31
+# [15:8] Dummy cycles
+# 0 - Auto-probed / detected / default value
+# Others - User specified value, for DDR read, the dummy cycles should be 2 * cycles on FLASH datasheet
+# [7:4] Misc.
+# 0 - Not used
+# 1 - SPI mode
+# 2 - Internal loopback
+# 3 - External DQS
+# [3:0] Frequency option
+# 1 - 30MHz / 2 - 50MHz / 3 - 66MHz / 4 - 80MHz / 5 - 100MHz / 6 - 120MHz / 7 - 133MHz / 8 - 166MHz
+# - option1:
+# [31:20] Reserved
+# [19:16] IO voltage
+# 0 - 3V / 1 - 1.8V
+# [15:12] Pin group
+# 0 - 1st group / 1 - 2nd group
+# [11:8] Connection selection
+# 0 - CA_CS0 / 1 - CB_CS0 / 2 - CA_CS0 + CB_CS0 (Two FLASH connected to CA and CB respectively)
+# [7:0] Drive Strength
+# 0 - Default value
+
+# xpi0 configs
+# - flash driver: hpm_xpi
+# - flash ctrl index: 0xF3000000
+# - base address: 0x80000000
+# - flash size: 0x2000000
+# - flash option0: 0x5
+# - flash option1: 0x1000
+flash bank xpi0 hpm_xpi 0x80000000 0x2000000 1 1 $_TARGET0 0xF3000000 0x5 0x1000
+
+# xpi0_hybrid configs
+# - flash driver: hpm_xpi
+# - flash ctrl index: 0xF3000000
+# - base address: 0xB0000000
+# - flash size: 0x2000000
+# - flash option0: 0x5
+# - flash option1: 0x1000
+flash bank xpi0_hybrid hpm_xpi 0xB0000000 0x2000000 1 1 $_TARGET0 0xF3000000 0x5 0x1000
+
+proc init_clock {} {
+ mww 0xF4000800 0xFFFFFFFF
+ mww 0xF4000810 0xFFFFFFFF
+ mww 0xF4000820 0xFFFFFFFF
+ mww 0xF4000830 0xFFFFFFFF
+ echo "clocks has been enabled!"
+}
+
+$_TARGET0 configure -event reset-init {
+ init_clock
+}
diff --git a/tcl/target/hpmicro/hpm5e00.cfg b/tcl/target/hpmicro/hpm5e00.cfg
new file mode 100644
index 000000000..4f3379986
--- /dev/null
+++ b/tcl/target/hpmicro/hpm5e00.cfg
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright (c) 2026 HPMicro
+
+if { [info exists CHIPNAME] } {
+ set _CHIP $CHIPNAME
+} else {
+ set _CHIP hpm5e00
+}
+set _CPUTAPID 0x1000563D
+jtag newtap $_CHIP cpu -irlen 5 -expected-id $_CPUTAPID
+
+set _TARGET0 $_CHIP.cpu0
+target create $_TARGET0 riscv -tap $_CHIP.cpu -coreid 0
+
+$_TARGET0 configure -work-area-phys 0x00000000 -work-area-size 0x20000 -work-area-backup 0
+
+source [find target/hpmicro/hpm_common.cfg]
+source [find target/hpmicro/hpm_common_csr.cfg]
+
+proc reset_soc {} {
+ sba_write_mem 0xF410001C 24000000
+}
-----------------------------------------------------------------------
Summary of changes:
tcl/board/hpmicro/{hpm5301evklite.cfg => hpm5e00evk.cfg} | 13 +++++++++++--
tcl/target/hpmicro/{hpm5100.cfg => hpm5e00.cfg} | 6 +++---
2 files changed, 14 insertions(+), 5 deletions(-)
copy tcl/board/hpmicro/{hpm5301evklite.cfg => hpm5e00evk.cfg} (86%)
copy tcl/target/hpmicro/{hpm5100.cfg => hpm5e00.cfg} (82%)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-16 07: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 bb5a52da599c3dac61ddc51d2fa8c1166ee795d0 (commit)
from 24651a5fce9eb5c9db6eeea3cd846b18041a5fc9 (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 bb5a52da599c3dac61ddc51d2fa8c1166ee795d0
Author: Tomas Vanek <va...@fb...>
Date: Wed Sep 9 09:08:25 2026 +0200
flash/nor, gdb_server: allow skipping flash bank without erase
Introduce new parameter to flash_erase_address_range()
allowing to skip banks with not defined erase method
while iterating over the address range.
Request skipping when erase is a preparatory operation
before writing. Missing erase support therefore means the memory
does not need to be erased before write.
Used in command
flash write_image erase
or in gdb load command.
Change-Id: Ide1d5c070418f11a2732e0c77494ca5c485cabf4
Signed-off-by: Tomas Vanek <va...@fb...>
Reviewed-on: https://review.openocd.org/c/openocd/+/9973
Tested-by: jenkins
Reviewed-by: Tarek BOCHKATI <tar...@gm...>
Reviewed-by: zapb <de...@za...>
Reviewed-by: Tomas Vanek <tom...@gm...>
diff --git a/doc/openocd.texi b/doc/openocd.texi
index 9b7c64d64..323ae4864 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -6168,7 +6168,9 @@ explicitly as @option{bin} (binary), @option{ihex} (Intel hex),
@option{elf} (ELF file), @option{s19} (Motorola s19).
@option{mem}, or @option{builder}.
The relevant flash sectors will be erased prior to programming
-if the @option{erase} parameter is given. If @option{unlock} is
+if the @option{erase} parameter is given. @option{erase}
+is silently ignored for banks without erase support.
+If @option{unlock} is
provided, then the flash banks are unlocked before erase and
program. The flash bank to use is inferred from the address of
each image section.
diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c
index bec542c42..f6ad97aee 100644
--- a/src/flash/nor/core.c
+++ b/src/flash/nor/core.c
@@ -649,7 +649,7 @@ static int flash_iterate_address_range_inner(struct target *target,
*/
static int flash_iterate_address_range(struct target *target,
char *pad_reason, target_addr_t addr, uint32_t length,
- bool iterate_protect_blocks,
+ bool iterate_protect_blocks, bool skip_banks_without_erase,
int (*callback)(struct flash_bank *bank, unsigned int first,
unsigned int last))
{
@@ -668,12 +668,17 @@ static int flash_iterate_address_range(struct target *target,
LOG_DEBUG("iterating over more than one flash bank.");
cur_length = c->base + c->size - addr;
}
- retval = flash_iterate_address_range_inner(target,
- pad_reason, addr, cur_length,
- iterate_protect_blocks,
- callback);
- if (retval != ERROR_OK)
- break;
+ if (skip_banks_without_erase && !c->driver->erase) {
+ LOG_DEBUG("bank %s does not support erase, skipped",
+ c->name);
+ } else {
+ retval = flash_iterate_address_range_inner(target,
+ pad_reason, addr, cur_length,
+ iterate_protect_blocks,
+ callback);
+ if (retval != ERROR_OK)
+ break;
+ }
length -= cur_length;
addr += cur_length;
@@ -683,10 +688,11 @@ static int flash_iterate_address_range(struct target *target,
}
int flash_erase_address_range(struct target *target,
- bool pad, target_addr_t addr, uint32_t length)
+ bool pad, target_addr_t addr, uint32_t length, bool skip_banks_without_erase)
{
return flash_iterate_address_range(target, pad ? "erase" : NULL,
- addr, length, false, &flash_driver_erase);
+ addr, length, false /* iterate_protect_blocks */,
+ skip_banks_without_erase, &flash_driver_erase);
}
static int flash_driver_unprotect(struct flash_bank *bank, unsigned int first,
@@ -703,7 +709,9 @@ int flash_unlock_address_range(struct target *target, target_addr_t addr,
* and doesn't restore it.
*/
return flash_iterate_address_range(target, "unprotect",
- addr, length, true, &flash_driver_unprotect);
+ addr, length, true /* iterate_protect_blocks */,
+ false /* skip_banks_without_erase */,
+ &flash_driver_unprotect);
}
static int compare_section(const void *a, const void *b)
@@ -1035,7 +1043,9 @@ int flash_write_unlock_verify(struct target *target, struct image *image,
if (erase) {
/* calculate and erase sectors */
retval = flash_erase_address_range(target,
- true, run_address, run_size);
+ true /* pad */,
+ run_address, run_size,
+ true /* skip_banks_without_erase */);
}
}
diff --git a/src/flash/nor/core.h b/src/flash/nor/core.h
index b1bb8ebba..d58dcb80f 100644
--- a/src/flash/nor/core.h
+++ b/src/flash/nor/core.h
@@ -149,10 +149,12 @@ int flash_register_commands(struct command_context *cmd_ctx);
* The range @a addr to @a addr + @a length - 1 must be strictly
* sector aligned, unless @a pad is true. Setting @a pad true extends
* the range, at beginning and/or end, if needed for sector alignment.
+ * @a skip_banks_without_erase silently skip banks which driver has
+ * no erase method defined.
* @returns ERROR_OK if successful; otherwise, an error code.
*/
int flash_erase_address_range(struct target *target,
- bool pad, target_addr_t addr, uint32_t length);
+ bool pad, target_addr_t addr, uint32_t length, bool skip_banks_without_erase);
int flash_unlock_address_range(struct target *target, target_addr_t addr,
uint32_t length);
diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c
index cf2494bda..365a9e2ab 100644
--- a/src/flash/nor/tcl.c
+++ b/src/flash/nor/tcl.c
@@ -279,7 +279,8 @@ COMMAND_HANDLER(handle_flash_erase_address_command)
retval = flash_unlock_address_range(target, address, length);
if (retval == ERROR_OK)
- retval = flash_erase_address_range(target, do_pad, address, length);
+ retval = flash_erase_address_range(target, do_pad, address, length,
+ false /* skip_banks_without_erase */);
if (retval == ERROR_FLASH_OPER_UNSUPPORTED) {
command_print(CMD, "erase operation is not supported");
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index 934ba2265..d87164a51 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -3647,8 +3647,8 @@ static int gdb_v_packet(struct connection *connection,
* end to be "block" aligned ... if padding is ever needed,
* GDB will have become dangerously confused.
*/
- result = flash_erase_address_range(target, false, addr,
- length);
+ result = flash_erase_address_range(target, false, /* pad */
+ addr, length, true /* skip_banks_without_erase */);
/* perform any target specific operations after the erase */
target_call_event_callbacks(target,
-----------------------------------------------------------------------
Summary of changes:
doc/openocd.texi | 4 +++-
src/flash/nor/core.c | 32 +++++++++++++++++++++-----------
src/flash/nor/core.h | 4 +++-
src/flash/nor/tcl.c | 3 ++-
src/server/gdb_server.c | 4 ++--
5 files changed, 31 insertions(+), 16 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-16 07:36:54
|
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 24651a5fce9eb5c9db6eeea3cd846b18041a5fc9 (commit)
from 66188cd58e767ec3e23efc31ec207c0e5ed4a84a (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 24651a5fce9eb5c9db6eeea3cd846b18041a5fc9
Author: Tomas Vanek <va...@fb...>
Date: Wed Sep 9 08:50:49 2026 +0200
flash/nor: allow driver erase method to be NULL
We need ability to test for unsupported erase
before the erase method is called.
Also drop the erase stub returning ERROR_FLASH_OPER_UNSUPPORTED
from nrf54 flash driver.
Change-Id: Iccc63decabea5a7bfdfefc0dd87ff8b3515c4f6a
Signed-off-by: Tomas Vanek <va...@fb...>
Reviewed-on: https://review.openocd.org/c/openocd/+/9972
Tested-by: jenkins
Reviewed-by: zapb <de...@za...>
Reviewed-by: Tomas Vanek <tom...@gm...>
diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c
index c6de2f66a..bec542c42 100644
--- a/src/flash/nor/core.c
+++ b/src/flash/nor/core.c
@@ -29,6 +29,11 @@ static struct flash_bank *flash_banks;
int flash_driver_erase(struct flash_bank *bank, unsigned int first,
unsigned int last)
{
+ if (!bank->driver->erase) {
+ // do not log error here to allow silently skip auto-erase
+ return ERROR_FLASH_OPER_UNSUPPORTED;
+ }
+
return bank->driver->erase(bank, first, last);
}
diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h
index 16c3756f3..f98d5dd9b 100644
--- a/src/flash/nor/driver.h
+++ b/src/flash/nor/driver.h
@@ -88,6 +88,9 @@ struct flash_driver {
* called, the flash driver should erase the specified sectors
* using whatever means are at its disposal.
*
+ * If the memory is a non-volatile RAM or other type which
+ * does not need to be erased before write, set method to NULL.
+ *
* @param bank The bank of flash to be erased.
* @param first The number of the first sector to erase, typically 0.
* @param last The number of the last sector to erase, typically N-1.
diff --git a/src/flash/nor/nrf54.c b/src/flash/nor/nrf54.c
index 3b90784a3..bb3ef4e3b 100644
--- a/src/flash/nor/nrf54.c
+++ b/src/flash/nor/nrf54.c
@@ -325,12 +325,6 @@ error:
return ERROR_OK;
}
-static int nrf54_erase(struct flash_bank *bank, unsigned int first,
- unsigned int last)
-{
- return ERROR_FLASH_OPER_UNSUPPORTED;
-}
-
FLASH_BANK_COMMAND_HANDLER(nrf54_flash_bank_command)
{
if (bank->base != NRF54_RRAM_BASE_ADDR) {
@@ -366,7 +360,6 @@ const struct flash_driver nrf54_flash = {
.commands = nrf54_command_handlers,
.flash_bank_command = nrf54_flash_bank_command,
.info = nrf54_info,
- .erase = nrf54_erase,
.write = nrf54_write,
.read = default_flash_read,
.probe = nrf54_probe,
diff --git a/src/flash/nor/virtual.c b/src/flash/nor/virtual.c
index 0c2f1b913..2e1c23476 100644
--- a/src/flash/nor/virtual.c
+++ b/src/flash/nor/virtual.c
@@ -101,6 +101,9 @@ static int virtual_erase(struct flash_bank *bank, unsigned int first,
if (!master_bank)
return ERROR_FLASH_OPERATION_FAILED;
+ if (!master_bank->driver->erase)
+ return ERROR_FLASH_OPER_UNSUPPORTED;
+
/* call master handler */
return master_bank->driver->erase(master_bank, first, last);
}
-----------------------------------------------------------------------
Summary of changes:
src/flash/nor/core.c | 5 +++++
src/flash/nor/driver.h | 3 +++
src/flash/nor/nrf54.c | 7 -------
src/flash/nor/virtual.c | 3 +++
4 files changed, 11 insertions(+), 7 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-16 07:32: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 66188cd58e767ec3e23efc31ec207c0e5ed4a84a (commit)
from fb58d764b4caabdece22d729bcce2daab9e4b370 (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 66188cd58e767ec3e23efc31ec207c0e5ed4a84a
Author: Marc Schink <de...@za...>
Date: Wed Dec 17 11:07:45 2025 +0000
flash/nor: Support erase check on banks without sectors
The current implementation of the deletion check is closely tied to the
concept of sectors. Implement a workaround to support sectorless banks
without having to make many changes to the code base.
Tested with nRF54L15-DK, tested for regression with AT32F421C8T7.
Change-Id: I88fd5d56f2edbd8337663bea8d25cd499c09add6
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/9319
Reviewed-by: Antonio Borneo <bor...@gm...>
Tested-by: jenkins
Reviewed-by: Tarek BOCHKATI <tar...@gm...>
Reviewed-by: Tomas Vanek <tom...@gm...>
diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c
index 336283ae2..c6de2f66a 100644
--- a/src/flash/nor/core.c
+++ b/src/flash/nor/core.c
@@ -373,6 +373,68 @@ done:
return retval;
}
+static int flash_blank_check_no_sectors_fast(struct flash_bank *bank)
+{
+ struct target_memory_check_block check_block;
+
+ check_block.address = bank->base;
+ check_block.size = bank->size;
+ // Erase state unknown.
+ check_block.result = UINT32_MAX;
+
+ unsigned int checked;
+ int retval = target_blank_check_memory(bank->target, &check_block, 1,
+ bank->erased_value, &checked);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ bank->is_erased = check_block.result;
+
+ return ERROR_OK;
+}
+
+static int flash_blank_check_no_sectors(struct flash_bank *bank)
+{
+ struct target *target = bank->target;
+ const uint32_t buffer_size = 1024;
+ uint8_t buffer[buffer_size];
+
+ if (bank->target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ int retval = flash_blank_check_no_sectors_fast(bank);
+ if (retval == ERROR_OK)
+ return retval;
+
+ LOG_WARNING("Fast erase check failed, running slow fallback");
+
+ bank->is_erased = -1;
+
+ for (uint32_t offset = 0; offset < bank->size; offset += buffer_size) {
+ uint32_t chunk_size = MIN(buffer_size, bank->size - offset);
+
+ retval = target_read_buffer(target, bank->base + offset,
+ chunk_size, buffer);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ for (uint32_t i = 0; i < chunk_size; i++) {
+ if (buffer[i] != bank->erased_value) {
+ bank->is_erased = 0;
+ return ERROR_OK;
+ }
+ }
+ }
+
+ bank->is_erased = 1;
+
+ return ERROR_OK;
+}
+
int default_flash_blank_check(struct flash_bank *bank)
{
struct target *target = bank->target;
@@ -383,6 +445,9 @@ int default_flash_blank_check(struct flash_bank *bank)
return ERROR_TARGET_NOT_HALTED;
}
+ if (bank->num_sectors == 0)
+ return flash_blank_check_no_sectors(bank);
+
struct target_memory_check_block *block_array;
block_array = malloc(bank->num_sectors * sizeof(struct target_memory_check_block));
if (!block_array) {
diff --git a/src/flash/nor/core.h b/src/flash/nor/core.h
index 55ea3c7e5..b1bb8ebba 100644
--- a/src/flash/nor/core.h
+++ b/src/flash/nor/core.h
@@ -116,6 +116,17 @@ struct flash_bank {
unsigned int num_sectors;
/** Array of sectors, allocated and initialized by the flash driver */
struct flash_sector *sectors;
+ /**
+ * Indication of erasure status: 0 = not erased, 1 = erased,
+ * other = unknown. Set by @c flash_driver::erase_check only.
+ *
+ * Use this only if the flash bank has no sectors.
+ *
+ * This information must be considered stale immediately.
+ * Don't set it in flash_driver::erase or a device mass_erase
+ * Don't clear it in flash_driver::write
+ */
+ int is_erased;
/**
* The number of protection blocks in this bank. This value
diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c
index c80b09c29..cf2494bda 100644
--- a/src/flash/nor/tcl.c
+++ b/src/flash/nor/tcl.c
@@ -221,6 +221,9 @@ COMMAND_HANDLER(handle_flash_erase_check_command)
erase_state);
}
+ if (p->num_sectors == 0)
+ blank = (p->is_erased == 1);
+
if (blank)
command_print(CMD, "\tBank is erased");
return retval;
-----------------------------------------------------------------------
Summary of changes:
src/flash/nor/core.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++
src/flash/nor/core.h | 11 +++++++++
src/flash/nor/tcl.c | 3 +++
3 files changed, 79 insertions(+)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-16 07:32: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 fb58d764b4caabdece22d729bcce2daab9e4b370 (commit)
from 930a525e7c18146e96586aff017119ba702d9018 (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 fb58d764b4caabdece22d729bcce2daab9e4b370
Author: Marc Schink <de...@za...>
Date: Sun Dec 7 20:54:57 2025 +0000
flash/nor: Handle banks without erase support
Handle banks that do not support an erase operation. This essentially only
applies to non-flash NVM banks.
Since all NVM is exposed to GDB as flash memory, GDB always issues an erase
before programming. We silently ignore the unsupported erase operation for
GDB requests. For the corresponding Tcl commands, we propagate the error of
missing support to the user.
To avoid confusing messages when programming (and auto-erasing) via GDB,
we remove lower-layer error logging.
While at it, rework the error handling in the respective command
handlers.
Tested with nRF54L15-DK, tested for regression with AT32F421C8T7.
Change-Id: Ic5a84b7af64d5c5dbe4bcd1e78e566771c016ca6
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/9289
Tested-by: jenkins
Reviewed-by: Tomas Vanek <tom...@gm...>
Reviewed-by: Antonio Borneo <bor...@gm...>
Reviewed-by: Tarek BOCHKATI <tar...@gm...>
diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c
index e71546348..336283ae2 100644
--- a/src/flash/nor/core.c
+++ b/src/flash/nor/core.c
@@ -29,13 +29,7 @@ static struct flash_bank *flash_banks;
int flash_driver_erase(struct flash_bank *bank, unsigned int first,
unsigned int last)
{
- int retval;
-
- retval = bank->driver->erase(bank, first, last);
- if (retval != ERROR_OK)
- LOG_ERROR("failed erasing sectors %u to %u", first, last);
-
- return retval;
+ return bank->driver->erase(bank, first, last);
}
int flash_driver_protect(struct flash_bank *bank, int set, unsigned int first,
diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c
index 9cf7fdfef..c80b09c29 100644
--- a/src/flash/nor/tcl.c
+++ b/src/flash/nor/tcl.c
@@ -278,13 +278,21 @@ COMMAND_HANDLER(handle_flash_erase_address_command)
if (retval == ERROR_OK)
retval = flash_erase_address_range(target, do_pad, address, length);
- if (retval == ERROR_OK && duration_measure(&bench) == ERROR_OK) {
+ if (retval == ERROR_FLASH_OPER_UNSUPPORTED) {
+ command_print(CMD, "erase operation is not supported");
+ return retval;
+ } else if (retval != ERROR_OK) {
+ command_print(CMD, "erase operation failed");
+ return retval;
+ }
+
+ if (duration_measure(&bench) == ERROR_OK) {
command_print(CMD, "erased address " TARGET_ADDR_FMT " (length %" PRIu32 ")"
" in %fs (%0.3f KiB/s)", address, length,
duration_elapsed(&bench), duration_kbps(&bench, length));
}
- return retval;
+ return ERROR_OK;
}
COMMAND_HANDLER(handle_flash_erase_command)
@@ -332,16 +340,21 @@ COMMAND_HANDLER(handle_flash_erase_command)
retval = flash_driver_erase(p, first, last);
- if (retval == ERROR_OK && duration_measure(&bench) == ERROR_OK) {
+ if (retval == ERROR_FLASH_OPER_UNSUPPORTED) {
+ command_print(CMD, "erase operation is not supported");
+ return retval;
+ } else if (retval != ERROR_OK) {
+ command_print(CMD, "failed to erase sectors");
+ return retval;
+ }
+
+ if (duration_measure(&bench) == ERROR_OK) {
command_print(CMD, "erased sectors %" PRIu32 " "
"through %" PRIu32 " on flash bank %u "
"in %fs", first, last, p->bank_number, duration_elapsed(&bench));
}
- if (retval != ERROR_OK)
- command_print(CMD, "failed to erase sectors");
-
- return retval;
+ return ERROR_OK;
}
COMMAND_HANDLER(handle_flash_protect_command)
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index e9073468a..934ba2265 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -3654,8 +3654,12 @@ static int gdb_v_packet(struct connection *connection,
target_call_event_callbacks(target,
TARGET_EVENT_GDB_FLASH_ERASE_END);
- /* perform erase */
- if (result != ERROR_OK) {
+ /* Perform erase.
+ * If the driver does not support erase, we silently ignore it.
+ * This is expected for non-flash NVM which does not require an erase
+ * operation before programming.
+ */
+ if (result != ERROR_OK && result != ERROR_FLASH_OPER_UNSUPPORTED) {
/* GDB doesn't evaluate the actual error number returned,
* treat a failed erase as an I/O error
*/
-----------------------------------------------------------------------
Summary of changes:
src/flash/nor/core.c | 8 +-------
src/flash/nor/tcl.c | 27 ++++++++++++++++++++-------
src/server/gdb_server.c | 8 ++++++--
3 files changed, 27 insertions(+), 16 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-16 07:31: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 930a525e7c18146e96586aff017119ba702d9018 (commit)
from 30efa3e11f10b5eff0d2449c9fe0223c8f1e49ed (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 930a525e7c18146e96586aff017119ba702d9018
Author: Marc Schink <de...@za...>
Date: Sun Dec 7 15:35:37 2025 +0000
flash/nor: Support erase operation on banks without sectors
This enables erasing flash banks that have no sectors, such as
configuration areas. Currently, these banks use a single sector as a
workaround.
This change is also required for a follow-up patch that adds support for
non-flash NVM, such as RRAM, which has no concept of sectors at all.
Although erase operations are not needed, GDB still issues them because
all NVM is advertised as flash memory. Internally, we treat the erase
operation as a no-op.
Note that this change is a pragmatic workaround given the current
codebase constraints, not the ideal implementation. In the future, a
model of NVM banks that better reflects their different properties
should be implemented.
Tested with nRF54L15-DK, tested for regression with AT32F421C8T7.
Change-Id: I0ff4ecd36332aa8e0d73bf7cf81fcda4381d6532
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/9288
Reviewed-by: Tomas Vanek <tom...@gm...>
Tested-by: jenkins
diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c
index 6a9d58ee2..e71546348 100644
--- a/src/flash/nor/core.c
+++ b/src/flash/nor/core.c
@@ -468,19 +468,22 @@ static int flash_iterate_address_range_inner(struct target *target,
if (retval != ERROR_OK)
return retval;
- if (c->size == 0 || c->num_sectors == 0) {
+ if (c->size == 0) {
LOG_ERROR("Bank is invalid");
return ERROR_FLASH_BANK_INVALID;
}
- if (length == 0) {
- /* special case, erase whole bank when length is zero */
+ if (length == 0 || c->sectors == 0) {
+ /*
+ * Special case, erase whole bank when length is zero or the
+ * bank has no sectors.
+ */
if (addr != c->base) {
LOG_ERROR("Whole bank access must start at beginning of bank.");
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}
- return callback(c, 0, c->num_sectors - 1);
+ return callback(c, 0, (c->num_sectors == 0) ? 0 : c->num_sectors - 1);
}
/* check whether it all fits in this bank */
diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c
index 5b8bda884..9cf7fdfef 100644
--- a/src/flash/nor/tcl.c
+++ b/src/flash/nor/tcl.c
@@ -302,23 +302,29 @@ COMMAND_HANDLER(handle_flash_erase_command)
if (retval != ERROR_OK)
return retval;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first);
- if (strcmp(CMD_ARGV[2], "last") == 0)
- last = p->num_sectors - 1;
- else
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);
+ if (p->num_sectors == 0) {
+ LOG_INFO("bank has no sectors, ignoring specified sectors");
+ first = 0;
+ last = 0;
+ } else {
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first);
+ if (strcmp(CMD_ARGV[2], "last") == 0)
+ last = p->num_sectors - 1;
+ else
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);
- if (!(first <= last)) {
- command_print(CMD, "ERROR: "
- "first sector must be <= last");
- return ERROR_FAIL;
- }
+ if (!(first <= last)) {
+ command_print(CMD, "ERROR: "
+ "first sector must be <= last");
+ return ERROR_FAIL;
+ }
- if (!(last <= (p->num_sectors - 1))) {
- command_print(CMD, "ERROR: "
- "last sector must be <= %u",
- p->num_sectors - 1);
- return ERROR_FAIL;
+ if (!(last <= (p->num_sectors - 1))) {
+ command_print(CMD, "ERROR: "
+ "last sector must be <= %u",
+ p->num_sectors - 1);
+ return ERROR_FAIL;
+ }
}
struct duration bench;
-----------------------------------------------------------------------
Summary of changes:
src/flash/nor/core.c | 11 +++++++----
src/flash/nor/tcl.c | 36 +++++++++++++++++++++---------------
2 files changed, 28 insertions(+), 19 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-16 07:28:10
|
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 30efa3e11f10b5eff0d2449c9fe0223c8f1e49ed (commit)
from 88a7138d344cab5227634c19e0abcfebc0c55948 (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 30efa3e11f10b5eff0d2449c9fe0223c8f1e49ed
Author: Marc Schink <de...@za...>
Date: Thu Aug 7 09:29:21 2025 +0200
flash/nor: Add error message to 'flash protect'
Provide an error message to the caller.
While at it, remove some unnecessary parentheses.
Change-Id: I5db1e5d25650e1f71425b5e41c26f3470dc1e032
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/9285
Tested-by: jenkins
Reviewed-by: Tomas Vanek <tom...@gm...>
Reviewed-by: Tarek BOCHKATI <tar...@gm...>
diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c
index c792a7083..5b8bda884 100644
--- a/src/flash/nor/tcl.c
+++ b/src/flash/nor/tcl.c
@@ -384,15 +384,18 @@ COMMAND_HANDLER(handle_flash_protect_command)
}
retval = flash_driver_protect(p, set, first, last);
- if (retval == ERROR_OK) {
- command_print(CMD, "%s protection for %s %" PRIu32
- " through %" PRIu32 " on flash bank %d",
- (set) ? "set" : "cleared",
- (p->num_prot_blocks) ? "blocks" : "sectors",
- first, last, p->bank_number);
+ if (retval != ERROR_OK) {
+ command_print(CMD, "failed to %s protection", set ? "set" : "clear");
+ return retval;
}
- return retval;
+ command_print(CMD, "%s protection for %s %" PRIu32
+ " through %" PRIu32 " on flash bank %d",
+ set ? "set" : "cleared",
+ p->num_prot_blocks ? "blocks" : "sectors",
+ first, last, p->bank_number);
+
+ return ERROR_OK;
}
COMMAND_HANDLER(handle_flash_write_image_command)
-----------------------------------------------------------------------
Summary of changes:
src/flash/nor/tcl.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-16 07:27: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 88a7138d344cab5227634c19e0abcfebc0c55948 (commit)
from ce6f83a74a7584909545dfdfb453a2d57befcd1a (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 88a7138d344cab5227634c19e0abcfebc0c55948
Author: Marc Schink <de...@za...>
Date: Mon Aug 4 12:55:46 2025 +0200
flash/nor: Add error message to 'flash erase_sector'
Provide an error message to the caller.
Change-Id: I2290323c0aabbe156d5bcfea02371df184a0095f
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/9284
Reviewed-by: Tomas Vanek <tom...@gm...>
Tested-by: jenkins
Reviewed-by: Tarek BOCHKATI <tar...@gm...>
diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c
index 0a0de8e24..c792a7083 100644
--- a/src/flash/nor/tcl.c
+++ b/src/flash/nor/tcl.c
@@ -332,6 +332,9 @@ COMMAND_HANDLER(handle_flash_erase_command)
"in %fs", first, last, p->bank_number, duration_elapsed(&bench));
}
+ if (retval != ERROR_OK)
+ command_print(CMD, "failed to erase sectors");
+
return retval;
}
-----------------------------------------------------------------------
Summary of changes:
src/flash/nor/tcl.c | 3 +++
1 file changed, 3 insertions(+)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-16 07:25:24
|
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 ce6f83a74a7584909545dfdfb453a2d57befcd1a (commit)
from 2075427d1585dc1bc17f75a51df91a1b20b4ad4b (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 ce6f83a74a7584909545dfdfb453a2d57befcd1a
Author: Marc Schink <de...@za...>
Date: Sun Mar 16 11:17:25 2025 +0000
flash/nor: Add nRF54 NVM driver
The driver is intentionally not integrated into the 'nRF5' driver in
order to serve as a kind of 'test vehicle' for non-flash memory drivers.
The driver does not support the UICR but only the main memory region.
Change-Id: Ia69527c4e07d40e8805186be8e988c0d74c12041
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8818
Tested-by: jenkins
Reviewed-by: Tomas Vanek <tom...@gm...>
diff --git a/doc/openocd.texi b/doc/openocd.texi
index 21af250f9..9b7c64d64 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -8076,6 +8076,19 @@ code.
@end deffn
+@deffn {Flash Driver} {nrf54}
+This driver supports the nRF54 microcontroller family from Nordic Semiconductor.
+These devices use a resistive random access memory (RRAM) and no flash memory technology.
+This technology requires no special erase operation, data can be arbitrarily manipulated.
+
+The UICR memory region is currently not supported by the driver.
+
+@example
+flash bank $_FLASHNAME nrf54 0 0x00000000 0 0 $_TARGETNAME
+@end example
+
+@end deffn
+
@deffn {Flash Driver} {ocl}
This driver is an implementation of the ``on chip flash loader''
protocol proposed by Pavel Chromy.
diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am
index bd39b21e3..58f6d5bd5 100644
--- a/src/flash/nor/Makefile.am
+++ b/src/flash/nor/Makefile.am
@@ -55,6 +55,7 @@ NOR_DRIVERS = \
%D%/non_cfi.c \
%D%/npcx.c \
%D%/nrf5.c \
+ %D%/nrf54.c \
%D%/numicro.c \
%D%/ocl.c \
%D%/pac55xx.c \
diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h
index 4031eacae..16c3756f3 100644
--- a/src/flash/nor/driver.h
+++ b/src/flash/nor/driver.h
@@ -298,6 +298,7 @@ extern const struct flash_driver niietcm4_flash;
extern const struct flash_driver npcx_flash;
extern const struct flash_driver nrf51_flash;
extern const struct flash_driver nrf5_flash;
+extern const struct flash_driver nrf54_flash;
extern const struct flash_driver numicro_flash;
extern const struct flash_driver ocl_flash;
extern const struct flash_driver pac55xx_flash;
diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
index c9ff774f8..335170a0b 100644
--- a/src/flash/nor/drivers.c
+++ b/src/flash/nor/drivers.c
@@ -64,6 +64,7 @@ static const struct flash_driver * const flash_drivers[] = {
&npcx_flash,
&nrf51_flash,
&nrf5_flash,
+ &nrf54_flash,
&numicro_flash,
&ocl_flash,
&pac55xx_flash,
diff --git a/src/flash/nor/nrf54.c b/src/flash/nor/nrf54.c
new file mode 100644
index 000000000..3b90784a3
--- /dev/null
+++ b/src/flash/nor/nrf54.c
@@ -0,0 +1,376 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "imp.h"
+#include <helper/binarybuffer.h>
+#include <target/algorithm.h>
+#include <target/armv7m.h>
+#include <helper/types.h>
+#include <helper/time_support.h>
+#include <helper/bits.h>
+
+/*
+ * Related documents
+ *
+ * nRF54L15, nRF54L10, and nRF54L05 Wireless SoCs
+ * https://docs-be.nordicsemi.com/bundle/ps_nrf54L15/page/pdf/nRF54L15_nRF54L10_nRF54L05_Datasheet_v0.8.pdf
+ *
+ * nRF54L Series Production Programming
+ * https://docs-be.nordicsemi.com/bundle/nan_047/attach/nan_047.pdf
+ */
+
+#define NRF54_FICR_BASE_ADDR 0x00FFC000
+
+#define NRF54_FICR_INFO_PART_REG 0x31c
+#define NRF54_FICR_INFO_VARIANT_REG 0x320
+#define NRF54_FICR_INFO_PACKAGE_REG 0x324
+#define NRF54_FICR_INFO_RAM_REG 0x328
+#define NRF54_FICR_INFO_RRAM_REG 0x32C
+
+#define NRF54_RRAM_BASE_ADDR 0x00000000
+
+#define NRF54_RRAMC_BASE_ADDR 0x5004B000
+
+#define NRF54_RRAMC_REG_CONFIG 0x500
+#define NRF54_RRAMC_REG_READY 0x400
+
+#define NRF54_RRAMC_CONFIG_WEN BIT(0)
+
+struct {
+ uint32_t id;
+ const char *name;
+} nrf54_part_names[] = {
+ { 0x00054B15, "nRF54L15" },
+ { 0x00054B10, "nRF54L10" },
+ { 0x00054B05, "nRF54L05" },
+};
+
+struct nrf54_ficr_info {
+ // Part identification number.
+ uint32_t part;
+ /*
+ * Part variant (V), hardware version (H) and production
+ * configuration (P) encoded as ASCII: <VV><H><P>.
+ */
+ uint32_t variant;
+ /*
+ * Package variant (P) encoded as ASCII: <__><PP>, where (_) indicates
+ * the null character.
+ */
+ uint32_t package;
+ // SRAM size in KiB.
+ uint32_t sram_size;
+ // RRAM size in KiB.
+ uint32_t rram_size;
+};
+
+struct nrf54_info {
+ bool probed;
+ const char *part_name;
+
+ struct nrf54_ficr_info ficr_info;
+};
+
+static int nrf54_read_ficr_info(struct target *target,
+ struct nrf54_ficr_info *info)
+{
+ int retval = target_read_u32(target,
+ NRF54_FICR_BASE_ADDR + NRF54_FICR_INFO_PART_REG, &info->part);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_read_u32(target,
+ NRF54_FICR_BASE_ADDR + NRF54_FICR_INFO_VARIANT_REG, &info->variant);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_read_u32(target,
+ NRF54_FICR_BASE_ADDR + NRF54_FICR_INFO_PACKAGE_REG, &info->package);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_read_u32(target,
+ NRF54_FICR_BASE_ADDR + NRF54_FICR_INFO_RAM_REG, &info->sram_size);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_read_u32(target,
+ NRF54_FICR_BASE_ADDR + NRF54_FICR_INFO_RRAM_REG, &info->rram_size);
+ if (retval != ERROR_OK)
+ return retval;
+
+ return ERROR_OK;
+}
+
+static const char *nrf54_get_part_name(uint32_t id)
+{
+ for (size_t i = 0; i < ARRAY_SIZE(nrf54_part_names); i++) {
+ if (id == nrf54_part_names[i].id)
+ return nrf54_part_names[i].name;
+ }
+
+ return NULL;
+}
+
+static void nrf54_u32_to_str(uint32_t data, char *str)
+{
+ uint8_t tmp[4];
+
+ h_u32_to_be(tmp, data);
+ memcpy(str, tmp, 4);
+ str[4] = '\0';
+}
+
+static bool nrf54_get_chip_type_str(const struct nrf54_info *info,
+ char *buf, size_t size)
+{
+ char variant[5];
+ nrf54_u32_to_str(info->ficr_info.variant, variant);
+
+ char package[5];
+ // Note that the first two characters are always null characters.
+ nrf54_u32_to_str(info->ficr_info.package, package);
+
+ int res = snprintf(buf, size, "%s-%c%c%c%c",
+ info->part_name, package[2], package[3], variant[0], variant[1]);
+
+ if (res < 0)
+ return false;
+
+ if ((size_t)res >= size)
+ return false;
+
+ return true;
+}
+
+static int nrf54_info(struct flash_bank *bank, struct command_invocation *cmd)
+{
+ struct nrf54_info *info = bank->driver_priv;
+
+ char chip_type[128];
+ if (!nrf54_get_chip_type_str(info, chip_type, sizeof(chip_type))) {
+ LOG_ERROR("Failed to build chip type string");
+ return ERROR_FAIL;
+ }
+
+ command_print_sameline(cmd, "%s %" PRIu32 " KiB RRAM, %" PRIu32 " KiB SRAM",
+ chip_type, info->ficr_info.rram_size, info->ficr_info.sram_size);
+
+ return ERROR_OK;
+}
+
+static int nrf54_probe(struct flash_bank *bank)
+{
+ struct target *target = bank->target;
+ struct nrf54_info *nrf54_info = bank->driver_priv;
+ struct nrf54_ficr_info *ficr_info = &nrf54_info->ficr_info;
+
+ int retval = nrf54_read_ficr_info(target, ficr_info);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to load FICR from device");
+ return retval;
+ }
+
+ const char *part_name = nrf54_get_part_name(ficr_info->part);
+
+ if (!part_name) {
+ LOG_ERROR("Unknown device with part number 0x%08" PRIx32,
+ nrf54_info->ficr_info.part);
+ return ERROR_FAIL;
+ }
+
+ nrf54_info->part_name = part_name;
+ bank->size = ficr_info->rram_size * 1024;
+
+ nrf54_info->probed = true;
+
+ // RRAM has no alignment constraints, see section 4.2.6.2 in the datasheet.
+ bank->write_start_alignment = 0;
+ bank->write_end_alignment = 0;
+
+ return ERROR_OK;
+}
+
+static int nrf54_auto_probe(struct flash_bank *bank)
+{
+ struct nrf54_info *info = bank->driver_priv;
+
+ if (!info->probed)
+ return nrf54_probe(bank);
+
+ return ERROR_OK;
+}
+
+static int nrf54_wait_until_ready(struct target *target, uint32_t timeout)
+{
+ const int64_t start_time = timeval_ms();
+
+ while (true) {
+ uint32_t ready;
+ int retval = target_read_u32(target,
+ NRF54_RRAMC_BASE_ADDR + NRF54_RRAMC_REG_READY, &ready);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ /*
+ * Send a 'keep-alive' signal before checking if the target is ready.
+ * The target is usually ready immediately, so without this 'keep-alive'
+ * it would process consecutive write calls without any keep-alive and
+ * eventually trigger a timeout.
+ */
+ keep_alive();
+
+ if (ready)
+ break;
+
+ if ((timeval_ms() - start_time) > timeout) {
+ LOG_ERROR("Timed out waiting for RRAM");
+ return ERROR_FAIL;
+ }
+ }
+
+ return ERROR_OK;
+}
+
+static int nrf54_write(struct flash_bank *bank, const uint8_t *buffer,
+ uint32_t offset, uint32_t count)
+{
+ struct target *target = bank->target;
+
+ if (target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ // Write buffer size in 128-bit words, we always use the maximum.
+ const uint32_t write_buffer_size = 32;
+
+ // Unlock RRAM to enables writes and configure the write buffer size.
+ int retval = target_write_u32(target,
+ NRF54_RRAMC_BASE_ADDR + NRF54_RRAMC_REG_CONFIG,
+ (write_buffer_size << 8) | NRF54_RRAMC_CONFIG_WEN);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to unlock RRAM");
+ return retval;
+ }
+
+ retval = nrf54_wait_until_ready(target, 1000);
+ if (retval != ERROR_OK)
+ goto error;
+
+ // See section (4.2.6.2) in the datasheet about writing to RRAM.
+ const uint32_t buffer_size = (write_buffer_size == 0) ?
+ 4 : write_buffer_size * 16;
+
+ while (count > 0) {
+ const uint32_t write_size = MIN(buffer_size, count);
+ retval = target_write_buffer(target, bank->base + offset, write_size,
+ buffer);
+
+ if (retval != ERROR_OK)
+ goto error;
+
+ retval = nrf54_wait_until_ready(target, 1000);
+ if (retval != ERROR_OK)
+ goto error;
+
+ offset += write_size;
+ buffer += write_size;
+ count -= write_size;
+ }
+
+ // Check if there is data in the write-buffer that needs to be committed.
+ uint32_t buf_status;
+ retval = target_read_u32(target, NRF54_RRAMC_BASE_ADDR + 0x418, &buf_status);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to read write-buffer status");
+ goto error;
+ }
+
+ if (!buf_status) {
+ LOG_DEBUG("Commit data from write-buffer to RRAM");
+
+ retval = target_write_u32(target, NRF54_RRAMC_BASE_ADDR + 0x8, 0x1);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to start write-buffer commit task");
+ goto error;
+ }
+
+ retval = nrf54_wait_until_ready(target, 1000);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Timed out during write-buffer commit task");
+ goto error;
+ }
+ }
+
+ int retval_lock;
+error:
+ // Lock RRAMC and disable writes.
+ retval_lock = target_write_u32(target,
+ NRF54_RRAMC_BASE_ADDR + NRF54_RRAMC_REG_CONFIG, 0x0);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (retval_lock != ERROR_OK) {
+ LOG_ERROR("Failed to lock RRAMC");
+ return retval_lock;
+ }
+
+ return ERROR_OK;
+}
+
+static int nrf54_erase(struct flash_bank *bank, unsigned int first,
+ unsigned int last)
+{
+ return ERROR_FLASH_OPER_UNSUPPORTED;
+}
+
+FLASH_BANK_COMMAND_HANDLER(nrf54_flash_bank_command)
+{
+ if (bank->base != NRF54_RRAM_BASE_ADDR) {
+ LOG_ERROR("Bank base address must be %" PRIx32, NRF54_RRAM_BASE_ADDR);
+ return ERROR_FAIL;
+ }
+
+ struct nrf54_info *nrf54_info = calloc(1, sizeof(struct nrf54_info));
+
+ if (!nrf54_info) {
+ LOG_ERROR("Failed to allocate memory");
+ return ERROR_FAIL;
+ }
+
+ nrf54_info->probed = false;
+ bank->driver_priv = nrf54_info;
+
+ return ERROR_OK;
+}
+
+static const struct command_registration nrf54_command_handlers[] = {
+ {
+ .name = "nrf54",
+ .mode = COMMAND_ANY,
+ .help = "nrf54 flash command group",
+ .usage = "",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+const struct flash_driver nrf54_flash = {
+ .name = "nrf54",
+ .commands = nrf54_command_handlers,
+ .flash_bank_command = nrf54_flash_bank_command,
+ .info = nrf54_info,
+ .erase = nrf54_erase,
+ .write = nrf54_write,
+ .read = default_flash_read,
+ .probe = nrf54_probe,
+ .auto_probe = nrf54_auto_probe,
+ .erase_check = default_flash_blank_check,
+ .free_driver_priv = default_flash_free_driver_priv,
+};
-----------------------------------------------------------------------
Summary of changes:
doc/openocd.texi | 13 ++
src/flash/nor/Makefile.am | 1 +
src/flash/nor/driver.h | 1 +
src/flash/nor/drivers.c | 1 +
src/flash/nor/nrf54.c | 376 ++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 392 insertions(+)
create mode 100644 src/flash/nor/nrf54.c
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-13 13:09:23
|
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 2075427d1585dc1bc17f75a51df91a1b20b4ad4b (commit)
from 60343e5cf960c68731353c5ad47307d3341aa313 (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 2075427d1585dc1bc17f75a51df91a1b20b4ad4b
Author: Jasper v. Blanckenburg <ja...@me...>
Date: Mon Sep 28 17:59:16 2026 +0200
flash/nor/kinetis: support nvm_partition on S32K1
The Program Partition command of the S32K1xx FTFC takes the same FCCOB
layout for FlexRAM load option, EEPROM size and DEPART as on Kinetis,
with two differences:
- There is no EEPROM split: FCCOB4[7:4] must be 0, otherwise the
command fails with ACCERR.
- DEPART is in SIM_FCFG1[15:12], so 'nvm_partition info' has to use
kinetis_fcfg1_depart().
Move the NULL check of k_chip to the start of the handler, as k_chip is
now dereferenced for the chip type check before any other use.
Tested on S32K118 after 'kinetis mdm mass_erase' and reset:
- eebkp 32 2048: FCFG1 DEPART 0x3, FlexRAM loaded as EEPROM after reset
(FCNFG[EEERDY]) and EEPROM contents survive a reset
- eebkp 32 1024 1024 off: FlexRAM not loaded (FCNFG[RAMRDY])
- dataflash 8 2048, dataflash 32: DEPART 0x9 / 0xb, 'info' reports
data flash 8 KB / 32 KB
- repartitioning without mass erase, eebkp 32 512 1536, dataflash 32
2048 and eebkp 32 (without EEPROM) are rejected
Checkpatch-ignore: BAD_SIGN_OFF
Change-Id: Iea6dbc930cfb2d57a18aa64b802cc019af3af333
Co-authored-by: Claude Opus 5.5 <no...@an...>
Signed-off-by: Jasper v. Blanckenburg <ja...@me...>
Reviewed-on: https://review.openocd.org/c/openocd/+/10078
Tested-by: jenkins
Reviewed-by: Tomas Vanek <tom...@gm...>
diff --git a/doc/openocd.texi b/doc/openocd.texi
index c5c353572..21af250f9 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -7574,8 +7574,7 @@ command completes.
@end deffn
@deffn {Command} {kinetis nvm_partition}
-For FlexNVM devices only (KxxDX and KxxFX).
-Not supported (yet) on S32K1 devices.
+For FlexNVM devices only (KxxDX, KxxFX and S32K1xx).
Command shows or sets data flash or EEPROM backup size in kilobytes,
sets two EEPROM blocks sizes in bytes and enables/disables loading
of EEPROM contents to FlexRAM during reset.
@@ -7602,6 +7601,14 @@ of 1024 bytes and its contents is not loaded to FlexRAM during reset:
@example
kinetis nvm_partition eebkp 16 1024 1024 off
@end example
+
+S32K1xx devices have a single EEPROM block, so specify the total EEPROM size
+only. Use @command{kinetis mdm mass_erase} to clear an existing partition. Set
+32 KB EEPROM backup (no data flash) with 2 KB EEPROM, loaded to FlexRAM during
+reset:
+@example
+kinetis nvm_partition eebkp 32 2048
+@end example
@end deffn
@deffn {Command} {kinetis mdm reset}
diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c
index 6f3dad5d2..c18f16646 100644
--- a/src/flash/nor/kinetis.c
+++ b/src/flash/nor/kinetis.c
@@ -3186,9 +3186,8 @@ COMMAND_HANDLER(kinetis_nvm_partition)
uint32_t sim_fcfg1;
k_chip = kinetis_get_chip(target);
-
- if (k_chip->chip_type == KINETIS_CT_S32K) {
- LOG_ERROR("NVM partition not supported on S32K1xx (yet).");
+ if (!k_chip) {
+ command_print(CMD, "[%s] is not a Kinetis chip", target_name(target));
return ERROR_FAIL;
}
@@ -3204,10 +3203,6 @@ COMMAND_HANDLER(kinetis_nvm_partition)
}
switch (sz_type) {
case SHOW_INFO:
- if (!k_chip) {
- LOG_ERROR("Chip not probed.");
- return ERROR_FAIL;
- }
result = target_read_u32(target, k_chip->sim_base + SIM_FCFG1_OFFSET, &sim_fcfg1);
if (result != ERROR_OK)
return result;
@@ -3273,6 +3268,11 @@ COMMAND_HANDLER(kinetis_nvm_partition)
}
}
+ if (k_chip->chip_type == KINETIS_CT_S32K && ee1 != ee2) {
+ LOG_ERROR("S32K1xx EEPROM cannot be split into two blocks");
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
if (ee1 * 3 == ee2)
ee_split = 1;
else if (ee1 * 7 == ee2)
@@ -3290,6 +3290,10 @@ COMMAND_HANDLER(kinetis_nvm_partition)
if (enable)
load_flex_ram = 0;
+ /* S32K1xx has no EEPROM split and rejects the command if split bits are set */
+ if (k_chip->chip_type == KINETIS_CT_S32K)
+ ee_size_code &= 0x0f;
+
LOG_INFO("DEPART 0x%" PRIx8 ", EEPROM size code 0x%" PRIx8,
flex_nvm_partition_code, ee_size_code);
@@ -3310,13 +3314,11 @@ COMMAND_HANDLER(kinetis_nvm_partition)
command_print(CMD, "FlexNVM partition set. Please reset MCU.");
- if (k_chip) {
- first_nvm_bank = k_chip->num_pflash_blocks;
- num_blocks = k_chip->num_pflash_blocks + k_chip->num_nvm_blocks;
- for (bank_idx = first_nvm_bank; bank_idx < num_blocks; bank_idx++)
- k_chip->banks[bank_idx].probed = false; /* re-probe before next use */
- k_chip->probed = false;
- }
+ first_nvm_bank = k_chip->num_pflash_blocks;
+ num_blocks = k_chip->num_pflash_blocks + k_chip->num_nvm_blocks;
+ for (bank_idx = first_nvm_bank; bank_idx < num_blocks; bank_idx++)
+ k_chip->banks[bank_idx].probed = false; /* re-probe before next use */
+ k_chip->probed = false;
command_print(CMD, "FlexNVM banks will be re-probed to set new data flash size.");
return ERROR_OK;
-----------------------------------------------------------------------
Summary of changes:
doc/openocd.texi | 11 +++++++++--
src/flash/nor/kinetis.c | 30 ++++++++++++++++--------------
2 files changed, 25 insertions(+), 16 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-13 13:08: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 60343e5cf960c68731353c5ad47307d3341aa313 (commit)
via a59bf8b7d2b5d43699ab69db97724084eb4af46a (commit)
from 751e5af67bf487c0f45ed2f5b53043dacfe72404 (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 60343e5cf960c68731353c5ad47307d3341aa313
Author: Jasper v. Blanckenburg <ja...@me...>
Date: Mon Sep 28 17:57:42 2026 +0200
flash/nor/kinetis: fix S32K1 FlexNVM partition decoding
Two problems with SIM_FCFG1[DEPART] on S32K1xx:
DEPART 0xf was treated like a 1xxx data flash size code. This can be
valid on S32K148, but not any other S32K1xx parts.
Also, kinetis_blank_check() read DEPART from bits 11:8 as on Kinetis K.
On S32K1xx these bits are reserved and DEPART is in bits 15:12, so the
block command was used even with an EEPROM backup partition and failed
with ACCERR ("Flash operation failed, illegal command") before falling
back to sector checks.
Tested on S32K118, unpartitioned: probe reports 0 KiB data flash instead
of 512 KiB. Partitioned as 8 KiB data flash / 24 KiB EEPROM backup:
'flash erase_check' on the FlexNVM bank no longer reports an error.
Checkpatch-ignore: BAD_SIGN_OFF
Change-Id: Iee5483f0f54db038dab905b2c67aeac2d4013762
Co-authored-by: Claude Opus 5.5 <no...@an...>
Signed-off-by: Jasper v. Blanckenburg <ja...@me...>
Reviewed-on: https://review.openocd.org/c/openocd/+/10077
Reviewed-by: Tomas Vanek <tom...@gm...>
Tested-by: jenkins
diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c
index 69eb8d343..6f3dad5d2 100644
--- a/src/flash/nor/kinetis.c
+++ b/src/flash/nor/kinetis.c
@@ -275,6 +275,11 @@ struct kinetis_flash_bank {
#define KINETIS_MAX_BANKS 4u
+enum kinetis_chip_type {
+ KINETIS_CT_KINETIS = 0,
+ KINETIS_CT_S32K,
+};
+
struct kinetis_chip {
struct target *target;
bool probed;
@@ -298,10 +303,7 @@ struct kinetis_chip {
uint32_t progr_accel_ram;
uint32_t sim_base;
- enum {
- CT_KINETIS = 0,
- CT_S32K,
- } chip_type;
+ enum kinetis_chip_type chip_type;
enum {
FS_PROGRAM_SECTOR = 1,
@@ -901,6 +903,13 @@ static struct kinetis_chip *kinetis_get_chip(struct target *target)
return NULL;
}
+static uint8_t kinetis_fcfg1_depart(enum kinetis_chip_type chip_type, uint32_t sim_fcfg1)
+{
+ unsigned int shift = chip_type == KINETIS_CT_S32K ? 12 : 8;
+
+ return (sim_fcfg1 >> shift) & 0x0f;
+}
+
static int kinetis_chip_options(struct kinetis_chip *k_chip, int argc, const char *argv[])
{
for (int i = 0; i < argc; i++) {
@@ -908,7 +917,7 @@ static int kinetis_chip_options(struct kinetis_chip *k_chip, int argc, const cha
if (i + 1 < argc)
k_chip->sim_base = strtoul(argv[++i], NULL, 0);
} else if (strcmp(argv[i], "-s32k") == 0) {
- k_chip->chip_type = CT_S32K;
+ k_chip->chip_type = KINETIS_CT_S32K;
} else
LOG_ERROR("Unsupported flash bank option %s", argv[i]);
}
@@ -1174,7 +1183,7 @@ static int kinetis_disable_wdog(struct kinetis_chip *k_chip)
if (!k_chip->probed) {
switch (k_chip->chip_type) {
- case CT_S32K:
+ case KINETIS_CT_S32K:
retval = kinetis_probe_chip_s32k(k_chip);
break;
default:
@@ -2234,7 +2243,18 @@ static int kinetis_probe_chip_s32k(struct kinetis_chip *k_chip)
fcfg1_eesize = (k_chip->sim_fcfg1 >> 16) & 0x0f;
if (fcfg1_eesize <= 9)
ee_size = (16 << (10 - fcfg1_eesize));
- if ((fcfg1_depart & 0x8) == 0) {
+ if (fcfg1_depart == 0xf) {
+ /* Default value. On most S32K1xx, this means FlexNVM is not partitioned. But on S32K148, this
+ can be valid (and mean 512KB DFlash / 0KB EEPROM backup) _if_ a PGMPART has been previously
+ launched. We can't distinguish this, so there we treat it as a valid value. */
+ if (generation == 1 && subseries == 4 && derivate == 8) {
+ LOG_WARNING("DEPART 0b1111 on S32K148: assuming 512 KiB DFlash. This is only valid if a PGMPART"
+ " has been previously launched. Use DEPART 0b0000 to avoid this warning.");
+ k_chip->dflash_size = k_chip->nvm_size;
+ } else {
+ k_chip->dflash_size = 0;
+ }
+ } else if ((fcfg1_depart & 0x8) == 0) {
/* Binary 0xxx values encode the amount reserved for EEPROM emulation. */
if (fcfg1_depart)
k_chip->dflash_size = k_chip->nvm_size - (4096 << fcfg1_depart);
@@ -2920,7 +2940,7 @@ static int kinetis_probe(struct flash_bank *bank)
if (!k_chip->probed) {
switch (k_chip->chip_type) {
- case CT_S32K:
+ case KINETIS_CT_S32K:
result = kinetis_probe_chip_s32k(k_chip);
break;
default:
@@ -2998,7 +3018,7 @@ static int kinetis_probe(struct flash_bank *bank)
}
/* S32K1xx does not implement FCFG2 register. Skip checks. */
- if (k_chip->chip_type != CT_S32K) {
+ if (k_chip->chip_type != KINETIS_CT_S32K) {
fcfg2_pflsh = (uint8_t)((k_chip->sim_fcfg2 >> 23) & 0x01);
fcfg2_maxaddr0 = (uint8_t)((k_chip->sim_fcfg2 >> 24) & 0x7f);
fcfg2_maxaddr1 = (uint8_t)((k_chip->sim_fcfg2 >> 16) & 0x7f);
@@ -3102,7 +3122,7 @@ static int kinetis_blank_check(struct flash_bank *bank)
uint8_t ftfx_fstat;
if (use_block_cmd && k_bank->flash_class == FC_FLEX_NVM) {
- uint8_t fcfg1_depart = (uint8_t)((k_chip->sim_fcfg1 >> 8) & 0x0f);
+ uint8_t fcfg1_depart = kinetis_fcfg1_depart(k_chip->chip_type, k_chip->sim_fcfg1);
/* block operation cannot be used on FlexNVM when EEPROM backup partition is set */
if (fcfg1_depart != 0xf && fcfg1_depart != 0)
use_block_cmd = false;
@@ -3167,7 +3187,7 @@ COMMAND_HANDLER(kinetis_nvm_partition)
k_chip = kinetis_get_chip(target);
- if (k_chip->chip_type == CT_S32K) {
+ if (k_chip->chip_type == KINETIS_CT_S32K) {
LOG_ERROR("NVM partition not supported on S32K1xx (yet).");
return ERROR_FAIL;
}
@@ -3192,7 +3212,7 @@ COMMAND_HANDLER(kinetis_nvm_partition)
if (result != ERROR_OK)
return result;
- flex_nvm_partition_code = (uint8_t)((sim_fcfg1 >> 8) & 0x0f);
+ flex_nvm_partition_code = kinetis_fcfg1_depart(k_chip->chip_type, sim_fcfg1);
switch (flex_nvm_partition_code) {
case 0:
command_print(CMD, "No EEPROM backup, data flash only");
commit a59bf8b7d2b5d43699ab69db97724084eb4af46a
Author: Jasper v. Blanckenburg <ja...@me...>
Date: Wed Sep 30 11:54:29 2026 +0200
flash/nor/kinetis: set sysmodectrlr_type on S32K1
kinetis_probe_chip_s32k() never set sysmodectrlr_type, so it used the
default KINETIS_SMC. This resulted in using 8-bit wide registers for
SMC_PMCTRL & SMC_PMSTAT at 0x4007E001 & 0x4007E003 respectively. On
S32K1xx the SMC registers are 32 bits wide at 0x4007E00C & 0x4007E014
respectively (see the RM sec. 40.3).
Tested on S32K118: with the core in VLPR, 'flash erase_sector' now
switches to RUN mode first (SMC_PMSTAT 0x04 -> 0x01).
Checkpatch-ignore: BAD_SIGN_OFF
Change-Id: Iaeefbd1bd16314295090a0a7b85eb40affa1f92c
Co-authored-by: Claude Opus 5.5 <no...@an...>
Signed-off-by: Jasper v. Blanckenburg <ja...@me...>
Reviewed-on: https://review.openocd.org/c/openocd/+/10076
Tested-by: jenkins
Reviewed-by: Tomas Vanek <tom...@gm...>
diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c
index 266b447c0..69eb8d343 100644
--- a/src/flash/nor/kinetis.c
+++ b/src/flash/nor/kinetis.c
@@ -2121,6 +2121,7 @@ static int kinetis_probe_chip_s32k(struct kinetis_chip *k_chip)
k_chip->progr_accel_ram = FLEXRAM;
k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR;
k_chip->watchdog_type = KINETIS_WDOG32_KE1X;
+ k_chip->sysmodectrlr_type = KINETIS_SMC32;
if (k_chip->sim_base == 0)
k_chip->sim_base = SIM_BASE;
-----------------------------------------------------------------------
Summary of changes:
src/flash/nor/kinetis.c | 45 +++++++++++++++++++++++++++++++++------------
1 file changed, 33 insertions(+), 12 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-11 10:05:54
|
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 751e5af67bf487c0f45ed2f5b53043dacfe72404 (commit)
from f4a4ac23d64ff055baa0754a1d54b2b3a0a1a930 (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 751e5af67bf487c0f45ed2f5b53043dacfe72404
Author: Kulyatskaya Alexandra <a.k...@sy...>
Date: Mon Nov 17 15:55:17 2025 +0300
target: prevent image load to overwrite a breakpoint
Call function 'is_breakpoint_in_range()' in handler_load_image_command and
handle_fast_load_command for detecting breakpoint memory overwriting.
Change-Id: I8fb6c9811dc7322d78ec9cbba0e4641d619b7e03
Signed-off-by: Kulyatskaya Alexandra <a.k...@sy...>
Reviewed-on: https://review.openocd.org/c/openocd/+/9240
Reviewed-by: Antonio Borneo <bor...@gm...>
Tested-by: jenkins
diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c
index 2c46cd3a6..eb165bdb1 100644
--- a/src/target/breakpoints.c
+++ b/src/target/breakpoints.c
@@ -37,6 +37,23 @@ static const char * const watchpoint_rw_strings[] = {
/* monotonic counter/id-number for breakpoints and watch points */
static int bpwp_unique_id;
+COMMAND_HELPER(detect_breakpoints_in_section, struct target *target,
+ struct imagesection section)
+{
+ target_addr_t start = section.base_address;
+ uint32_t length = section.size;
+ bool found_breakpoint = false;
+
+ for (struct breakpoint *bp = target->breakpoints; bp; bp = bp->next)
+ if (is_memory_regions_overlap(start, length, bp->address, bp->length)) {
+ found_breakpoint = true;
+ command_print(cmd, "conflicting breakpoint at address: "
+ TARGET_ADDR_FMT, bp->address);
+ }
+
+ return found_breakpoint ? ERROR_FAIL : ERROR_OK;
+}
+
static int breakpoint_add_internal(struct target *target,
target_addr_t address,
unsigned int length,
diff --git a/src/target/breakpoints.h b/src/target/breakpoints.h
index 4f156cb16..3246b8a5c 100644
--- a/src/target/breakpoints.h
+++ b/src/target/breakpoints.h
@@ -11,6 +11,8 @@
#include <stdint.h>
#include "helper/types.h"
+#include "helper/command.h"
+#include "image.h"
struct target;
@@ -68,6 +70,9 @@ static inline void breakpoint_hw_set(struct breakpoint *breakpoint, unsigned int
breakpoint->number = hw_number;
}
+COMMAND_HELPER(detect_breakpoints_in_section, struct target *target,
+ struct imagesection section);
+
int watchpoint_add(struct target *target,
target_addr_t address, unsigned int length,
enum watchpoint_rw rw, uint64_t value, uint64_t mask);
diff --git a/src/target/target.c b/src/target/target.c
index 57470e7df..b1e28f008 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -3658,6 +3658,10 @@ COMMAND_HANDLER(handle_load_image_command)
image_size = 0x0;
retval = ERROR_OK;
for (unsigned int i = 0; i < image.num_sections; i++) {
+ retval = CALL_COMMAND_HANDLER(detect_breakpoints_in_section, target, image.sections[i]);
+ if (retval != ERROR_OK)
+ return retval;
+
buffer = malloc(image.sections[i].size);
if (!buffer) {
command_print(CMD,
@@ -6369,8 +6373,19 @@ COMMAND_HANDLER(handle_fast_load_command)
int64_t ms = timeval_ms();
int size = 0;
int retval = ERROR_OK;
+
+ struct target *target = get_current_target(CMD_CTX);
+ for (i = 0; i < fastload_num; i++) {
+ struct imagesection section = {
+ .base_address = fastload[i].address,
+ .size = fastload[i].length,
+ };
+ retval = CALL_COMMAND_HANDLER(detect_breakpoints_in_section, target, section);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
for (i = 0; i < fastload_num; i++) {
- struct target *target = get_current_target(CMD_CTX);
command_print(CMD, "Write to 0x%08x, length 0x%08x",
(unsigned int)(fastload[i].address),
(unsigned int)(fastload[i].length));
-----------------------------------------------------------------------
Summary of changes:
src/target/breakpoints.c | 17 +++++++++++++++++
src/target/breakpoints.h | 5 +++++
src/target/target.c | 17 ++++++++++++++++-
3 files changed, 38 insertions(+), 1 deletion(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-11 10:04:33
|
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 f4a4ac23d64ff055baa0754a1d54b2b3a0a1a930 (commit)
from 20620c907ba1da4dec91d2247550ab9a7beb9a1b (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 f4a4ac23d64ff055baa0754a1d54b2b3a0a1a930
Author: Marc Schink <de...@za...>
Date: Mon Sep 28 22:54:24 2026 +0200
tcl/cpld: Move Xilinx config files into vendor folder
Move the configuration files into a dedicated vendor folder as required
by the developer guidelines.
Change-Id: I638510a45c02e932df9e52ae3ec6b211baa597c8
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/10069
Tested-by: jenkins
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/tcl/cpld/xilinx-xcr3256.cfg b/tcl/cpld/xlnx/xcr3256.cfg
similarity index 100%
rename from tcl/cpld/xilinx-xcr3256.cfg
rename to tcl/cpld/xlnx/xcr3256.cfg
diff --git a/tcl/file_renaming.cfg b/tcl/file_renaming.cfg
index ca0be0330..7aa44e331 100644
--- a/tcl/file_renaming.cfg
+++ b/tcl/file_renaming.cfg
@@ -49,6 +49,7 @@ set _file_renaming {
cpld/altera-maxv.cfg cpld/altera/max-v.cfg
cpld/altera-max10.cfg fpga/altera/max-10.cfg
cpld/xilinx-xc3s.cfg fpga/xlnx/xc3s.cfg
+ cpld/xilinx-xcr3256.cfg cpld/xlnx/xcr3256.cfg
cpld/xilinx-xc4v.cfg fpga/xlnx/xc4v.cfg
cpld/xilinx-xc4vfx_40_60_100_140.cfg fpga/xlnx/xc4vfx-40-60-100-140.cfg
cpld/xilinx-xc5v.cfg fpga/xlnx/xc5v.cfg
-----------------------------------------------------------------------
Summary of changes:
tcl/cpld/{xilinx-xcr3256.cfg => xlnx/xcr3256.cfg} | 0
tcl/file_renaming.cfg | 1 +
2 files changed, 1 insertion(+)
rename tcl/cpld/{xilinx-xcr3256.cfg => xlnx/xcr3256.cfg} (100%)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-11 10:04:14
|
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 20620c907ba1da4dec91d2247550ab9a7beb9a1b (commit)
via 7a95bf8cca3390a737ee5077fa903a17d9c1e6c1 (commit)
from b20f0fb10b4352618c7de707390a3346d93aad2e (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 20620c907ba1da4dec91d2247550ab9a7beb9a1b
Author: Marc Schink <de...@za...>
Date: Mon Sep 28 22:54:18 2026 +0200
tcl/cpld: Move Lattice config files into vendor folder
Move the configuration files into a dedicated vendor folder as required
by the developer guidelines.
Change-Id: I7fa6e6bc4ca70e5272b3fbe3beca4106fd975d17
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/10068
Reviewed-by: Antonio Borneo <bor...@gm...>
Tested-by: jenkins
diff --git a/src/helper/startup.tcl b/src/helper/startup.tcl
index 25ba56f06..4d16c4c88 100644
--- a/src/helper/startup.tcl
+++ b/src/helper/startup.tcl
@@ -47,7 +47,7 @@ proc find {filename} {
return $t
}
- foreach vendor {altera gigadevice nordic sifive st ti} {
+ foreach vendor {altera gigadevice lattice nordic sifive st ti} {
# - path/to/a/certain/config_file
# replaced either with
# - path/to/a/certain/${vendor}/config_file
diff --git a/tcl/cpld/lattice-lc4032ze.cfg b/tcl/cpld/lattice/lc4032ze.cfg
similarity index 100%
rename from tcl/cpld/lattice-lc4032ze.cfg
rename to tcl/cpld/lattice/lc4032ze.cfg
commit 7a95bf8cca3390a737ee5077fa903a17d9c1e6c1
Author: Marc Schink <de...@za...>
Date: Mon Sep 28 22:54:14 2026 +0200
tcl/cpld: Move Altera config files into vendor folder
Move the configuration files into a dedicated vendor folder as required
by the developer guidelines.
Change-Id: Ibf6c7221310b7d9e676b13816d00655c091e3d16
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/10067
Tested-by: jenkins
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/tcl/cpld/altera-5m570z-cpld.cfg b/tcl/cpld/altera-5m570z-cpld.cfg
index 4504a8064..a1e7cbb08 100644
--- a/tcl/cpld/altera-5m570z-cpld.cfg
+++ b/tcl/cpld/altera-5m570z-cpld.cfg
@@ -1,9 +1,9 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# file altera-5m570z-cpld.cfg replaced by altera-maxv.cfg
-echo "DEPRECATED: use altera-maxv.cfg instead of deprecated altera-5m570z-cpld.cfg"
+echo "DEPRECATED: use cpld/altera/max-v.cfg instead of deprecated altera-5m570z-cpld.cfg"
#just to be backward compatible:
#tap will be 5m570z.tap instead of maxv.tap:
set CHIPNAME 5m570z
-source [find cpld/altera-maxv.cfg]
+source [find cpld/altera/max-v.cfg]
diff --git a/tcl/cpld/altera-epm240.cfg b/tcl/cpld/altera-epm240.cfg
index 185925a16..d645dfbd8 100644
--- a/tcl/cpld/altera-epm240.cfg
+++ b/tcl/cpld/altera-epm240.cfg
@@ -1,12 +1,12 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# file altera-epm240.cfg replaced by altera-maxii.cfg
-echo "DEPRECATED: use altera-maxii.cfg instead of deprecated altera-epm240.cfg"
+echo "DEPRECATED: use cpld/altera/max-ii.cfg instead of deprecated altera-epm240.cfg"
#just to be backward compatible:
#tap will be epm240.tap instead of maxii.tap:
set CHIPNAME epm240
-source [find cpld/altera-maxii.cfg]
+source [find cpld/altera/max-ii.cfg]
# 200ns seems like a good speed
# c.f. Table 5-34: MAX II JTAG Timing Parameters
diff --git a/tcl/cpld/altera-maxii.cfg b/tcl/cpld/altera/max-ii.cfg
similarity index 100%
rename from tcl/cpld/altera-maxii.cfg
rename to tcl/cpld/altera/max-ii.cfg
diff --git a/tcl/cpld/altera-maxv.cfg b/tcl/cpld/altera/max-v.cfg
similarity index 100%
rename from tcl/cpld/altera-maxv.cfg
rename to tcl/cpld/altera/max-v.cfg
diff --git a/tcl/file_renaming.cfg b/tcl/file_renaming.cfg
index bb8d881c7..ca0be0330 100644
--- a/tcl/file_renaming.cfg
+++ b/tcl/file_renaming.cfg
@@ -45,6 +45,8 @@ set _file_renaming {
board/ti_beaglebone-base.cfg board/beagle/beaglebone-base.cfg
board/ti_beaglebone_black.cfg board/beagle/beaglebone-black.cfg
board/ti_beaglebone.cfg board/beagle/beaglebone.cfg
+ cpld/altera-maxii.cfg cpld/altera/max-ii.cfg
+ cpld/altera-maxv.cfg cpld/altera/max-v.cfg
cpld/altera-max10.cfg fpga/altera/max-10.cfg
cpld/xilinx-xc3s.cfg fpga/xlnx/xc3s.cfg
cpld/xilinx-xc4v.cfg fpga/xlnx/xc4v.cfg
-----------------------------------------------------------------------
Summary of changes:
src/helper/startup.tcl | 2 +-
tcl/cpld/altera-5m570z-cpld.cfg | 4 ++--
tcl/cpld/altera-epm240.cfg | 4 ++--
tcl/cpld/{altera-maxii.cfg => altera/max-ii.cfg} | 0
tcl/cpld/{altera-maxv.cfg => altera/max-v.cfg} | 0
tcl/cpld/{lattice-lc4032ze.cfg => lattice/lc4032ze.cfg} | 0
tcl/file_renaming.cfg | 2 ++
7 files changed, 7 insertions(+), 5 deletions(-)
rename tcl/cpld/{altera-maxii.cfg => altera/max-ii.cfg} (100%)
rename tcl/cpld/{altera-maxv.cfg => altera/max-v.cfg} (100%)
rename tcl/cpld/{lattice-lc4032ze.cfg => lattice/lc4032ze.cfg} (100%)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-11 09:59:29
|
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 b20f0fb10b4352618c7de707390a3346d93aad2e (commit)
from 0e6ae2525d64a4b39d65f21a4ad6069daa8af3f1 (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 b20f0fb10b4352618c7de707390a3346d93aad2e
Author: Nguyen Minh Tien <tie...@em...>
Date: Wed Sep 30 19:10:42 2026 +0700
tcl/target/allwinner_v3s: create the DAP with 'dap create'
The config does not load:
Error: target requires -dap parameter instead of -tap
A cortex_a target takes its DAP from '-dap' and refuses '-tap' (before
that '-chain-position'). That was already the case when the file was
added: 0.12.0 fails the same way, naming '-chain-position'.
Create the DAP on the existing TAP and pass it with '-dap', as
ls1046a.cfg does. The TAP, the DAP and the target keep their names
(v3s.dap, v3s.cpu).
Checked with the dummy adapter only: the config loads and creates the
cortex_a target v3s.cpu on the DAP v3s.dap.
Fixes: f8367dbb4976 ("tcl/target: add Allwinner V3s SoC support")
Change-Id: Ie8396b7ffbb2b494a74bcfe7fe0f4241cbcf1f7b
Signed-off-by: Nguyen Minh Tien <tie...@em...>
Reviewed-on: https://review.openocd.org/c/openocd/+/10080
Tested-by: jenkins
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/tcl/target/allwinner_v3s.cfg b/tcl/target/allwinner_v3s.cfg
index dd0ce476f..8b22d8a1c 100644
--- a/tcl/target/allwinner_v3s.cfg
+++ b/tcl/target/allwinner_v3s.cfg
@@ -68,6 +68,8 @@ reset_config none srst_pulls_trst
jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x01 -irmask 0x0f \
-expected-id $_DAP_TAPID
+dap create $_CHIPNAME.dap -tap $_CHIPNAME.dap
+
# Add Cortex A7 core
set _TARGETNAME $_CHIPNAME.cpu
-target create $_TARGETNAME cortex_a -tap $_CHIPNAME.dap
+target create $_TARGETNAME cortex_a -dap $_CHIPNAME.dap
-----------------------------------------------------------------------
Summary of changes:
tcl/target/allwinner_v3s.cfg | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2026-10-11 09:58:37
|
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 0e6ae2525d64a4b39d65f21a4ad6069daa8af3f1 (commit)
from 6bacfd24cd5ed364528ae7bdaddcc454851d2fbb (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 0e6ae2525d64a4b39d65f21a4ad6069daa8af3f1
Author: Antonio Borneo <bor...@gm...>
Date: Thu Sep 24 15:00:51 2026 +0200
target/st/stm32mpxxx: enable smp only when working on multi-core
Setting an HW breakpoint when one target is declared in the SMP
list but is not examined causes error on OpenOCD
Info : no hardware breakpoint available
Error: [..] can't add breakpoint: resource not available
because OpenOCD doesn't know how many HW breakpoint are allowed
on the not yet examined target.
Simply drop the SMP association when only one target is debugged.
Change-Id: Ib7a5e3e6bb4329107bbc00f8334fca988a420e6c
Signed-off-by: Antonio Borneo <bor...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/10066
Tested-by: jenkins
diff --git a/tcl/target/st/stm32mp15x.cfg b/tcl/target/st/stm32mp15x.cfg
index 05bb33311..43e13dafd 100644
--- a/tcl/target/st/stm32mp15x.cfg
+++ b/tcl/target/st/stm32mp15x.cfg
@@ -68,7 +68,10 @@ target create $_CHIPNAME.cm4 cortex_m -dap $_CHIPNAME.dap -ap-num 2 -defer-exami
targets $_CHIPNAME.cpu0
-target smp $_CHIPNAME.cpu0 $_CHIPNAME.cpu1
+if {$EN_CA7_0 && $EN_CA7_1} {
+ target smp $_CHIPNAME.cpu0 $_CHIPNAME.cpu1
+}
+
$_CHIPNAME.cpu0 configure -rtos hwthread
$_CHIPNAME.cpu1 configure -rtos hwthread
diff --git a/tcl/target/st/stm32mp23x.cfg b/tcl/target/st/stm32mp23x.cfg
index 2ab6458c8..422bd8321 100644
--- a/tcl/target/st/stm32mp23x.cfg
+++ b/tcl/target/st/stm32mp23x.cfg
@@ -85,7 +85,10 @@ tpiu create $_CHIPNAME.tpiu -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0x80050000
targets $_CHIPNAME.a35_0
-target smp $_CHIPNAME.a35_0 $_CHIPNAME.a35_1
+if {$EN_CA35_0 && $EN_CA35_1} {
+ target smp $_CHIPNAME.a35_0 $_CHIPNAME.a35_1
+}
+
$_CHIPNAME.a35_0 configure -rtos hwthread
$_CHIPNAME.a35_1 configure -rtos hwthread
diff --git a/tcl/target/st/stm32mp25x.cfg b/tcl/target/st/stm32mp25x.cfg
index 360a45af5..b2d5d3c80 100644
--- a/tcl/target/st/stm32mp25x.cfg
+++ b/tcl/target/st/stm32mp25x.cfg
@@ -97,7 +97,10 @@ tpiu create $_CHIPNAME.tpiu -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0x80050000
targets $_CHIPNAME.a35_0
-target smp $_CHIPNAME.a35_0 $_CHIPNAME.a35_1
+if {$EN_CA35_0 && $EN_CA35_1} {
+ target smp $_CHIPNAME.a35_0 $_CHIPNAME.a35_1
+}
+
$_CHIPNAME.a35_0 configure -rtos hwthread
$_CHIPNAME.a35_1 configure -rtos hwthread
-----------------------------------------------------------------------
Summary of changes:
tcl/target/st/stm32mp15x.cfg | 5 ++++-
tcl/target/st/stm32mp23x.cfg | 5 ++++-
tcl/target/st/stm32mp25x.cfg | 5 ++++-
3 files changed, 12 insertions(+), 3 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|