#include "general.h"
#include "gdb_if.h"
#include "version.h"
#include "remote.h"
#include "target.h"
#include "bmp_remote.h"
#include "cli.h"
#include "hex_utils.h"
#include "exception.h"
#include "remote/protocol_v0.h"
#include "remote/protocol_v1.h"
#include "remote/protocol_v2.h"
#include "remote/protocol_v3.h"
#include <assert.h>
#include <sys/time.h>
#include <errno.h>
#include "adiv5.h"
bmp_remote_protocol_s remote_funcs;
uint64_t remote_decode_response(const char *const response, const size_t digits)
{
uint64_t value = 0U;
for (size_t idx = 0U; idx < digits; ++idx) {
value <<= 4U;
value |= unhex_digit(response[idx]);
}
return value;
}
bool remote_init(const bool power_up)
{
platform_buffer_write(REMOTE_START_STR, sizeof(REMOTE_START_STR));
char buffer[REMOTE_MAX_MSG_SIZE];
ssize_t length = platform_buffer_read(buffer, REMOTE_MAX_MSG_SIZE);
if (length < 1 || buffer[0] == REMOTE_RESP_ERR) {
DEBUG_ERROR("Remote Start failed, error %s\n", length ? buffer + 1 : "unknown");
return false;
}
DEBUG_PROBE("Remote is %s\n", buffer + 1);
platform_buffer_write(REMOTE_HL_CHECK_STR, sizeof(REMOTE_HL_CHECK_STR));
length = platform_buffer_read(buffer, REMOTE_MAX_MSG_SIZE);
if (length < 1) {
DEBUG_ERROR("%s comms error: %zd\n", __func__, length);
return false;
}
if (buffer[0] != REMOTE_RESP_OK)
remote_v0_init();
else {
const uint64_t version = remote_decode_response(buffer + 1, length - 1);
switch (version) {
case 0:
remote_v0_plus_init();
break;
case 1:
remote_v1_init();
break;
case 2:
remote_v2_init();
break;
case 3:
remote_v3_init();
break;
default:
DEBUG_ERROR("Unknown remote protocol version %" PRIu64 ", aborting\n", version);
return false;
}
}
remote_target_set_power(power_up);
return true;
}
bool remote_target_get_power(void)
{
char buffer[REMOTE_MAX_MSG_SIZE];
int length = snprintf(buffer, REMOTE_MAX_MSG_SIZE, "%s", REMOTE_PWR_GET_STR);
platform_buffer_write(buffer, length);
length = platform_buffer_read(buffer, REMOTE_MAX_MSG_SIZE);
if (length < 1 || buffer[0] == REMOTE_RESP_ERR) {
DEBUG_ERROR("platform_target_get_power failed, error %s\n", length ? buffer + 1 : "unknown");
exit(-1);
}
return buffer[1] == '1';
}
bool remote_target_set_power(const bool power)
{
char buffer[REMOTE_MAX_MSG_SIZE];
int length = snprintf(buffer, REMOTE_MAX_MSG_SIZE, REMOTE_PWR_SET_STR, power ? '1' : '0');
platform_buffer_write(buffer, length);
length = platform_buffer_read(buffer, REMOTE_MAX_MSG_SIZE);
if (length < 1 || buffer[0] == REMOTE_RESP_ERR)
DEBUG_ERROR("platform_target_set_power failed, error %s\n", length ? buffer + 1 : "unknown");
return length > 0 && buffer[0] == REMOTE_RESP_OK;
}
void remote_nrst_set_val(bool assert)
{
char buffer[REMOTE_MAX_MSG_SIZE];
int length = snprintf(buffer, REMOTE_MAX_MSG_SIZE, REMOTE_NRST_SET_STR, assert ? '1' : '0');
platform_buffer_write(buffer, length);
length = platform_buffer_read(buffer, REMOTE_MAX_MSG_SIZE);
if (length < 1 || buffer[0] == REMOTE_RESP_ERR) {
DEBUG_ERROR("platform_nrst_set_val failed, error %s\n", length ? buffer + 1 : "unknown");
exit(-1);
}
}
bool remote_nrst_get_val(void)
{
char buffer[REMOTE_MAX_MSG_SIZE];
int length = snprintf(buffer, REMOTE_MAX_MSG_SIZE, "%s", REMOTE_NRST_GET_STR);
platform_buffer_write(buffer, length);
length = platform_buffer_read(buffer, REMOTE_MAX_MSG_SIZE);
if (length < 1 || buffer[0] == REMOTE_RESP_ERR) {
DEBUG_ERROR("platform_nrst_set_val failed, error %s\n", length ? buffer + 1 : "unknown");
exit(-1);
}
return buffer[1] == '1';
}
void remote_max_frequency_set(uint32_t freq)
{
if (remote_funcs.set_comms_frequency)
remote_funcs.set_comms_frequency(freq);
else
DEBUG_WARN("Please update probe firmware to enable SWD/JTAG frequency selection\n");
}
uint32_t remote_max_frequency_get(void)
{
if (remote_funcs.get_comms_frequency)
return remote_funcs.get_comms_frequency();
return FREQ_FIXED;
}
const char *remote_target_voltage(void)
{
static char buffer[REMOTE_MAX_MSG_SIZE];
int length = snprintf(buffer, REMOTE_MAX_MSG_SIZE, " %s", REMOTE_VOLTAGE_STR);
platform_buffer_write(buffer, length);
length = platform_buffer_read(buffer, REMOTE_MAX_MSG_SIZE);
if (length < 1 || buffer[0] == REMOTE_RESP_ERR) {
DEBUG_ERROR("platform_target_voltage failed, error %s\n", length ? buffer + 1 : "unknown");
exit(-1);
}
return buffer + 1;
}
void remote_target_clk_output_enable(const bool enable)
{
if (remote_funcs.target_clk_output_enable)
remote_funcs.target_clk_output_enable(enable);
else
DEBUG_WARN("Please update probe firmware to enable high impedance clock feature\n");
}
bool remote_jtag_init(void)
{
return remote_funcs.jtag_init();
}
bool remote_swd_init(void)
{
return remote_funcs.swd_init();
}
void remote_adiv5_dp_init(adiv5_debug_port_s *const dp)
{
remote_funcs.adiv5_init(dp);
}
void remote_add_jtag_dev(uint32_t dev_index, const jtag_dev_s *jtag_dev)
{
if (remote_funcs.add_jtag_dev)
remote_funcs.add_jtag_dev(dev_index, jtag_dev);
}