cortex_a :apb mem read/write working with mmu_on

Conflicts:

	src/target/cortex_a.c
This commit is contained in:
Michel JAOUEN 2011-04-12 16:48:22 +02:00 committed by Øyvind Harboe
parent 28ddd16ddc
commit 08303f10aa
1 changed files with 168 additions and 156 deletions

View File

@ -320,6 +320,7 @@ static int cortex_a8_dap_write_coreregister_u32(struct target *target,
/* DCCRX to Rn, "MRC p14, 0, Rn, c0, c5, 0", 0xEE10nE15 */ /* DCCRX to Rn, "MRC p14, 0, Rn, c0, c5, 0", 0xEE10nE15 */
retval = cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, Rd, 0, 5, 0), retval = cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, Rd, 0, 5, 0),
&dscr); &dscr);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
} }
@ -1449,6 +1450,94 @@ static int cortex_a8_deassert_reset(struct target *target)
return ERROR_OK; return ERROR_OK;
} }
static int cortex_a8_write_apb_ab_memory(struct target *target,
uint32_t address, uint32_t size,
uint32_t count, const uint8_t *buffer)
{
int retval = ERROR_INVALID_ARGUMENTS;
struct armv7a_common *armv7a = target_to_armv7a(target);
struct arm *armv4_5 = &armv7a->armv4_5_common;
int nbytes = count * size;
uint32_t data;
struct reg *reg;
if (target->state != TARGET_HALTED)
{
LOG_WARNING("target not halted");
return ERROR_TARGET_NOT_HALTED;
}
reg = arm_reg_current(armv4_5, 0);
reg->dirty = 1;
reg = arm_reg_current(armv4_5, 1);
reg->dirty = 1;
retval = cortex_a8_dap_write_coreregister_u32(target, address, 0);
if (retval != ERROR_OK)
return retval;
while (nbytes > 0) {
data = *buffer++;
retval = cortex_a8_dap_write_coreregister_u32(target, data, 1);
if (retval != ERROR_OK)
return retval;
/* execute instruction STRB r1, [r0], 1 (0xe4c01001) */
retval = cortex_a8_exec_opcode(target, ARMV4_5_STRB_IP(1, 0) , NULL);
if (retval != ERROR_OK)
return retval;
--nbytes;
}
return retval;
}
static int cortex_a8_read_apb_ab_memory(struct target *target,
uint32_t address, uint32_t size,
uint32_t count, uint8_t *buffer)
{
int retval = ERROR_INVALID_ARGUMENTS;
struct armv7a_common *armv7a = target_to_armv7a(target);
struct arm *armv4_5 = &armv7a->armv4_5_common;
/* read memory through APB-AP */
int nbytes = count * size;
uint32_t data;
struct reg *reg;
if (target->state != TARGET_HALTED)
{
LOG_WARNING("target not halted");
return ERROR_TARGET_NOT_HALTED;
}
reg = arm_reg_current(armv4_5, 0);
reg->dirty = 1;
reg = arm_reg_current(armv4_5, 1);
reg->dirty = 1;
retval = cortex_a8_dap_write_coreregister_u32(target, address, 0);
if (retval != ERROR_OK)
return retval;
while (nbytes > 0) {
/* execute instruction LDRB r1, [r0], 1 (0xe4d01001) */
retval = cortex_a8_exec_opcode(target, ARMV4_5_LDRB_IP(1, 0) , NULL);
if (retval != ERROR_OK)
return retval;
retval = cortex_a8_dap_read_coreregister_u32(target, &data, 1);
if (retval != ERROR_OK)
return retval;
*buffer++ = data;
--nbytes;
}
return retval;
}
/* /*
* Cortex-A8 Memory access * Cortex-A8 Memory access
* *
@ -1464,8 +1553,8 @@ static int cortex_a8_read_phys_memory(struct target *target,
struct adiv5_dap *swjdp = armv7a->armv4_5_common.dap; struct adiv5_dap *swjdp = armv7a->armv4_5_common.dap;
int retval = ERROR_INVALID_ARGUMENTS; int retval = ERROR_INVALID_ARGUMENTS;
uint8_t apsel = swjdp->apsel; uint8_t apsel = swjdp->apsel;
LOG_DEBUG("Reading memory at real address 0x%x; size %d; count %d",
LOG_DEBUG("Reading memory at real address 0x%x; size %d; count %d", address, size, count); address, size, count);
if (count && buffer) { if (count && buffer) {
@ -1474,115 +1563,75 @@ static int cortex_a8_read_phys_memory(struct target *target,
/* read memory through AHB-AP */ /* read memory through AHB-AP */
switch (size) { switch (size) {
case 4: case 4:
retval = mem_ap_sel_read_buf_u32(swjdp, swjdp_memoryap, retval = mem_ap_sel_read_buf_u32(swjdp, swjdp_memoryap,
buffer, 4 * count, address); buffer, 4 * count, address);
break; break;
case 2: case 2:
retval = mem_ap_sel_read_buf_u16(swjdp, swjdp_memoryap, retval = mem_ap_sel_read_buf_u16(swjdp, swjdp_memoryap,
buffer, 2 * count, address); buffer, 2 * count, address);
break; break;
case 1: case 1:
retval = mem_ap_sel_read_buf_u8(swjdp, swjdp_memoryap, retval = mem_ap_sel_read_buf_u8(swjdp, swjdp_memoryap,
buffer, count, address); buffer, count, address);
break; break;
} }
} else { } else {
/* read memory through APB-AP */ /* read memory through APB-AP */
uint32_t saved_r0, saved_r1;
int nbytes = count * size;
uint32_t data;
int enabled = 0; int enabled = 0;
if (target->state != TARGET_HALTED)
{
LOG_WARNING("target not halted");
return ERROR_TARGET_NOT_HALTED;
}
retval = cortex_a8_mmu(target, &enabled); retval = cortex_a8_mmu(target, &enabled);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
if (enabled) if (enabled)
{ {
LOG_WARNING("Reading physical memory through APB with MMU enabled is not yet implemented"); LOG_WARNING("Reading physical memory through \
APB with MMU enabled is not yet implemented");
return ERROR_TARGET_FAILURE; return ERROR_TARGET_FAILURE;
} }
retval = cortex_a8_read_apb_ab_memory(target, address, size, count, buffer);
/* save registers r0 and r1, we are going to corrupt them */
retval = cortex_a8_dap_read_coreregister_u32(target, &saved_r0, 0);
if (retval != ERROR_OK)
return retval;
retval = cortex_a8_dap_read_coreregister_u32(target, &saved_r1, 1);
if (retval != ERROR_OK)
return retval;
retval = cortex_a8_dap_write_coreregister_u32(target, address, 0);
if (retval != ERROR_OK)
return retval;
while (nbytes > 0) {
/* execute instruction LDRB r1, [r0], 1 (0xe4d01001) */
retval = cortex_a8_exec_opcode(target, ARMV4_5_LDRB_IP(1, 0) , NULL);
if (retval != ERROR_OK)
return retval;
retval = cortex_a8_dap_read_coreregister_u32(target, &data, 1);
if (retval != ERROR_OK)
return retval;
*buffer++ = data;
--nbytes;
}
/* restore corrupted registers r0 and r1 */
retval = cortex_a8_dap_write_coreregister_u32(target, saved_r0, 0);
if (retval != ERROR_OK)
return retval;
retval = cortex_a8_dap_write_coreregister_u32(target, saved_r1, 1);
if (retval != ERROR_OK)
return retval;
} }
} }
return retval; return retval;
} }
static int cortex_a8_read_memory(struct target *target, uint32_t address, static int cortex_a8_read_memory(struct target *target, uint32_t address,
uint32_t size, uint32_t count, uint8_t *buffer) uint32_t size, uint32_t count, uint8_t *buffer)
{ {
int enabled = 0; int enabled = 0;
uint32_t virt, phys; uint32_t virt, phys;
int retval; int retval;
struct armv7a_common *armv7a = target_to_armv7a(target);
struct adiv5_dap *swjdp = armv7a->armv4_5_common.dap;
uint8_t apsel = swjdp->apsel;
/* cortex_a8 handles unaligned memory access */ /* cortex_a8 handles unaligned memory access */
LOG_DEBUG("Reading memory at address 0x%x; size %d; count %d", address,
size, count);
if (apsel == swjdp_memoryap) {
retval = cortex_a8_mmu(target, &enabled);
if (retval != ERROR_OK)
return retval;
LOG_DEBUG("Reading memory at address 0x%x; size %d; count %d", address, size, count); if(enabled)
retval = cortex_a8_mmu(target, &enabled); {
if (retval != ERROR_OK) virt = address;
return retval; retval = cortex_a8_virt2phys(target, virt, &phys);
if (retval != ERROR_OK)
return retval;
if(enabled) LOG_DEBUG("Reading at virtual address. Translating v:0x%x to r:0x%x",
{ virt, phys);
virt = address; address = phys;
retval = cortex_a8_virt2phys(target, virt, &phys); }
if (retval != ERROR_OK) retval = cortex_a8_read_phys_memory(target, address, size, count, buffer);
return retval; } else {
retval = cortex_a8_read_apb_ab_memory(target, address, size, count, buffer);
LOG_DEBUG("Reading at virtual address. Translating v:0x%x to r:0x%x", virt, phys); }
address = phys; return retval;
}
return cortex_a8_read_phys_memory(target, address, size, count, buffer);
} }
static int cortex_a8_write_phys_memory(struct target *target, static int cortex_a8_write_phys_memory(struct target *target,
@ -1594,7 +1643,8 @@ static int cortex_a8_write_phys_memory(struct target *target,
int retval = ERROR_INVALID_ARGUMENTS; int retval = ERROR_INVALID_ARGUMENTS;
uint8_t apsel = swjdp->apsel; uint8_t apsel = swjdp->apsel;
LOG_DEBUG("Writing memory to real address 0x%x; size %d; count %d", address, size, count); LOG_DEBUG("Writing memory to real address 0x%x; size %d; count %d", address,
size, count);
if (count && buffer) { if (count && buffer) {
@ -1620,69 +1670,19 @@ static int cortex_a8_write_phys_memory(struct target *target,
} else { } else {
/* write memory through APB-AP */ /* write memory through APB-AP */
uint32_t saved_r0, saved_r1;
int nbytes = count * size;
uint32_t data;
int enabled = 0; int enabled = 0;
if (target->state != TARGET_HALTED)
{
LOG_WARNING("target not halted");
return ERROR_TARGET_NOT_HALTED;
}
retval = cortex_a8_mmu(target, &enabled); retval = cortex_a8_mmu(target, &enabled);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
if (enabled) if (enabled)
{ {
LOG_WARNING("Writing physical memory through APB with MMU enabled is not yet implemented"); LOG_WARNING("Writing physical memory through APB with MMU" \
"enabled is not yet implemented");
return ERROR_TARGET_FAILURE; return ERROR_TARGET_FAILURE;
} }
return cortex_a8_write_apb_ab_memory(target, address, size, count, buffer);
/* save registers r0 and r1, we are going to corrupt them */
retval = cortex_a8_dap_read_coreregister_u32(target, &saved_r0, 0);
if (retval != ERROR_OK)
return retval;
retval = cortex_a8_dap_read_coreregister_u32(target, &saved_r1, 1);
if (retval != ERROR_OK)
return retval;
retval = cortex_a8_dap_write_coreregister_u32(target, address, 0);
if (retval != ERROR_OK)
return retval;
while (nbytes > 0) {
data = *buffer++;
retval = cortex_a8_dap_write_coreregister_u32(target, data, 1);
if (retval != ERROR_OK)
return retval;
/* execute instruction STRB r1, [r0], 1 (0xe4c01001) */
retval = cortex_a8_exec_opcode(target, ARMV4_5_STRB_IP(1, 0) , NULL);
if (retval != ERROR_OK)
return retval;
--nbytes;
}
/* restore corrupted registers r0 and r1 */
retval = cortex_a8_dap_write_coreregister_u32(target, saved_r0, 0);
if (retval != ERROR_OK)
return retval;
retval = cortex_a8_dap_write_coreregister_u32(target, saved_r1, 1);
if (retval != ERROR_OK)
return retval;
/* we can return here without invalidating D/I-cache because */
/* access through APB maintains cache coherency */
return retval;
} }
} }
@ -1750,27 +1750,39 @@ static int cortex_a8_write_phys_memory(struct target *target,
static int cortex_a8_write_memory(struct target *target, uint32_t address, static int cortex_a8_write_memory(struct target *target, uint32_t address,
uint32_t size, uint32_t count, const uint8_t *buffer) uint32_t size, uint32_t count, const uint8_t *buffer)
{ {
int enabled = 0; int enabled = 0;
uint32_t virt, phys; uint32_t virt, phys;
int retval; int retval;
struct armv7a_common *armv7a = target_to_armv7a(target);
struct adiv5_dap *swjdp = armv7a->armv4_5_common.dap;
uint8_t apsel = swjdp->apsel;
/* cortex_a8 handles unaligned memory access */
LOG_DEBUG("Reading memory at address 0x%x; size %d; count %d", address,
size, count);
if (apsel == swjdp_memoryap) {
LOG_DEBUG("Writing memory to address 0x%x; size %d; count %d", address, size, count); LOG_DEBUG("Writing memory to address 0x%x; size %d; count %d", address, size, count);
retval = cortex_a8_mmu(target, &enabled); retval = cortex_a8_mmu(target, &enabled);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
if(enabled) if(enabled)
{ {
virt = address; virt = address;
retval = cortex_a8_virt2phys(target, virt, &phys); retval = cortex_a8_virt2phys(target, virt, &phys);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
LOG_DEBUG("Writing to virtual address. Translating v:0x%x to r:0x%x", virt, phys); LOG_DEBUG("Writing to virtual address. Translating v:0x%x to r:0x%x", virt, phys);
address = phys; address = phys;
} }
return cortex_a8_write_phys_memory(target, address, size, retval = cortex_a8_write_phys_memory(target, address, size,
count, buffer); count, buffer);
}
else {
retval = cortex_a8_write_apb_ab_memory(target, address, size, count, buffer);
}
return retval;
} }
static int cortex_a8_bulk_write_memory(struct target *target, uint32_t address, static int cortex_a8_bulk_write_memory(struct target *target, uint32_t address,