uint32_t count, uint8_t *buffer)
{
struct armv7a_common *armv7a = target_to_armv7a(target);
- struct adiv5_dap *swjdp = armv7a->arm.dap;
int retval = ERROR_COMMAND_SYNTAX_ERROR;
- uint8_t apsel = swjdp->apsel;
+
LOG_DEBUG("Reading memory at real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32,
address, size, count);
if (count && buffer) {
+ /* read memory through APB-AP */
+ if (!armv7a->is_armv7r) {
+ /* disable mmu */
+ retval = cortex_a_mmu_modify(target, 0);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+ retval = cortex_a_read_apb_ab_memory(target, address, size, count, buffer);
+ }
+ return retval;
+}
- if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) {
+static int cortex_a_read_memory(struct target *target, uint32_t address,
+ uint32_t size, uint32_t count, uint8_t *buffer)
+{
+ int mmu_enabled = 0;
+ int retval;
+ struct armv7a_common *armv7a = target_to_armv7a(target);
- /* read memory through AHB-AP */
- retval = mem_ap_sel_read_buf(swjdp, armv7a->memory_ap, buffer, size, count, address);
- } else {
+ /* cortex_a handles unaligned memory access */
+ LOG_DEBUG("Reading memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
+ size, count);
- /* read memory through APB-AP */
- if (!armv7a->is_armv7r) {
- /* disable mmu */
- retval = cortex_a_mmu_modify(target, 0);
- if (retval != ERROR_OK)
- return retval;
- }
- retval = cortex_a_read_apb_ab_memory(target, address, size, count, buffer);
- }
+ /* determine if MMU was enabled on target stop */
+ if (!armv7a->is_armv7r) {
+ retval = cortex_a_mmu(target, &mmu_enabled);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
+ if (mmu_enabled) {
+ retval = cortex_a_check_address(target, address);
+ if (retval != ERROR_OK)
+ return retval;
+ /* enable MMU as we could have disabled it for phys access */
+ retval = cortex_a_mmu_modify(target, 1);
+ if (retval != ERROR_OK)
+ return retval;
}
+ retval = cortex_a_read_apb_ab_memory(target, address, size, count, buffer);
+
return retval;
}
-static int cortex_a_read_memory(struct target *target, uint32_t address,
+static int cortex_a_read_memory_ahb(struct target *target, uint32_t address,
uint32_t size, uint32_t count, uint8_t *buffer)
{
int mmu_enabled = 0;
struct adiv5_dap *swjdp = armv7a->arm.dap;
uint8_t apsel = swjdp->apsel;
+ if (!armv7a->memory_ap_available || (apsel != armv7a->memory_ap))
+ return target_read_memory(target, address, size, count, buffer);
+
/* cortex_a handles unaligned memory access */
LOG_DEBUG("Reading memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
size, count);
return retval;
}
- if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) {
- if (mmu_enabled) {
- virt = address;
- retval = cortex_a_virt2phys(target, virt, &phys);
- if (retval != ERROR_OK)
- return retval;
+ if (mmu_enabled) {
+ virt = address;
+ retval = cortex_a_virt2phys(target, virt, &phys);
+ if (retval != ERROR_OK)
+ return retval;
- LOG_DEBUG("Reading at virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32,
- virt, phys);
- address = phys;
- }
- retval = cortex_a_read_phys_memory(target, address, size,
- count, buffer);
- } else {
- if (mmu_enabled) {
- retval = cortex_a_check_address(target, address);
- if (retval != ERROR_OK)
- return retval;
- /* enable MMU as we could have disabled it for phys access */
- retval = cortex_a_mmu_modify(target, 1);
- if (retval != ERROR_OK)
- return retval;
- }
- retval = cortex_a_read_apb_ab_memory(target, address, size, count, buffer);
+ LOG_DEBUG("Reading at virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32,
+ virt, phys);
+ address = phys;
}
+
+ if (!count || !buffer)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ retval = mem_ap_sel_read_buf(swjdp, armv7a->memory_ap, buffer, size, count, address);
+
return retval;
}
uint32_t count, const uint8_t *buffer)
{
struct armv7a_common *armv7a = target_to_armv7a(target);
- struct adiv5_dap *swjdp = armv7a->arm.dap;
int retval = ERROR_COMMAND_SYNTAX_ERROR;
- uint8_t apsel = swjdp->apsel;
LOG_DEBUG("Writing memory to real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
size, count);
if (count && buffer) {
-
- if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) {
-
- /* write memory through AHB-AP */
- retval = mem_ap_sel_write_buf(swjdp, armv7a->memory_ap, buffer, size, count, address);
- } else {
-
- /* write memory through APB-AP */
- if (!armv7a->is_armv7r) {
- retval = cortex_a_mmu_modify(target, 0);
- if (retval != ERROR_OK)
- return retval;
- }
- return cortex_a_write_apb_ab_memory(target, address, size, count, buffer);
+ /* write memory through APB-AP */
+ if (!armv7a->is_armv7r) {
+ retval = cortex_a_mmu_modify(target, 0);
+ if (retval != ERROR_OK)
+ return retval;
}
+ return cortex_a_write_apb_ab_memory(target, address, size, count, buffer);
}
+ return retval;
+}
- /* REVISIT this op is generic ARMv7-A/R stuff */
- if (retval == ERROR_OK && target->state == TARGET_HALTED) {
- struct arm_dpm *dpm = armv7a->arm.dpm;
+static int cortex_a_write_memory(struct target *target, uint32_t address,
+ uint32_t size, uint32_t count, const uint8_t *buffer)
+{
+ int mmu_enabled = 0;
+ int retval;
+ struct armv7a_common *armv7a = target_to_armv7a(target);
- retval = dpm->prepare(dpm);
+ /* cortex_a handles unaligned memory access */
+ LOG_DEBUG("Writing memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
+ size, count);
+
+ /* determine if MMU was enabled on target stop */
+ if (!armv7a->is_armv7r) {
+ retval = cortex_a_mmu(target, &mmu_enabled);
if (retval != ERROR_OK)
return retval;
+ }
- /* The Cache handling will NOT work with MMU active, the
- * wrong addresses will be invalidated!
- *
- * For both ICache and DCache, walk all cache lines in the
- * address range. Cortex-A has fixed 64 byte line length.
- *
- * REVISIT per ARMv7, these may trigger watchpoints ...
- */
-
- /* invalidate I-Cache */
- if (armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled) {
- /* ICIMVAU - Invalidate Cache single entry
- * with MVA to PoU
- * MCR p15, 0, r0, c7, c5, 1
- */
- for (uint32_t cacheline = 0;
- cacheline < size * count;
- cacheline += 64) {
- retval = dpm->instr_write_data_r0(dpm,
- ARMV4_5_MCR(15, 0, 0, 7, 5, 1),
- address + cacheline);
- if (retval != ERROR_OK)
- return retval;
- }
- }
-
- /* invalidate D-Cache */
- if (armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled) {
- /* DCIMVAC - Invalidate data Cache line
- * with MVA to PoC
- * MCR p15, 0, r0, c7, c6, 1
- */
- for (uint32_t cacheline = 0;
- cacheline < size * count;
- cacheline += 64) {
- retval = dpm->instr_write_data_r0(dpm,
- ARMV4_5_MCR(15, 0, 0, 7, 6, 1),
- address + cacheline);
- if (retval != ERROR_OK)
- return retval;
- }
- }
-
- /* (void) */ dpm->finish(dpm);
+ if (mmu_enabled) {
+ retval = cortex_a_check_address(target, address);
+ if (retval != ERROR_OK)
+ return retval;
+ /* enable MMU as we could have disabled it for phys access */
+ retval = cortex_a_mmu_modify(target, 1);
+ if (retval != ERROR_OK)
+ return retval;
}
+ retval = cortex_a_write_apb_ab_memory(target, address, size, count, buffer);
return retval;
}
-static int cortex_a_write_memory(struct target *target, uint32_t address,
+static int cortex_a_write_memory_ahb(struct target *target, uint32_t address,
uint32_t size, uint32_t count, const uint8_t *buffer)
{
int mmu_enabled = 0;
struct adiv5_dap *swjdp = armv7a->arm.dap;
uint8_t apsel = swjdp->apsel;
+ if (!armv7a->memory_ap_available || (apsel != armv7a->memory_ap))
+ return target_write_memory(target, address, size, count, buffer);
+
/* cortex_a handles unaligned memory access */
LOG_DEBUG("Writing memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
size, count);
return retval;
}
- if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) {
- LOG_DEBUG("Writing memory to address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, size,
- count);
- if (mmu_enabled) {
- virt = address;
- retval = cortex_a_virt2phys(target, virt, &phys);
+ if (mmu_enabled) {
+ virt = address;
+ retval = cortex_a_virt2phys(target, virt, &phys);
+ if (retval != ERROR_OK)
+ return retval;
+
+ LOG_DEBUG("Writing to virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32,
+ virt,
+ phys);
+ address = phys;
+ }
+
+ if (!count || !buffer)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ retval = mem_ap_sel_write_buf(swjdp, armv7a->memory_ap, buffer, size, count, address);
+
+ return retval;
+}
+
+static int cortex_a_read_buffer(struct target *target, uint32_t address,
+ uint32_t count, uint8_t *buffer)
+{
+ uint32_t size;
+
+ /* Align up to maximum 4 bytes. The loop condition makes sure the next pass
+ * will have something to do with the size we leave to it. */
+ for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) {
+ if (address & size) {
+ int retval = cortex_a_read_memory_ahb(target, address, size, 1, buffer);
if (retval != ERROR_OK)
return retval;
+ address += size;
+ count -= size;
+ buffer += size;
+ }
+ }
- LOG_DEBUG("Writing to virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32,
- virt,
- phys);
- address = phys;
+ /* Read the data with as large access size as possible. */
+ for (; size > 0; size /= 2) {
+ uint32_t aligned = count - count % size;
+ if (aligned > 0) {
+ int retval = cortex_a_read_memory_ahb(target, address, size, aligned / size, buffer);
+ if (retval != ERROR_OK)
+ return retval;
+ address += aligned;
+ count -= aligned;
+ buffer += aligned;
}
- retval = cortex_a_write_phys_memory(target, address, size,
- count, buffer);
- } else {
- if (mmu_enabled) {
- retval = cortex_a_check_address(target, address);
+ }
+
+ return ERROR_OK;
+}
+
+static int cortex_a_write_buffer(struct target *target, uint32_t address,
+ uint32_t count, const uint8_t *buffer)
+{
+ uint32_t size;
+
+ /* Align up to maximum 4 bytes. The loop condition makes sure the next pass
+ * will have something to do with the size we leave to it. */
+ for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) {
+ if (address & size) {
+ int retval = cortex_a_write_memory_ahb(target, address, size, 1, buffer);
if (retval != ERROR_OK)
return retval;
- /* enable MMU as we could have disabled it for phys access */
- retval = cortex_a_mmu_modify(target, 1);
+ address += size;
+ count -= size;
+ buffer += size;
+ }
+ }
+
+ /* Write the data with as large access size as possible. */
+ for (; size > 0; size /= 2) {
+ uint32_t aligned = count - count % size;
+ if (aligned > 0) {
+ int retval = cortex_a_write_memory_ahb(target, address, size, aligned / size, buffer);
if (retval != ERROR_OK)
return retval;
+ address += aligned;
+ count -= aligned;
+ buffer += aligned;
}
- retval = cortex_a_write_apb_ab_memory(target, address, size, count, buffer);
}
- return retval;
+
+ return ERROR_OK;
}
static int cortex_a_handle_target_request(void *priv)
.read_memory = cortex_a_read_memory,
.write_memory = cortex_a_write_memory,
+ .read_buffer = cortex_a_read_buffer,
+ .write_buffer = cortex_a_write_buffer,
+
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,