Merge pull request #225 from riscv/old_bus2
Support v0 System Bus Access
This commit is contained in:
commit
b7c5c5d228
|
@ -1791,10 +1791,80 @@ static int read_sbcs_nonbusy(struct target *target, uint32_t *sbcs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int read_memory_bus_v0(struct target *target, target_addr_t address,
|
||||||
|
uint32_t size, uint32_t count, uint8_t *buffer)
|
||||||
|
{
|
||||||
|
LOG_DEBUG("System Bus Access: size: %d\tcount:%d\tstart address: 0x%08"
|
||||||
|
TARGET_PRIxADDR, size, count, address);
|
||||||
|
uint8_t *t_buffer = buffer;
|
||||||
|
riscv_addr_t cur_addr = address;
|
||||||
|
riscv_addr_t fin_addr = address + (count * size);
|
||||||
|
uint64_t access = 0;
|
||||||
|
|
||||||
|
const int DMI_SBCS_SBSINGLEREAD_OFFSET = 20;
|
||||||
|
const uint32_t DMI_SBCS_SBSINGLEREAD = (0x1U << DMI_SBCS_SBSINGLEREAD_OFFSET);
|
||||||
|
|
||||||
|
const int DMI_SBCS_SBAUTOREAD_OFFSET = 15;
|
||||||
|
const uint32_t DMI_SBCS_SBAUTOREAD = (0x1U << DMI_SBCS_SBAUTOREAD_OFFSET);
|
||||||
|
|
||||||
|
/* ww favorise one off reading if there is an issu */
|
||||||
|
if (count == 1) {
|
||||||
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
|
access = dmi_read(target, DMI_SBCS);
|
||||||
|
dmi_write(target, DMI_SBADDRESS0, cur_addr);
|
||||||
|
/* size/2 matching the bit access of the spec 0.13 */
|
||||||
|
access = set_field(access, DMI_SBCS_SBACCESS, size/2);
|
||||||
|
access = set_field(access, DMI_SBCS_SBSINGLEREAD, 1);
|
||||||
|
LOG_DEBUG("\r\nread_memory: sab: access: 0x%08" PRIx64, access);
|
||||||
|
dmi_write(target, DMI_SBCS, access);
|
||||||
|
/* 3) read */
|
||||||
|
uint32_t value = dmi_read(target, DMI_SBDATA0);
|
||||||
|
LOG_DEBUG("\r\nread_memory: sab: value: 0x%08x", value);
|
||||||
|
write_to_buf(t_buffer, value, size);
|
||||||
|
t_buffer += size;
|
||||||
|
cur_addr += size;
|
||||||
|
}
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* has to be the same size if we want to read a block */
|
||||||
|
LOG_DEBUG("reading block until final address 0x%" PRIx64, fin_addr);
|
||||||
|
access = dmi_read(target, DMI_SBCS);
|
||||||
|
/* set current address */
|
||||||
|
dmi_write(target, DMI_SBADDRESS0, cur_addr);
|
||||||
|
/* 2) write sbaccess=2, sbsingleread,sbautoread,sbautoincrement
|
||||||
|
* size/2 matching the bit access of the spec 0.13 */
|
||||||
|
access = set_field(access, DMI_SBCS_SBACCESS, size/2);
|
||||||
|
access = set_field(access, DMI_SBCS_SBAUTOREAD, 1);
|
||||||
|
access = set_field(access, DMI_SBCS_SBSINGLEREAD, 1);
|
||||||
|
access = set_field(access, DMI_SBCS_SBAUTOINCREMENT, 1);
|
||||||
|
LOG_DEBUG("\r\naccess: 0x%08" PRIx64, access);
|
||||||
|
dmi_write(target, DMI_SBCS, access);
|
||||||
|
|
||||||
|
while (cur_addr < fin_addr) {
|
||||||
|
LOG_DEBUG("\r\nsab:autoincrement: \r\n size: %d\tcount:%d\taddress: 0x%08"
|
||||||
|
PRIx64, size, count, cur_addr);
|
||||||
|
/* read */
|
||||||
|
uint32_t value = dmi_read(target, DMI_SBDATA0);
|
||||||
|
write_to_buf(t_buffer, value, size);
|
||||||
|
cur_addr += size;
|
||||||
|
t_buffer += size;
|
||||||
|
|
||||||
|
/* if we are reaching last address, we must clear autoread */
|
||||||
|
if (cur_addr == fin_addr && count != 1) {
|
||||||
|
dmi_write(target, DMI_SBCS, 0);
|
||||||
|
value = dmi_read(target, DMI_SBDATA0);
|
||||||
|
write_to_buf(t_buffer, value, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the requested memory using the system bus interface.
|
* Read the requested memory using the system bus interface.
|
||||||
*/
|
*/
|
||||||
static int read_memory_bus(struct target *target, target_addr_t address,
|
static int read_memory_bus_v1(struct target *target, target_addr_t address,
|
||||||
uint32_t size, uint32_t count, uint8_t *buffer)
|
uint32_t size, uint32_t count, uint8_t *buffer)
|
||||||
{
|
{
|
||||||
RISCV013_INFO(info);
|
RISCV013_INFO(info);
|
||||||
|
@ -2106,22 +2176,113 @@ static int read_memory(struct target *target, target_addr_t address,
|
||||||
uint32_t size, uint32_t count, uint8_t *buffer)
|
uint32_t size, uint32_t count, uint8_t *buffer)
|
||||||
{
|
{
|
||||||
RISCV013_INFO(info);
|
RISCV013_INFO(info);
|
||||||
if (info->progbufsize >= 2) {
|
if (info->progbufsize >= 2)
|
||||||
return read_memory_progbuf(target, address, size, count, buffer);
|
return read_memory_progbuf(target, address, size, count, buffer);
|
||||||
} else if ((get_field(info->sbcs, DMI_SBCS_SBVERSION) == 1) && (
|
|
||||||
(get_field(info->sbcs, DMI_SBCS_SBACCESS8) && size == 1) ||
|
if ((get_field(info->sbcs, DMI_SBCS_SBACCESS8) && size == 1) ||
|
||||||
(get_field(info->sbcs, DMI_SBCS_SBACCESS16) && size == 2) ||
|
(get_field(info->sbcs, DMI_SBCS_SBACCESS16) && size == 2) ||
|
||||||
(get_field(info->sbcs, DMI_SBCS_SBACCESS32) && size == 4) ||
|
(get_field(info->sbcs, DMI_SBCS_SBACCESS32) && size == 4) ||
|
||||||
(get_field(info->sbcs, DMI_SBCS_SBACCESS64) && size == 8) ||
|
(get_field(info->sbcs, DMI_SBCS_SBACCESS64) && size == 8) ||
|
||||||
(get_field(info->sbcs, DMI_SBCS_SBACCESS128) && size == 16))) {
|
(get_field(info->sbcs, DMI_SBCS_SBACCESS128) && size == 16)) {
|
||||||
return read_memory_bus(target, address, size, count, buffer);
|
if (get_field(info->sbcs, DMI_SBCS_SBVERSION) == 0)
|
||||||
} else {
|
return read_memory_bus_v0(target, address, size, count, buffer);
|
||||||
LOG_ERROR("Don't know how to read memory on this target.");
|
else if (get_field(info->sbcs, DMI_SBCS_SBVERSION) == 1)
|
||||||
return ERROR_FAIL;
|
return read_memory_bus_v1(target, address, size, count, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_ERROR("Don't know how to read memory on this target.");
|
||||||
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_memory_bus(struct target *target, target_addr_t address,
|
static int write_memory_bus_v0(struct target *target, target_addr_t address,
|
||||||
|
uint32_t size, uint32_t count, const uint8_t *buffer)
|
||||||
|
{
|
||||||
|
/*1) write sbaddress: for singlewrite and autoincrement, we need to write the address once*/
|
||||||
|
LOG_DEBUG("System Bus Access: size: %d\tcount:%d\tstart address: 0x%08"
|
||||||
|
TARGET_PRIxADDR, size, count, address);
|
||||||
|
dmi_write(target, DMI_SBADDRESS0, address);
|
||||||
|
int64_t value = 0;
|
||||||
|
int64_t access = 0;
|
||||||
|
riscv_addr_t offset = 0;
|
||||||
|
riscv_addr_t t_addr = 0;
|
||||||
|
const uint8_t *t_buffer = buffer + offset;
|
||||||
|
|
||||||
|
/* B.8 Writing Memory, single write check if we write in one go */
|
||||||
|
if (count == 1) { /* count is in bytes here */
|
||||||
|
/* check the size */
|
||||||
|
switch (size) {
|
||||||
|
case 1:
|
||||||
|
value = t_buffer[0];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
value = t_buffer[0]
|
||||||
|
| ((uint32_t) t_buffer[1] << 8);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
value = t_buffer[0]
|
||||||
|
| ((uint32_t) t_buffer[1] << 8)
|
||||||
|
| ((uint32_t) t_buffer[2] << 16)
|
||||||
|
| ((uint32_t) t_buffer[3] << 24);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_ERROR("unsupported access size: %d", size);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
access = 0;
|
||||||
|
access = set_field(access, DMI_SBCS_SBACCESS, size/2);
|
||||||
|
dmi_write(target, DMI_SBCS, access);
|
||||||
|
LOG_DEBUG("\r\naccess: 0x%08" PRIx64, access);
|
||||||
|
LOG_DEBUG("\r\nwrite_memory:SAB: ONE OFF: value 0x%08" PRIx64, value);
|
||||||
|
dmi_write(target, DMI_SBDATA0, value);
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*B.8 Writing Memory, using autoincrement*/
|
||||||
|
|
||||||
|
access = 0;
|
||||||
|
access = set_field(access, DMI_SBCS_SBACCESS, size/2);
|
||||||
|
access = set_field(access, DMI_SBCS_SBAUTOINCREMENT, 1);
|
||||||
|
LOG_DEBUG("\r\naccess: 0x%08" PRIx64, access);
|
||||||
|
dmi_write(target, DMI_SBCS, access);
|
||||||
|
|
||||||
|
/*2)set the value according to the size required and write*/
|
||||||
|
for (riscv_addr_t i = 0; i < count; ++i) {
|
||||||
|
offset = size*i;
|
||||||
|
/* for monitoring only */
|
||||||
|
t_addr = address + offset;
|
||||||
|
t_buffer = buffer + offset;
|
||||||
|
|
||||||
|
switch (size) {
|
||||||
|
case 1:
|
||||||
|
value = t_buffer[0];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
value = t_buffer[0]
|
||||||
|
| ((uint32_t) t_buffer[1] << 8);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
value = t_buffer[0]
|
||||||
|
| ((uint32_t) t_buffer[1] << 8)
|
||||||
|
| ((uint32_t) t_buffer[2] << 16)
|
||||||
|
| ((uint32_t) t_buffer[3] << 24);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_ERROR("unsupported access size: %d", size);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
LOG_DEBUG("SAB:autoincrement: expected address: 0x%08x value: 0x%08x"
|
||||||
|
PRIx64, (uint32_t)t_addr, (uint32_t)value);
|
||||||
|
dmi_write(target, DMI_SBDATA0, value);
|
||||||
|
}
|
||||||
|
/*reset the autoincrement when finished (something weird is happening if this is not done at the end*/
|
||||||
|
access = set_field(access, DMI_SBCS_SBAUTOINCREMENT, 0);
|
||||||
|
dmi_write(target, DMI_SBCS, access);
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_memory_bus_v1(struct target *target, target_addr_t address,
|
||||||
uint32_t size, uint32_t count, const uint8_t *buffer)
|
uint32_t size, uint32_t count, const uint8_t *buffer)
|
||||||
{
|
{
|
||||||
RISCV013_INFO(info);
|
RISCV013_INFO(info);
|
||||||
|
@ -2382,19 +2543,21 @@ static int write_memory(struct target *target, target_addr_t address,
|
||||||
uint32_t size, uint32_t count, const uint8_t *buffer)
|
uint32_t size, uint32_t count, const uint8_t *buffer)
|
||||||
{
|
{
|
||||||
RISCV013_INFO(info);
|
RISCV013_INFO(info);
|
||||||
if (info->progbufsize >= 2) {
|
if (info->progbufsize >= 2)
|
||||||
return write_memory_progbuf(target, address, size, count, buffer);
|
return write_memory_progbuf(target, address, size, count, buffer);
|
||||||
} else if ((get_field(info->sbcs, DMI_SBCS_SBVERSION) == 1) && (
|
if ((get_field(info->sbcs, DMI_SBCS_SBACCESS8) && size == 1) ||
|
||||||
(get_field(info->sbcs, DMI_SBCS_SBACCESS8) && size == 1) ||
|
|
||||||
(get_field(info->sbcs, DMI_SBCS_SBACCESS16) && size == 2) ||
|
(get_field(info->sbcs, DMI_SBCS_SBACCESS16) && size == 2) ||
|
||||||
(get_field(info->sbcs, DMI_SBCS_SBACCESS32) && size == 4) ||
|
(get_field(info->sbcs, DMI_SBCS_SBACCESS32) && size == 4) ||
|
||||||
(get_field(info->sbcs, DMI_SBCS_SBACCESS64) && size == 8) ||
|
(get_field(info->sbcs, DMI_SBCS_SBACCESS64) && size == 8) ||
|
||||||
(get_field(info->sbcs, DMI_SBCS_SBACCESS128) && size == 16))) {
|
(get_field(info->sbcs, DMI_SBCS_SBACCESS128) && size == 16)) {
|
||||||
return write_memory_bus(target, address, size, count, buffer);
|
if (get_field(info->sbcs, DMI_SBCS_SBVERSION) == 0)
|
||||||
} else {
|
return write_memory_bus_v0(target, address, size, count, buffer);
|
||||||
LOG_ERROR("Don't know how to write memory on this target.");
|
else if (get_field(info->sbcs, DMI_SBCS_SBVERSION) == 1)
|
||||||
return ERROR_FAIL;
|
return write_memory_bus_v1(target, address, size, count, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_ERROR("Don't know how to write memory on this target.");
|
||||||
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int arch_state(struct target *target)
|
static int arch_state(struct target *target)
|
||||||
|
|
Loading…
Reference in New Issue