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 efd1d64222 ("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
This commit is contained in:
+16
-53
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user