#include <assert.h>
#include "bmp_remote.h"
#include "protocol_v0_defs.h"
#include "protocol_v0_adiv5.h"
#include "hex_utils.h"
static bool remote_adiv5_check_error(const char *const func, const char *const buffer, const ssize_t length)
{
if (length < 1) {
DEBUG_ERROR("%s comms error: %zd\n", func, length);
return false;
}
if (buffer[0] == REMOTE_RESP_ERR) {
const uint64_t response_code = remote_decode_response(buffer + 1, (size_t)length - 1U);
const uint8_t error = response_code & 0xffU;
DEBUG_ERROR("%s: Unexpected error %u\n", func, error);
}
else if (buffer[0] == REMOTE_RESP_PARERR)
DEBUG_ERROR("%s: !BUG! Firmware reported a parameter error\n", func);
else if (buffer[0] != REMOTE_RESP_OK)
DEBUG_ERROR("%s: Firmware reported unexpected error: %c\n", func, buffer[0]);
return buffer[0] == REMOTE_RESP_OK;
}
uint32_t remote_v0_adiv5_raw_access(
adiv5_debug_port_s *const dp, const uint8_t rnw, const uint16_t addr, const uint32_t request_value)
{
(void)dp;
char buffer[REMOTE_MAX_MSG_SIZE];
ssize_t length = snprintf(buffer, REMOTE_MAX_MSG_SIZE, REMOTE_ADIv5_RAW_ACCESS_STR, rnw, addr, request_value);
platform_buffer_write(buffer, length);
length = platform_buffer_read(buffer, REMOTE_MAX_MSG_SIZE);
if (!remote_adiv5_check_error(__func__, buffer, length))
return 0U;
uint32_t result_value = 0U;
unhexify(&result_value, buffer + 1, 4);
DEBUG_PROBE("%s: addr %04x %s %08" PRIx32, __func__, addr, rnw ? "->" : "<-", rnw ? result_value : request_value);
if (!rnw)
DEBUG_PROBE(" -> %08" PRIx32, result_value);
DEBUG_PROBE("\n");
return result_value;
}
uint32_t remote_v0_adiv5_dp_read(adiv5_debug_port_s *const dp, const uint16_t addr)
{
(void)dp;
char buffer[REMOTE_MAX_MSG_SIZE];
ssize_t length = snprintf(buffer, REMOTE_MAX_MSG_SIZE, REMOTE_DP_READ_STR, addr);
platform_buffer_write(buffer, length);
length = platform_buffer_read(buffer, REMOTE_MAX_MSG_SIZE);
if (!remote_adiv5_check_error(__func__, buffer, length))
return 0U;
uint32_t value = 0U;
unhexify(&value, buffer + 1, 4);
DEBUG_PROBE("%s: addr %04x -> %08" PRIx32 "\n", __func__, addr, value);
return value;
}
uint32_t remote_v0_adiv5_ap_read(adiv5_access_port_s *const ap, const uint16_t addr)
{
char buffer[REMOTE_MAX_MSG_SIZE];
ssize_t length = snprintf(buffer, REMOTE_MAX_MSG_SIZE, REMOTE_AP_READ_STR, ap->apsel, addr);
platform_buffer_write(buffer, length);
length = platform_buffer_read(buffer, REMOTE_MAX_MSG_SIZE);
if (!remote_adiv5_check_error(__func__, buffer, length))
return 0U;
uint32_t value = 0U;
unhexify(&value, buffer + 1, 4);
DEBUG_PROBE("%s: addr %04x -> %08" PRIx32 "\n", __func__, addr, value);
return value;
}
void remote_v0_adiv5_ap_write(adiv5_access_port_s *const ap, const uint16_t addr, const uint32_t value)
{
char buffer[REMOTE_MAX_MSG_SIZE];
ssize_t length = snprintf(buffer, REMOTE_MAX_MSG_SIZE, REMOTE_AP_WRITE_STR, ap->apsel, addr, value);
platform_buffer_write(buffer, length);
length = platform_buffer_read(buffer, REMOTE_MAX_MSG_SIZE);
if (!remote_adiv5_check_error(__func__, buffer, length))
return;
DEBUG_PROBE("%s: addr %04x <- %08" PRIx32 "\n", __func__, addr, value);
}
void remote_v0_adiv5_mem_read_bytes(
adiv5_access_port_s *const ap, void *const dest, const uint32_t src, const size_t read_length)
{
if (!read_length)
return;
char *const data = (char *)dest;
DEBUG_PROBE("%s: @%08" PRIx32 "+%zx\n", __func__, src, read_length);
char buffer[REMOTE_MAX_MSG_SIZE];
const size_t blocksize = (REMOTE_MAX_MSG_SIZE - 2U) / 2U;
for (size_t offset = 0; offset < read_length; offset += blocksize) {
const size_t amount = MIN(read_length - offset, blocksize);
ssize_t length =
snprintf(buffer, REMOTE_MAX_MSG_SIZE, REMOTE_ADIv5_MEM_READ_STR, ap->apsel, ap->csw, src + offset, amount);
platform_buffer_write(buffer, length);
length = platform_buffer_read(buffer, REMOTE_MAX_MSG_SIZE);
if (!remote_adiv5_check_error(__func__, buffer, length)) {
DEBUG_ERROR("%s error around 0x%08zx\n", __func__, (size_t)src + offset);
return;
}
unhexify(data + offset, buffer + 1, amount);
}
}
void remote_v0_adiv5_mem_write_bytes(adiv5_access_port_s *const ap, const uint32_t dest, const void *const src,
const size_t write_length, const align_e align)
{
if (!write_length)
return;
const char *data = (const char *)src;
DEBUG_PROBE("%s: @%08" PRIx32 "+%zx alignment %u\n", __func__, dest, write_length, align);
char buffer[REMOTE_MAX_MSG_SIZE + 1U];
const size_t alignment_mask = ~((1U << align) - 1U);
const size_t blocksize = ((REMOTE_MAX_MSG_SIZE - REMOTE_ADIv5_MEM_WRITE_LENGTH) / 2U) & alignment_mask;
for (size_t offset = 0; offset < write_length; offset += blocksize) {
const size_t amount = MIN(write_length - offset, blocksize);
ssize_t length = snprintf(
buffer, REMOTE_MAX_MSG_SIZE, REMOTE_ADIv5_MEM_WRITE_STR, ap->apsel, ap->csw, align, dest + offset, amount);
assert(length == REMOTE_ADIv5_MEM_WRITE_LENGTH - 1U);
hexify(buffer + length, data + offset, amount);
length += (ssize_t)(amount * 2U);
buffer[length++] = REMOTE_EOM;
buffer[length++] = '\0';
platform_buffer_write(buffer, length);
length = platform_buffer_read(buffer, REMOTE_MAX_MSG_SIZE);
if (!remote_adiv5_check_error(__func__, buffer, length)) {
DEBUG_ERROR("%s error around 0x%08zx\n", __func__, (size_t)dest + offset);
return;
}
}
}