diff options
author | Antonio Borneo <borneo.antonio@gmail.com> | 2020-01-26 17:00:55 +0100 |
---|---|---|
committer | Antonio Borneo <borneo.antonio@gmail.com> | 2020-05-24 21:29:42 +0100 |
commit | ac18e960ce79f06b22e71a17415be0feb741a482 (patch) | |
tree | 1f235cf901ec48a3d09cce24a5674ccea8b01df2 /src | |
parent | 93c4c0fcbec1ebcb2ce19b37c39b63f10a91b9e8 (diff) | |
download | riscv-openocd-ac18e960ce79f06b22e71a17415be0feb741a482.zip riscv-openocd-ac18e960ce79f06b22e71a17415be0feb741a482.tar.gz riscv-openocd-ac18e960ce79f06b22e71a17415be0feb741a482.tar.bz2 |
swim: abstract the transport in stm8 target
SWIM is implemented by (ab)using the HLA API. This was acceptable
when OpenOCD code did not provided a clear separation between
transports and related APIs. Still today SWIM in OpenOCD is only
supported by STLink, so the decision to re-use the HLA API was the
simpler way to implement it.
After commit efd1d642220a ("adapter: switch from struct
jtag_interface to adapter_driver") the transports API are better
split and SWIM can be implemented as a separate set of API. This
would open the possibility to extend OpenOCD for other adapters
that provide SWIM, e.g. versaloon, or through SPI emulation [1].
Introduce a new set of files swim.[ch] to handle the SWIM API.
Beside the API that almost match the transport low-level data
communication (system_reset, read_mem, write_mem), add a further
API reconnect. Today, inside HLA STLink code, the reconnect is
implemented by hacking the HLA API state(). Please notice that
due to this hack the return type is incorrect; stlink_usb_state()
returns ERROR_OK in SWIM mode, while its return type is enum
target_state. Ignore the type mismatch and still call the HLA API
state in the new SWIM API reconnect. Further commit will fix it.
[1] http://kuku.eu.org/?projects/stm8spi/stm8spi
Change-Id: I52018e1e2200cbd41af8e5031f7b35dc761b61d6
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: http://openocd.zylin.com/5528
Tested-by: jenkins
Diffstat (limited to 'src')
-rw-r--r-- | src/jtag/Makefile.am | 2 | ||||
-rw-r--r-- | src/jtag/swim.c | 51 | ||||
-rw-r--r-- | src/jtag/swim.h | 65 | ||||
-rw-r--r-- | src/target/stm8.c | 69 |
4 files changed, 134 insertions, 53 deletions
diff --git a/src/jtag/Makefile.am b/src/jtag/Makefile.am index a764863..b82914b 100644 --- a/src/jtag/Makefile.am +++ b/src/jtag/Makefile.am @@ -56,6 +56,7 @@ endif %D%/interface.c \ %D%/interfaces.c \ %D%/tcl.c \ + %D%/swim.c \ %D%/commands.h \ %D%/driver.h \ %D%/interface.h \ @@ -65,6 +66,7 @@ endif %D%/minidriver/minidriver_imp.h \ %D%/minidummy/jtag_minidriver.h \ %D%/swd.h \ + %D%/swim.h \ %D%/tcl.h \ $(JTAG_SRCS) diff --git a/src/jtag/swim.c b/src/jtag/swim.c new file mode 100644 index 0000000..965018c --- /dev/null +++ b/src/jtag/swim.c @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* + * Copyright (C) 2020 by Antonio Borneo <borneo.antonio@gmail.com + * + * SWIM (Single Wire Interface Module) is a low-pin-count debug protocol + * used by STMicroelectronics MCU family STM8 and documented in UM470 + * https://www.st.com/resource/en/user_manual/cd00173911.pdf + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "interface.h" +#include "swim.h" +#include "jtag/hla/hla_transport.h" +#include "jtag/hla/hla_interface.h" +#include "jtag/hla/hla_layout.h" + +extern struct adapter_driver *adapter_driver; + +int swim_system_reset(void) +{ + assert(adapter_driver->hla_if); + + return adapter_driver->hla_if->layout->api->reset(adapter_driver->hla_if->handle); +} + +int swim_read_mem(uint32_t addr, uint32_t size, uint32_t count, + uint8_t *buffer) +{ + assert(adapter_driver->hla_if); + + return adapter_driver->hla_if->layout->api->read_mem(adapter_driver->hla_if->handle, addr, size, count, buffer); +} + +int swim_write_mem(uint32_t addr, uint32_t size, uint32_t count, + const uint8_t *buffer) +{ + assert(adapter_driver->hla_if); + + return adapter_driver->hla_if->layout->api->write_mem(adapter_driver->hla_if->handle, addr, size, count, buffer); +} + +int swim_reconnect(void) +{ + assert(adapter_driver->hla_if); + + return adapter_driver->hla_if->layout->api->state(adapter_driver->hla_if->handle); +} diff --git a/src/jtag/swim.h b/src/jtag/swim.h new file mode 100644 index 0000000..d0ae18e --- /dev/null +++ b/src/jtag/swim.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* + * Copyright (C) 2020 by Antonio Borneo <borneo.antonio@gmail.com + */ + +/** + * @file + * This file implements support for STMicroelectronics debug protocol SWIM + * (Single Wire Interface Module). + */ + +#ifndef OPENOCD_JTAG_SWIM_H +#define OPENOCD_JTAG_SWIM_H + +struct swim_driver { + /** + * Send SRST (system reset) command to target. + * + * @return ERROR_OK on success, else a fault code. + */ + int (*srst)(void); + + /** + * Read target memory through ROTF (read on-the-fly) command. + * + * @param addr Start address to read data from target memory. + * @param size Size in bytes of data units, 1, 2 or 4. + * @param count Number of units (size units, not bytes) to read. + * @param buffer Data buffer to receive data. + * @return ERROR_OK on success, else a fault code. + */ + int (*read_mem)(uint32_t addr, uint32_t size, uint32_t count, + uint8_t *buffer); + + /** + * Write target memory through WOTF (write on-the-fly) command. + * + * @param addr Start address to write data to target memory. + * @param size Size in bytes of data units, 1, 2 or 4. + * @param count Number of units (size units, not bytes) to write. + * @param buffer Data buffer to write. + * @return ERROR_OK on success, else a fault code. + */ + int (*write_mem)(uint32_t addr, uint32_t size, uint32_t count, + const uint8_t *buffer); + + /** + * Reconnect to the target. + * Should be reworked to be more generic and not linked to current + * implementation in stlink driver. + * + * @return ERROR_OK on success, else a fault code. + */ + int (*reconnect)(void); +}; + +int swim_system_reset(void); +int swim_read_mem(uint32_t addr, uint32_t size, uint32_t count, + uint8_t *buffer); +int swim_write_mem(uint32_t addr, uint32_t size, uint32_t count, + const uint8_t *buffer); +int swim_reconnect(void); + +#endif /* OPENOCD_JTAG_SWIM_H */ diff --git a/src/target/stm8.c b/src/target/stm8.c index 6b03bb5..ad05b54 100644 --- a/src/target/stm8.c +++ b/src/target/stm8.c @@ -27,9 +27,7 @@ #include "hello.h" #include "jtag/interface.h" #include "jtag/jtag.h" -#include "jtag/hla/hla_transport.h" -#include "jtag/hla/hla_interface.h" -#include "jtag/hla/hla_layout.h" +#include "jtag/swim.h" #include "register.h" #include "breakpoints.h" #include "algorithm.h" @@ -180,68 +178,31 @@ struct stm8_comparator { enum hw_break_type type; }; -static inline struct hl_interface_s *target_to_adapter(struct target *target) -{ - return target->tap->priv; -} - static int stm8_adapter_read_memory(struct target *target, uint32_t addr, int size, int count, void *buf) { - int ret; - struct hl_interface_s *adapter = target_to_adapter(target); - - ret = adapter->layout->api->read_mem(adapter->handle, - addr, size, count, buf); - if (ret != ERROR_OK) - return ret; - return ERROR_OK; + return swim_read_mem(addr, size, count, buf); } static int stm8_adapter_write_memory(struct target *target, uint32_t addr, int size, int count, const void *buf) { - int ret; - struct hl_interface_s *adapter = target_to_adapter(target); - - ret = adapter->layout->api->write_mem(adapter->handle, - addr, size, count, buf); - if (ret != ERROR_OK) - return ret; - return ERROR_OK; + return swim_write_mem(addr, size, count, buf); } static int stm8_write_u8(struct target *target, uint32_t addr, uint8_t val) { - int ret; uint8_t buf[1]; - struct hl_interface_s *adapter = target_to_adapter(target); buf[0] = val; - ret = adapter->layout->api->write_mem(adapter->handle, addr, 1, 1, buf); - if (ret != ERROR_OK) - return ret; - return ERROR_OK; + return swim_write_mem(addr, 1, 1, buf); } static int stm8_read_u8(struct target *target, uint32_t addr, uint8_t *val) { - int ret; - struct hl_interface_s *adapter = target_to_adapter(target); - - ret = adapter->layout->api->read_mem(adapter->handle, addr, 1, 1, val); - if (ret != ERROR_OK) - return ret; - return ERROR_OK; -} - -static int stm8_set_speed(struct target *target, int speed) -{ - struct hl_interface_s *adapter = target_to_adapter(target); - adapter->layout->api->speed(adapter->handle, speed, 0); - return ERROR_OK; + return swim_read_mem(addr, 1, 1, val); } /* @@ -924,7 +885,6 @@ static int stm8_halt(struct target *target) static int stm8_reset_assert(struct target *target) { int res = ERROR_OK; - struct hl_interface_s *adapter = target_to_adapter(target); struct stm8_common *stm8 = target_to_stm8(target); bool use_srst_fallback = true; @@ -942,7 +902,7 @@ static int stm8_reset_assert(struct target *target) if (use_srst_fallback) { LOG_DEBUG("Hardware srst not supported, falling back to swim reset"); - res = adapter->layout->api->reset(adapter->handle); + res = swim_system_reset(); if (res != ERROR_OK) return res; } @@ -1696,7 +1656,7 @@ static int stm8_examine(struct target *target) uint8_t csr1, csr2; /* get pointers to arch-specific information */ struct stm8_common *stm8 = target_to_stm8(target); - struct hl_interface_s *adapter = target_to_adapter(target); + enum reset_types jtag_reset_config = jtag_get_reset_config(); if (!target_was_examined(target)) { if (!stm8->swim_configured) { @@ -1710,20 +1670,23 @@ static int stm8_examine(struct target *target) retval = stm8_write_u8(target, SWIM_CSR, SAFE_MASK + SWIM_DM + HS); if (retval != ERROR_OK) return retval; - retval = stm8_set_speed(target, 1); - if (retval == ERROR_OK) - stm8->swim_configured = true; + jtag_config_khz(1); + stm8->swim_configured = true; /* Now is the time to deassert reset if connect_under_reset. Releasing reset line will cause the option bytes to load. The core will still be stalled. */ - if (adapter->param.connect_under_reset) - stm8_reset_deassert(target); + if (jtag_reset_config & RESET_CNCT_UNDER_SRST) { + if (jtag_reset_config & RESET_SRST_NO_GATING) + stm8_reset_deassert(target); + else + LOG_WARNING("\'srst_nogate\' reset_config option is required"); + } } else { LOG_INFO("trying to reconnect"); - retval = adapter->layout->api->state(adapter->handle); + retval = swim_reconnect(); if (retval != ERROR_OK) { LOG_ERROR("reconnect failed"); return ERROR_FAIL; |