aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2022-05-03 13:41:55 -0700
committerTim Newsome <tim@sifive.com>2022-05-03 13:41:55 -0700
commit9460f43dc356829858bcb0057c7fe0dd7153c0c6 (patch)
tree51fa5e6f157caeffeec27d0dba117c01389f6d66 /src
parentb6dddfacc05ea981aabcf76ed155f68b677950a1 (diff)
parent66335683fec62ac89da48d64932fd9d082314225 (diff)
downloadriscv-openocd-9460f43dc356829858bcb0057c7fe0dd7153c0c6.zip
riscv-openocd-9460f43dc356829858bcb0057c7fe0dd7153c0c6.tar.gz
riscv-openocd-9460f43dc356829858bcb0057c7fe0dd7153c0c6.tar.bz2
Merge branch 'master' into from_upstream
Conflicts: tcl/target/gd32vf103.cfg I kept our version, except I changed the flash device as happened in mainline. Once this file settles down in mainline, we can copy it wholesale into this fork. Change-Id: I4c5b21fec0734b5e08eba392883e006a46386b1c
Diffstat (limited to 'src')
-rw-r--r--src/flash/nor/stm32f1x.c477
-rw-r--r--src/jtag/drivers/bcm2835gpio.c13
-rw-r--r--src/jtag/drivers/cmsis_dap.c14
-rw-r--r--src/jtag/drivers/linuxgpiod.c47
-rw-r--r--src/rtos/zephyr.c6
-rw-r--r--src/server/gdb_server.c43
-rw-r--r--src/target/a64_disassembler.c2
-rw-r--r--src/target/arm_cti.c7
-rw-r--r--src/target/arm_disassembler.c2
-rw-r--r--src/target/image.c4
-rw-r--r--src/target/image.h4
11 files changed, 425 insertions, 194 deletions
diff --git a/src/flash/nor/stm32f1x.c b/src/flash/nor/stm32f1x.c
index 6972bae..c750ff0 100644
--- a/src/flash/nor/stm32f1x.c
+++ b/src/flash/nor/stm32f1x.c
@@ -26,6 +26,8 @@
#include "config.h"
#endif
+#include <string.h>
+
#include "imp.h"
#include <helper/binarybuffer.h>
#include <target/algorithm.h>
@@ -129,9 +131,8 @@ struct stm32x_flash_bank {
};
static int stm32x_mass_erase(struct flash_bank *bank);
-static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id);
static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t address, uint32_t count);
+ uint32_t address, uint32_t hwords_count);
/* flash bank stm32x <base> <size> 0 0 <target#>
*/
@@ -151,6 +152,9 @@ FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command)
stm32x_info->register_base = FLASH_REG_BASE_B0;
stm32x_info->user_bank_size = bank->size;
+ /* The flash write must be aligned to a halfword boundary */
+ bank->write_start_alignment = bank->write_end_alignment = 2;
+
return ERROR_OK;
}
@@ -182,19 +186,19 @@ static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout)
break;
if (timeout-- <= 0) {
LOG_ERROR("timed out waiting for flash");
- return ERROR_FAIL;
+ return ERROR_FLASH_BUSY;
}
alive_sleep(1);
}
if (status & FLASH_WRPRTERR) {
LOG_ERROR("stm32x device protected");
- retval = ERROR_FAIL;
+ retval = ERROR_FLASH_PROTECTED;
}
if (status & FLASH_PGERR) {
- LOG_ERROR("stm32x device programming failed");
- retval = ERROR_FAIL;
+ LOG_ERROR("stm32x device programming failed / flash not erased");
+ retval = ERROR_FLASH_OPERATION_FAILED;
}
/* Clear but report errors */
@@ -258,36 +262,39 @@ static int stm32x_erase_options(struct flash_bank *bank)
int retval = target_write_u32(target, STM32_FLASH_KEYR_B0, KEY1);
if (retval != ERROR_OK)
return retval;
-
retval = target_write_u32(target, STM32_FLASH_KEYR_B0, KEY2);
if (retval != ERROR_OK)
- return retval;
+ goto flash_lock;
/* unlock option flash registers */
retval = target_write_u32(target, STM32_FLASH_OPTKEYR_B0, KEY1);
if (retval != ERROR_OK)
- return retval;
+ goto flash_lock;
retval = target_write_u32(target, STM32_FLASH_OPTKEYR_B0, KEY2);
if (retval != ERROR_OK)
- return retval;
+ goto flash_lock;
/* erase option bytes */
retval = target_write_u32(target, STM32_FLASH_CR_B0, FLASH_OPTER | FLASH_OPTWRE);
if (retval != ERROR_OK)
- return retval;
+ goto flash_lock;
retval = target_write_u32(target, STM32_FLASH_CR_B0, FLASH_OPTER | FLASH_STRT | FLASH_OPTWRE);
if (retval != ERROR_OK)
- return retval;
+ goto flash_lock;
retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
if (retval != ERROR_OK)
- return retval;
+ goto flash_lock;
/* clear read protection option byte
* this will also force a device unlock if set */
stm32x_info->option_bytes.rdp = stm32x_info->default_rdp;
return ERROR_OK;
+
+flash_lock:
+ target_write_u32(target, STM32_FLASH_CR_B0, FLASH_LOCK);
+ return retval;
}
static int stm32x_write_options(struct flash_bank *bank)
@@ -303,20 +310,20 @@ static int stm32x_write_options(struct flash_bank *bank)
return retval;
retval = target_write_u32(target, STM32_FLASH_KEYR_B0, KEY2);
if (retval != ERROR_OK)
- return retval;
+ goto flash_lock;
/* unlock option flash registers */
retval = target_write_u32(target, STM32_FLASH_OPTKEYR_B0, KEY1);
if (retval != ERROR_OK)
- return retval;
+ goto flash_lock;
retval = target_write_u32(target, STM32_FLASH_OPTKEYR_B0, KEY2);
if (retval != ERROR_OK)
- return retval;
+ goto flash_lock;
/* program option bytes */
retval = target_write_u32(target, STM32_FLASH_CR_B0, FLASH_OPTPG | FLASH_OPTWRE);
if (retval != ERROR_OK)
- return retval;
+ goto flash_lock;
uint8_t opt_bytes[16];
@@ -329,18 +336,20 @@ static int stm32x_write_options(struct flash_bank *bank)
target_buffer_set_u16(target, opt_bytes + 12, (stm32x_info->option_bytes.protection >> 16) & 0xff);
target_buffer_set_u16(target, opt_bytes + 14, (stm32x_info->option_bytes.protection >> 24) & 0xff);
+ /* Block write is preferred in favour of operation with ancient ST-Link
+ * firmwares without 16-bit memory access. See
+ * 480: flash: stm32f1x: write option bytes using the loader
+ * https://review.openocd.org/c/openocd/+/480
+ */
retval = stm32x_write_block(bank, opt_bytes, STM32_OB_RDP, sizeof(opt_bytes) / 2);
- if (retval != ERROR_OK) {
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
- LOG_ERROR("working area required to erase options bytes");
- return retval;
- }
-
- retval = target_write_u32(target, STM32_FLASH_CR_B0, FLASH_LOCK);
- if (retval != ERROR_OK)
- return retval;
- return ERROR_OK;
+flash_lock:
+ {
+ int retval2 = target_write_u32(target, STM32_FLASH_CR_B0, FLASH_LOCK);
+ if (retval == ERROR_OK)
+ retval = retval2;
+ }
+ return retval;
}
static int stm32x_protect_check(struct flash_bank *bank)
@@ -384,31 +393,33 @@ static int stm32x_erase(struct flash_bank *bank, unsigned int first,
return retval;
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY2);
if (retval != ERROR_OK)
- return retval;
+ goto flash_lock;
for (unsigned int i = first; i <= last; i++) {
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PER);
if (retval != ERROR_OK)
- return retval;
+ goto flash_lock;
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_AR),
bank->base + bank->sectors[i].offset);
if (retval != ERROR_OK)
- return retval;
+ goto flash_lock;
retval = target_write_u32(target,
stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PER | FLASH_STRT);
if (retval != ERROR_OK)
- return retval;
+ goto flash_lock;
retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
if (retval != ERROR_OK)
- return retval;
+ goto flash_lock;
}
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
+flash_lock:
+ {
+ int retval2 = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
+ if (retval == ERROR_OK)
+ retval = retval2;
+ }
+ return retval;
}
static int stm32x_protect(struct flash_bank *bank, int set, unsigned int first,
@@ -442,17 +453,16 @@ static int stm32x_protect(struct flash_bank *bank, int set, unsigned int first,
return stm32x_write_options(bank);
}
-static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t address, uint32_t count)
+static int stm32x_write_block_async(struct flash_bank *bank, const uint8_t *buffer,
+ uint32_t address, uint32_t hwords_count)
{
struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
struct target *target = bank->target;
- uint32_t buffer_size = 16384;
+ uint32_t buffer_size;
struct working_area *write_algorithm;
struct working_area *source;
- struct reg_param reg_params[5];
struct armv7m_algorithm armv7m_info;
- int retval = ERROR_OK;
+ int retval;
static const uint8_t stm32x_flash_write_code[] = {
#include "../../../contrib/loaders/flash/stm32/stm32f1x.inc"
@@ -473,19 +483,28 @@ static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer,
}
/* memory buffer */
- while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 2;
- buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */
- if (buffer_size <= 256) {
- /* we already allocated the writing code, but failed to get a
- * buffer, free the algorithm */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING("no large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
+ buffer_size = target_get_working_area_avail(target);
+ buffer_size = MIN(hwords_count * 2, MAX(buffer_size, 256));
+ /* Normally we allocate all available working area.
+ * MIN shrinks buffer_size if the size of the written block is smaller.
+ * MAX prevents using async algo if the available working area is smaller
+ * than 256, the following allocation fails with
+ * ERROR_TARGET_RESOURCE_NOT_AVAILABLE and slow flashing takes place.
+ */
+
+ retval = target_alloc_working_area(target, buffer_size, &source);
+ /* Allocated size is always 32-bit word aligned */
+ if (retval != ERROR_OK) {
+ target_free_working_area(target, write_algorithm);
+ LOG_WARNING("no large enough working area available, can't do block memory writes");
+ /* target_alloc_working_area() may return ERROR_FAIL if area backup fails:
+ * convert any error to ERROR_TARGET_RESOURCE_NOT_AVAILABLE
+ */
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
+ struct reg_param reg_params[5];
+
init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* flash base (in), status (out) */
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* count (halfword-16bit) */
init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* buffer start */
@@ -493,7 +512,7 @@ static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer,
init_reg_param(&reg_params[4], "r4", 32, PARAM_IN_OUT); /* target address */
buf_set_u32(reg_params[0].value, 0, 32, stm32x_info->register_base);
- buf_set_u32(reg_params[1].value, 0, 32, count);
+ buf_set_u32(reg_params[1].value, 0, 32, hwords_count);
buf_set_u32(reg_params[2].value, 0, 32, source->address);
buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size);
buf_set_u32(reg_params[4].value, 0, 32, address);
@@ -501,126 +520,235 @@ static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer,
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
armv7m_info.core_mode = ARM_MODE_THREAD;
- retval = target_run_flash_async_algorithm(target, buffer, count, 2,
+ retval = target_run_flash_async_algorithm(target, buffer, hwords_count, 2,
0, NULL,
- 5, reg_params,
+ ARRAY_SIZE(reg_params), reg_params,
source->address, source->size,
write_algorithm->address, 0,
&armv7m_info);
if (retval == ERROR_FLASH_OPERATION_FAILED) {
- LOG_ERROR("flash write failed at address 0x%"PRIx32,
- buf_get_u32(reg_params[4].value, 0, 32));
-
- if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_PGERR) {
- LOG_ERROR("flash memory not erased before writing");
- /* Clear but report errors */
- target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_SR), FLASH_PGERR);
- }
+ /* Actually we just need to check for programming errors
+ * stm32x_wait_status_busy also reports error and clears status bits.
+ *
+ * Target algo returns flash status in r0 only if properly finished.
+ * It is safer to re-read status register.
+ */
+ int retval2 = stm32x_wait_status_busy(bank, 5);
+ if (retval2 != ERROR_OK)
+ retval = retval2;
- if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_WRPRTERR) {
- LOG_ERROR("flash memory write protected");
- /* Clear but report errors */
- target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_SR), FLASH_WRPRTERR);
- }
+ LOG_ERROR("flash write failed just before address 0x%"PRIx32,
+ buf_get_u32(reg_params[4].value, 0, 32));
}
+ for (unsigned int i = 0; i < ARRAY_SIZE(reg_params); i++)
+ destroy_reg_param(&reg_params[i]);
+
target_free_working_area(target, source);
target_free_working_area(target, write_algorithm);
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
-
return retval;
}
-static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
+static int stm32x_write_block_riscv(struct flash_bank *bank, const uint8_t *buffer,
+ uint32_t address, uint32_t hwords_count)
{
struct target *target = bank->target;
- uint8_t *new_buffer = NULL;
+ uint32_t buffer_size;
+ struct working_area *write_algorithm;
+ struct working_area *source;
+ static const uint8_t gd32vf103_flash_write_code[] = {
+#include "../../../contrib/loaders/flash/gd32vf103/gd32vf103.inc"
+ };
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
+ /* flash write code */
+ if (target_alloc_working_area(target, sizeof(gd32vf103_flash_write_code),
+ &write_algorithm) != ERROR_OK) {
+ LOG_WARNING("no working area available, can't do block memory writes");
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
- if (offset & 0x1) {
- LOG_ERROR("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
+ int retval = target_write_buffer(target, write_algorithm->address,
+ sizeof(gd32vf103_flash_write_code), gd32vf103_flash_write_code);
+ if (retval != ERROR_OK) {
+ target_free_working_area(target, write_algorithm);
+ return retval;
}
- /* If there's an odd number of bytes, the data has to be padded. Duplicate
- * the buffer and use the normal code path with a single block write since
- * it's probably cheaper than to special case the last odd write using
- * discrete accesses. */
- if (count & 1) {
- new_buffer = malloc(count + 1);
- if (!new_buffer) {
- LOG_ERROR("odd number of bytes to write and no memory for padding buffer");
- return ERROR_FAIL;
+ /* memory buffer */
+ buffer_size = target_get_working_area_avail(target);
+ buffer_size = MIN(hwords_count * 2, MAX(buffer_size, 256));
+
+ retval = target_alloc_working_area(target, buffer_size, &source);
+ /* Allocated size is always word aligned */
+ if (retval != ERROR_OK) {
+ target_free_working_area(target, write_algorithm);
+ LOG_WARNING("no large enough working area available, can't do block memory writes");
+ /* target_alloc_working_area() may return ERROR_FAIL if area backup fails:
+ * convert any error to ERROR_TARGET_RESOURCE_NOT_AVAILABLE
+ */
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+
+ struct reg_param reg_params[4];
+
+ init_reg_param(&reg_params[0], "a0", 32, PARAM_OUT); /* poiner to FLASH_SR */
+ init_reg_param(&reg_params[1], "a1", 32, PARAM_OUT); /* count (halfword-16bit) */
+ init_reg_param(&reg_params[2], "a2", 32, PARAM_OUT); /* buffer start */
+ init_reg_param(&reg_params[3], "a3", 32, PARAM_IN_OUT); /* target address */
+
+ while (hwords_count > 0) {
+ uint32_t thisrun_hwords = source->size / 2;
+
+ /* Limit to the amount of data we actually want to write */
+ if (thisrun_hwords > hwords_count)
+ thisrun_hwords = hwords_count;
+
+ /* Write data to buffer */
+ retval = target_write_buffer(target, source->address,
+ thisrun_hwords * 2, buffer);
+ if (retval != ERROR_OK)
+ break;
+
+ buf_set_u32(reg_params[0].value, 0, 32, stm32x_get_flash_reg(bank, STM32_FLASH_SR));
+ buf_set_u32(reg_params[1].value, 0, 32, thisrun_hwords);
+ buf_set_u32(reg_params[2].value, 0, 32, source->address);
+ buf_set_u32(reg_params[3].value, 0, 32, address);
+
+ retval = target_run_algorithm(target,
+ 0, NULL,
+ ARRAY_SIZE(reg_params), reg_params,
+ write_algorithm->address,
+ write_algorithm->address + sizeof(gd32vf103_flash_write_code) - 4,
+ 10000, NULL);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to execute algorithm at 0x%" TARGET_PRIxADDR ": %d",
+ write_algorithm->address, retval);
+ break;
+ }
+
+ /* Actually we just need to check for programming errors
+ * stm32x_wait_status_busy also reports error and clears status bits
+ */
+ retval = stm32x_wait_status_busy(bank, 5);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("flash write failed at address 0x%"PRIx32,
+ buf_get_u32(reg_params[3].value, 0, 32));
+ break;
}
- LOG_INFO("odd number of bytes to write, padding with 0xff");
- buffer = memcpy(new_buffer, buffer, count);
- new_buffer[count++] = 0xff;
+
+ /* Update counters */
+ buffer += thisrun_hwords * 2;
+ address += thisrun_hwords * 2;
+ hwords_count -= thisrun_hwords;
}
- uint32_t words_remaining = count / 2;
- int retval, retval2;
+ for (unsigned int i = 0; i < ARRAY_SIZE(reg_params); i++)
+ destroy_reg_param(&reg_params[i]);
- /* unlock flash registers */
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY1);
- if (retval != ERROR_OK)
- goto cleanup;
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY2);
- if (retval != ERROR_OK)
- goto cleanup;
+ target_free_working_area(target, source);
+ target_free_working_area(target, write_algorithm);
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PG);
- if (retval != ERROR_OK)
- goto cleanup;
+ return retval;
+}
- /* try using a block write */
- retval = stm32x_write_block(bank, buffer, bank->base + offset, words_remaining);
+/** Writes a block to flash either using target algorithm
+ * or use fallback, host controlled halfword-by-halfword access.
+ * Flash controller must be unlocked before this call.
+ */
+static int stm32x_write_block(struct flash_bank *bank,
+ const uint8_t *buffer, uint32_t address, uint32_t hwords_count)
+{
+ struct target *target = bank->target;
+
+ /* The flash write must be aligned to a halfword boundary.
+ * The flash infrastructure ensures it, do just a security check
+ */
+ assert(address % 2 == 0);
+
+ int retval;
+ struct arm *arm = target_to_arm(target);
+ if (is_arm(arm)) {
+ /* try using a block write - on ARM architecture or... */
+ retval = stm32x_write_block_async(bank, buffer, address, hwords_count);
+ } else {
+ /* ... RISC-V architecture */
+ retval = stm32x_write_block_riscv(bank, buffer, address, hwords_count);
+ }
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
/* if block write failed (no sufficient working area),
* we use normal (slow) single halfword accesses */
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
- while (words_remaining > 0) {
- retval = target_write_memory(target, bank->base + offset, 2, 1, buffer);
+ while (hwords_count > 0) {
+ retval = target_write_memory(target, address, 2, 1, buffer);
if (retval != ERROR_OK)
- goto reset_pg_and_lock;
+ return retval;
retval = stm32x_wait_status_busy(bank, 5);
if (retval != ERROR_OK)
- goto reset_pg_and_lock;
+ return retval;
- words_remaining--;
+ hwords_count--;
buffer += 2;
- offset += 2;
+ address += 2;
}
}
+ return retval;
+}
+
+static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer,
+ uint32_t offset, uint32_t count)
+{
+ struct target *target = bank->target;
+
+ if (bank->target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ /* The flash write must be aligned to a halfword boundary.
+ * The flash infrastructure ensures it, do just a security check
+ */
+ assert(offset % 2 == 0);
+ assert(count % 2 == 0);
+
+ int retval, retval2;
+
+ /* unlock flash registers */
+ retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY1);
+ if (retval != ERROR_OK)
+ return retval;
+ retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY2);
+ if (retval != ERROR_OK)
+ goto reset_pg_and_lock;
+
+ /* enable flash programming */
+ retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PG);
+ if (retval != ERROR_OK)
+ goto reset_pg_and_lock;
+
+ /* write to flash */
+ retval = stm32x_write_block(bank, buffer, bank->base + offset, count / 2);
reset_pg_and_lock:
retval2 = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
if (retval == ERROR_OK)
retval = retval2;
-cleanup:
- free(new_buffer);
return retval;
}
-static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id)
-{
- struct target *target = bank->target;
- uint32_t device_id_register = 0;
+struct stm32x_property_addr {
+ uint32_t device_id;
+ uint32_t flash_size;
+};
+static int stm32x_get_property_addr(struct target *target, struct stm32x_property_addr *addr)
+{
if (!target_was_examined(target)) {
LOG_ERROR("Target not examined yet");
return ERROR_TARGET_NOT_EXAMINED;
@@ -628,63 +756,61 @@ static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id)
switch (cortex_m_get_partno_safe(target)) {
case CORTEX_M0_PARTNO: /* STM32F0x devices */
- device_id_register = 0x40015800;
- break;
+ addr->device_id = 0x40015800;
+ addr->flash_size = 0x1FFFF7CC;
+ return ERROR_OK;
case CORTEX_M3_PARTNO: /* STM32F1x devices */
- device_id_register = 0xE0042000;
- break;
+ addr->device_id = 0xE0042000;
+ addr->flash_size = 0x1FFFF7E0;
+ return ERROR_OK;
case CORTEX_M4_PARTNO: /* STM32F3x devices */
- device_id_register = 0xE0042000;
- break;
+ addr->device_id = 0xE0042000;
+ addr->flash_size = 0x1FFFF7CC;
+ return ERROR_OK;
case CORTEX_M23_PARTNO: /* GD32E23x devices */
- device_id_register = 0x40015800;
- break;
+ addr->device_id = 0x40015800;
+ addr->flash_size = 0x1FFFF7E0;
+ return ERROR_OK;
+ case CORTEX_M_PARTNO_INVALID:
+ /* Check for GD32VF103 with RISC-V CPU */
+ if (strcmp(target_type_name(target), "riscv") == 0
+ && target_address_bits(target) == 32) {
+ /* There is nothing like arm common_magic in riscv_info_t
+ * check text name of target and if target is 32-bit
+ */
+ addr->device_id = 0xE0042000;
+ addr->flash_size = 0x1FFFF7E0;
+ return ERROR_OK;
+ }
+ /* fallthrough */
default:
LOG_ERROR("Cannot identify target as a stm32x");
return ERROR_FAIL;
}
+}
- /* read stm32 device id register */
- int retval = target_read_u32(target, device_id_register, device_id);
+static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id)
+{
+ struct target *target = bank->target;
+ struct stm32x_property_addr addr;
+
+ int retval = stm32x_get_property_addr(target, &addr);
if (retval != ERROR_OK)
return retval;
- return retval;
+ return target_read_u32(target, addr.device_id, device_id);
}
static int stm32x_get_flash_size(struct flash_bank *bank, uint16_t *flash_size_in_kb)
{
struct target *target = bank->target;
- uint32_t flash_size_reg;
+ struct stm32x_property_addr addr;
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_TARGET_NOT_EXAMINED;
- }
-
- switch (cortex_m_get_partno_safe(target)) {
- case CORTEX_M0_PARTNO: /* STM32F0x devices */
- flash_size_reg = 0x1FFFF7CC;
- break;
- case CORTEX_M3_PARTNO: /* STM32F1x devices */
- flash_size_reg = 0x1FFFF7E0;
- break;
- case CORTEX_M4_PARTNO: /* STM32F3x devices */
- flash_size_reg = 0x1FFFF7CC;
- break;
- case CORTEX_M23_PARTNO: /* GD32E23x devices */
- flash_size_reg = 0x1FFFF7E0;
- break;
- default:
- LOG_ERROR("Cannot identify target as a stm32x");
- return ERROR_FAIL;
- }
-
- int retval = target_read_u16(target, flash_size_reg, flash_size_in_kb);
+ int retval = stm32x_get_property_addr(target, &addr);
if (retval != ERROR_OK)
return retval;
- return retval;
+ return target_read_u16(target, addr.flash_size, flash_size_in_kb);
}
static int stm32x_probe(struct flash_bank *bank)
@@ -770,15 +896,20 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->user_data_offset = 16;
stm32x_info->option_offset = 6;
max_flash_size_in_kb = 64;
+ stm32x_info->can_load_options = true;
break;
case 0x1704: /* gd32f3x0 */
stm32x_info->user_data_offset = 16;
stm32x_info->option_offset = 6;
+ stm32x_info->can_load_options = true;
+ break;
+ case 0x1906: /* gd32vf103 */
break;
case 0x1909: /* gd32e23x */
stm32x_info->user_data_offset = 16;
stm32x_info->option_offset = 6;
max_flash_size_in_kb = 64;
+ stm32x_info->can_load_options = true;
break;
}
break;
@@ -990,6 +1121,10 @@ static int get_stm32x_info(struct flash_bank *bank, struct command_invocation *c
device_str = "GD32F3x0";
break;
+ case 0x1906:
+ device_str = "GD32VF103";
+ break;
+
case 0x1909: /* gd32e23x */
device_str = "GD32E23x";
break;
@@ -1473,8 +1608,10 @@ COMMAND_HANDLER(stm32x_handle_options_load_command)
if (retval != ERROR_OK)
return retval;
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY2);
- if (retval != ERROR_OK)
+ if (retval != ERROR_OK) {
+ (void)target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
return retval;
+ }
/* force re-load of option bytes - generates software reset */
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_OBL_LAUNCH);
@@ -1499,26 +1636,26 @@ static int stm32x_mass_erase(struct flash_bank *bank)
return retval;
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY2);
if (retval != ERROR_OK)
- return retval;
+ goto flash_lock;
/* mass erase flash memory */
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER);
if (retval != ERROR_OK)
- return retval;
+ goto flash_lock;
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR),
FLASH_MER | FLASH_STRT);
if (retval != ERROR_OK)
- return retval;
+ goto flash_lock;
retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
- if (retval != ERROR_OK)
- return retval;
- return ERROR_OK;
+flash_lock:
+ {
+ int retval2 = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
+ if (retval == ERROR_OK)
+ retval = retval2;
+ }
+ return retval;
}
COMMAND_HANDLER(stm32x_handle_mass_erase_command)
diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c
index fd6c28b..b7a4d99 100644
--- a/src/jtag/drivers/bcm2835gpio.c
+++ b/src/jtag/drivers/bcm2835gpio.c
@@ -565,6 +565,13 @@ static int bcm2835gpio_init(void)
}
if (transport_is_swd()) {
+ /* Make buffer an output before the GPIO connected to it */
+ if (swdio_dir_gpio != -1) {
+ swdio_dir_gpio_mode = MODE_GPIO(swdio_dir_gpio);
+ GPIO_SET = 1 << swdio_dir_gpio;
+ OUT_GPIO(swdio_dir_gpio);
+ }
+
swclk_gpio_mode = MODE_GPIO(swclk_gpio);
swdio_gpio_mode = MODE_GPIO(swdio_gpio);
@@ -580,12 +587,6 @@ static int bcm2835gpio_init(void)
OUT_GPIO(srst_gpio);
}
- if (swdio_dir_gpio != -1) {
- swdio_dir_gpio_mode = MODE_GPIO(swdio_dir_gpio);
- GPIO_SET = 1 << swdio_dir_gpio;
- OUT_GPIO(swdio_dir_gpio);
- }
-
LOG_DEBUG("saved pinmux settings: tck %d tms %d tdi %d "
"tdo %d trst %d srst %d", tck_gpio_mode, tms_gpio_mode,
tdi_gpio_mode, tdo_gpio_mode, trst_gpio_mode, srst_gpio_mode);
diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c
index 63407be..eaa65ab 100644
--- a/src/jtag/drivers/cmsis_dap.c
+++ b/src/jtag/drivers/cmsis_dap.c
@@ -1405,18 +1405,18 @@ static void debug_parse_cmsis_buf(const uint8_t *cmd, int cmdlen)
for (int i = 0; i < cmdlen; ++i)
printf(" %02x", cmd[i]);
printf("\n");
- switch (cmd[1]) {
+ switch (cmd[0]) {
case CMD_DAP_JTAG_SEQ: {
- printf("cmsis-dap jtag sequence command %02x (n=%d)\n", cmd[1], cmd[2]);
+ printf("cmsis-dap jtag sequence command %02x (n=%d)\n", cmd[0], cmd[1]);
/*
- * #2 = number of sequences
- * #3 = sequence info 1
- * #4...4+n_bytes-1 = sequence 1
+ * #1 = number of sequences
+ * #2 = sequence info 1
+ * #3...4+n_bytes-1 = sequence 1
* #4+n_bytes = sequence info 2
* #5+n_bytes = sequence 2 (single bit)
*/
- int pos = 3;
- for (int seq = 0; seq < cmd[2]; ++seq) {
+ int pos = 2;
+ for (int seq = 0; seq < cmd[1]; ++seq) {
uint8_t info = cmd[pos++];
int len = info & DAP_JTAG_SEQ_TCK;
if (len == 0)
diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c
index 9f9f27a..288035f 100644
--- a/src/jtag/drivers/linuxgpiod.c
+++ b/src/jtag/drivers/linuxgpiod.c
@@ -27,6 +27,7 @@ static int trst_gpio = -1;
static int srst_gpio = -1;
static int swclk_gpio = -1;
static int swdio_gpio = -1;
+static int swdio_dir_gpio = -1;
static int led_gpio = -1;
static int gpiochip = -1;
static int tck_gpiochip = -1;
@@ -37,6 +38,7 @@ static int trst_gpiochip = -1;
static int srst_gpiochip = -1;
static int swclk_gpiochip = -1;
static int swdio_gpiochip = -1;
+static int swdio_dir_gpiochip = -1;
static int led_gpiochip = -1;
static struct gpiod_chip *gpiod_chip_tck;
@@ -47,6 +49,7 @@ static struct gpiod_chip *gpiod_chip_trst;
static struct gpiod_chip *gpiod_chip_srst;
static struct gpiod_chip *gpiod_chip_swclk;
static struct gpiod_chip *gpiod_chip_swdio;
+static struct gpiod_chip *gpiod_chip_swdio_dir;
static struct gpiod_chip *gpiod_chip_led;
static struct gpiod_line *gpiod_tck;
@@ -56,6 +59,7 @@ static struct gpiod_line *gpiod_tdo;
static struct gpiod_line *gpiod_trst;
static struct gpiod_line *gpiod_swclk;
static struct gpiod_line *gpiod_swdio;
+static struct gpiod_line *gpiod_swdio_dir;
static struct gpiod_line *gpiod_srst;
static struct gpiod_line *gpiod_led;
@@ -63,6 +67,7 @@ static int last_swclk;
static int last_swdio;
static bool last_stored;
static bool swdio_input;
+static bool swdio_dir_is_active_high = true;
/* Bitbang interface read of TDO */
static bb_value_t linuxgpiod_read(void)
@@ -152,6 +157,11 @@ static void linuxgpiod_swdio_drive(bool is_output)
gpiod_line_release(gpiod_swdio);
if (is_output) {
+ if (gpiod_swdio_dir) {
+ retval = gpiod_line_set_value(gpiod_swdio_dir, swdio_dir_is_active_high ? 1 : 0);
+ if (retval < 0)
+ LOG_WARNING("Fail set swdio_dir");
+ }
retval = gpiod_line_request_output(gpiod_swdio, "OpenOCD", 1);
if (retval < 0)
LOG_WARNING("Fail request_output line swdio");
@@ -159,6 +169,11 @@ static void linuxgpiod_swdio_drive(bool is_output)
retval = gpiod_line_request_input(gpiod_swdio, "OpenOCD");
if (retval < 0)
LOG_WARNING("Fail request_input line swdio");
+ if (gpiod_swdio_dir) {
+ retval = gpiod_line_set_value(gpiod_swdio_dir, swdio_dir_is_active_high ? 0 : 1);
+ if (retval < 0)
+ LOG_WARNING("Fail set swdio_dir");
+ }
}
last_stored = false;
@@ -297,6 +312,8 @@ static int linuxgpiod_quit(void)
gpiod_chip_close(gpiod_chip_srst);
if (gpiod_chip_swdio != NULL)
gpiod_chip_close(gpiod_chip_swdio);
+ if (gpiod_chip_swdio_dir != NULL)
+ gpiod_chip_close(gpiod_chip_swdio_dir);
if (gpiod_chip_swclk != NULL)
gpiod_chip_close(gpiod_chip_swclk);
if (gpiod_chip_trst != NULL)
@@ -451,10 +468,26 @@ static int linuxgpiod_init(void)
goto out_error;
}
+ if (is_gpio_valid(swdio_dir_gpio)) {
+ gpiod_chip_swdio_dir = gpiod_chip_open_by_number(swdio_dir_gpiochip);
+ if (!gpiod_chip_swdio_dir) {
+ LOG_ERROR("Cannot open LinuxGPIOD swdio_dir_gpiochip %d", swdio_dir_gpiochip);
+ goto out_error;
+ }
+ }
+
gpiod_swclk = helper_get_output_line("swclk", gpiod_chip_swclk, swclk_gpio, 1);
if (!gpiod_swclk)
goto out_error;
+ /* Set buffer direction before making SWDIO an output */
+ if (is_gpio_valid(swdio_dir_gpio)) {
+ gpiod_swdio_dir = helper_get_output_line("swdio_dir", gpiod_chip_swdio_dir, swdio_dir_gpio,
+ swdio_dir_is_active_high ? 1 : 0);
+ if (!gpiod_swdio_dir)
+ goto out_error;
+ }
+
gpiod_swdio = helper_get_output_line("swdio", gpiod_chip_swdio, swdio_gpio, 1);
if (!gpiod_swdio)
goto out_error;
@@ -593,6 +626,12 @@ COMMAND_HANDLER(linuxgpiod_handle_swd_gpionum_swdio)
&swdio_gpio);
}
+COMMAND_HANDLER(linuxgpiod_handle_swd_gpionum_swdio_dir)
+{
+ return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "swdio_dir", &swdio_dir_gpiochip,
+ &swdio_dir_gpio);
+}
+
COMMAND_HANDLER(linuxgpiod_handle_gpionum_led)
{
return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "led", &led_gpiochip,
@@ -611,6 +650,7 @@ COMMAND_HANDLER(linuxgpiod_handle_gpiochip)
srst_gpiochip = gpiochip;
swclk_gpiochip = gpiochip;
swdio_gpiochip = gpiochip;
+ swdio_dir_gpiochip = gpiochip;
led_gpiochip = gpiochip;
}
@@ -690,6 +730,13 @@ static const struct command_registration linuxgpiod_subcommand_handlers[] = {
.usage = "[chip] swdio",
},
{
+ .name = "swdio_dir_num",
+ .handler = linuxgpiod_handle_swd_gpionum_swdio_dir,
+ .mode = COMMAND_CONFIG,
+ .help = "gpio chip number (optional) and gpio number for swdio_dir.",
+ .usage = "[chip] swdio_dir",
+ },
+ {
.name = "led_num",
.handler = linuxgpiod_handle_gpionum_led,
.mode = COMMAND_CONFIG,
diff --git a/src/rtos/zephyr.c b/src/rtos/zephyr.c
index 6305116..7f3325f 100644
--- a/src/rtos/zephyr.c
+++ b/src/rtos/zephyr.c
@@ -375,15 +375,15 @@ static const struct symbol_table_elem zephyr_symbol_list[] = {
.optional = false
},
{
- .symbol_name = "_kernel_openocd_offsets",
+ .symbol_name = "_kernel_thread_info_offsets",
.optional = false
},
{
- .symbol_name = "_kernel_openocd_size_t_size",
+ .symbol_name = "_kernel_thread_info_size_t_size",
.optional = false
},
{
- .symbol_name = "_kernel_openocd_num_offsets",
+ .symbol_name = "_kernel_thread_info_num_offsets",
.optional = true
},
{
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index 07dfaec..da65527 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -2768,11 +2768,52 @@ static int gdb_query_packet(struct connection *connection,
/* some commands need to know the GDB connection, make note of current
* GDB connection. */
current_gdb_connection = gdb_connection;
- command_run_line(cmd_ctx, cmd);
+ struct target *saved_target_override = cmd_ctx->current_target_override;
+ cmd_ctx->current_target_override = target;
+
+ int retval = Jim_EvalObj(cmd_ctx->interp, Jim_NewStringObj(cmd_ctx->interp, cmd, -1));
+
+ cmd_ctx->current_target_override = saved_target_override;
current_gdb_connection = NULL;
target_call_timer_callbacks_now();
gdb_connection->output_flag = GDB_OUTPUT_NO;
free(cmd);
+ if (retval == JIM_RETURN)
+ retval = cmd_ctx->interp->returnCode;
+ int lenmsg;
+ const char *cretmsg = Jim_GetString(Jim_GetResult(cmd_ctx->interp), &lenmsg);
+ char *retmsg;
+ if (lenmsg && cretmsg[lenmsg - 1] != '\n') {
+ retmsg = alloc_printf("%s\n", cretmsg);
+ lenmsg++;
+ } else {
+ retmsg = strdup(cretmsg);
+ }
+ if (!retmsg)
+ return ERROR_GDB_BUFFER_TOO_SMALL;
+
+ if (retval == JIM_OK) {
+ if (lenmsg) {
+ char *hex_buffer = malloc(lenmsg * 2 + 1);
+ if (!hex_buffer) {
+ free(retmsg);
+ return ERROR_GDB_BUFFER_TOO_SMALL;
+ }
+
+ size_t pkt_len = hexify(hex_buffer, (const uint8_t *)retmsg, lenmsg,
+ lenmsg * 2 + 1);
+ gdb_put_packet(connection, hex_buffer, pkt_len);
+ free(hex_buffer);
+ } else {
+ gdb_put_packet(connection, "OK", 2);
+ }
+ } else {
+ if (lenmsg)
+ gdb_output_con(connection, retmsg);
+ gdb_send_error(connection, retval);
+ }
+ free(retmsg);
+ return ERROR_OK;
}
gdb_put_packet(connection, "OK", 2);
return ERROR_OK;
diff --git a/src/target/a64_disassembler.c b/src/target/a64_disassembler.c
index bd78129..58ddf60 100644
--- a/src/target/a64_disassembler.c
+++ b/src/target/a64_disassembler.c
@@ -26,7 +26,7 @@
#if HAVE_CAPSTONE
-#include <capstone/capstone.h>
+#include <capstone.h>
static void print_opcode(struct command_invocation *cmd, const cs_insn *insn)
{
diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c
index c776e9c..96927bf 100644
--- a/src/target/arm_cti.c
+++ b/src/target/arm_cti.c
@@ -435,8 +435,13 @@ static int cti_configure(struct jim_getopt_info *goi, struct arm_cti *cti)
/* parse config or cget options ... */
while (goi->argc > 0) {
int e = adiv5_jim_mem_ap_spot_configure(&cti->spot, goi);
+
+ if (e == JIM_CONTINUE)
+ Jim_SetResultFormatted(goi->interp, "unknown option '%s'",
+ Jim_String(goi->argv[0]));
+
if (e != JIM_OK)
- return e;
+ return JIM_ERR;
}
if (!cti->spot.dap) {
diff --git a/src/target/arm_disassembler.c b/src/target/arm_disassembler.c
index 6618593..d3d27a9 100644
--- a/src/target/arm_disassembler.c
+++ b/src/target/arm_disassembler.c
@@ -27,7 +27,7 @@
#include <helper/log.h>
#if HAVE_CAPSTONE
-#include <capstone/capstone.h>
+#include <capstone.h>
#endif
/*
diff --git a/src/target/image.c b/src/target/image.c
index eafa73e..130ea6c 100644
--- a/src/target/image.c
+++ b/src/target/image.c
@@ -596,7 +596,7 @@ static int image_elf64_read_headers(struct image *image)
image->sections[j].base_address = field64(elf,
elf->segments64[i].p_paddr);
image->sections[j].private = &elf->segments64[i];
- image->sections[j].flags = field32(elf, elf->segments64[i].p_flags);
+ image->sections[j].flags = field64(elf, elf->segments64[i].p_flags);
j++;
}
}
@@ -1168,7 +1168,7 @@ int image_read_section(struct image *image,
return ERROR_OK;
}
-int image_add_section(struct image *image, target_addr_t base, uint32_t size, int flags, uint8_t const *data)
+int image_add_section(struct image *image, target_addr_t base, uint32_t size, uint64_t flags, uint8_t const *data)
{
struct imagesection *section;
diff --git a/src/target/image.h b/src/target/image.h
index 5b5d11f..bf06064 100644
--- a/src/target/image.h
+++ b/src/target/image.h
@@ -52,7 +52,7 @@ enum image_type {
struct imagesection {
target_addr_t base_address;
uint32_t size;
- int flags;
+ uint64_t flags;
void *private; /* private data */
};
@@ -108,7 +108,7 @@ int image_read_section(struct image *image, int section, target_addr_t offset,
void image_close(struct image *image);
int image_add_section(struct image *image, target_addr_t base, uint32_t size,
- int flags, uint8_t const *data);
+ uint64_t flags, uint8_t const *data);
int image_calculate_checksum(const uint8_t *buffer, uint32_t nbytes,
uint32_t *checksum);