X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Fcortex_a.c;h=50eb9d48aa8d2801202bd48ed3ba36d794540d2d;hp=4649f6c7da544f9ee5f77e00c075b6e8a3a99b47;hb=ee54f7e9f0ad096d8db91a302c70d18d250db74b;hpb=32ac9c0144f7aa7233b941bf78139eef8332fbc2 diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 4649f6c7da..50eb9d48aa 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -102,14 +102,14 @@ static int cortex_a8_check_address(struct target *target, uint32_t address) uint32_t os_border = armv7a->armv7a_mmu.os_border; if ((address < os_border) && (armv7a->arm.core_mode == ARM_MODE_SVC)) { - LOG_ERROR("%x access in userspace and target in supervisor", address); + LOG_ERROR("%" PRIx32 " access in userspace and target in supervisor", address); return ERROR_FAIL; } if ((address >= os_border) && (cortex_a8->curr_mode != ARM_MODE_SVC)) { dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC); cortex_a8->curr_mode = ARM_MODE_SVC; - LOG_INFO("%x access in kernel space and target not in supervisor", + LOG_INFO("%" PRIx32 " access in kernel space and target not in supervisor", address); return ERROR_OK; } @@ -279,8 +279,8 @@ static int cortex_a8_read_regs_through_mem(struct target *target, uint32_t addre if (retval != ERROR_OK) return retval; - retval = mem_ap_sel_read_buf_u32(swjdp, armv7a->memory_ap, - (uint8_t *)(®file[1]), 4*15, address); + retval = mem_ap_sel_read_buf(swjdp, armv7a->memory_ap, + (uint8_t *)(®file[1]), 4, 15, address); return retval; } @@ -766,7 +766,7 @@ static int cortex_a8_halt_smp(struct target *target) static int update_halt_gdb(struct target *target) { int retval = 0; - if (target->gdb_service->core[0] == -1) { + if (target->gdb_service && target->gdb_service->core[0] == -1) { target->gdb_service->target = target; target->gdb_service->core[0] = target->coreid; retval += cortex_a8_halt_smp(target); @@ -1798,6 +1798,8 @@ static int cortex_a8_write_apb_ab_memory(struct target *target, uint32_t dscr; uint8_t *tmp_buff = NULL; + LOG_DEBUG("Writing APB-AP memory address 0x%" PRIx32 " size %" PRIu32 " count%" PRIu32, + address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; @@ -1829,8 +1831,7 @@ static int cortex_a8_write_apb_ab_memory(struct target *target, * The first and last words will be read first to avoid * corruption if needed. */ - tmp_buff = (uint8_t *) malloc(total_u32 << 2); - + tmp_buff = malloc(total_u32 * 4); if ((start_byte != 0) && (total_u32 > 1)) { /* First bytes not aligned - read the 32 bit word to avoid corrupting @@ -1846,7 +1847,7 @@ static int cortex_a8_write_apb_ab_memory(struct target *target, ((total_u32 == 1) && (total_bytes != 4))) { /* Read the last word to avoid corruption during 32 bit write */ - int mem_offset = (total_u32-1) << 4; + int mem_offset = (total_u32-1) * 4; retval = cortex_a8_read_apb_ab_memory(target, (address & ~0x3) + mem_offset, 4, 1, &tmp_buff[mem_offset]); if (retval != ERROR_OK) goto error_free_buff_w; @@ -1891,8 +1892,8 @@ static int cortex_a8_write_apb_ab_memory(struct target *target, goto error_unset_dtr_w; /* Do the write */ - retval = mem_ap_sel_write_buf_u32_noincr(swjdp, armv7a->debug_ap, - tmp_buff, (total_u32)<<2, armv7a->debug_base + CPUDBG_DTRRX); + retval = mem_ap_sel_write_buf_noincr(swjdp, armv7a->debug_ap, + tmp_buff, 4, total_u32, armv7a->debug_base + CPUDBG_DTRRX); if (retval != ERROR_OK) goto error_unset_dtr_w; @@ -1911,7 +1912,7 @@ static int cortex_a8_write_apb_ab_memory(struct target *target, goto error_free_buff_w; if (dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) { /* Abort occurred - clear it and exit */ - LOG_ERROR("abort occurred - dscr = 0x%08x", dscr); + LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr); mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DRCR, 1<<2); goto error_free_buff_w; @@ -1947,25 +1948,21 @@ static int cortex_a8_read_apb_ab_memory(struct target *target, int total_bytes = count * size; int total_u32; int start_byte = address & 0x3; + int end_byte = (address + total_bytes) & 0x3; struct reg *reg; uint32_t dscr; - uint32_t *tmp_buff; - uint32_t buff32[2]; + uint8_t *tmp_buff = NULL; + uint8_t buf[8]; + uint8_t *u8buf_ptr; + + LOG_DEBUG("Reading APB-AP memory address 0x%" PRIx32 " size %" PRIu32 " count%" PRIu32, + address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } total_u32 = DIV_ROUND_UP((address & 3) + total_bytes, 4); - - /* Due to offset word alignment, the buffer may not have space - * to read the full first and last int32 words, - * hence, malloc space to read into, then copy and align into the buffer. - */ - tmp_buff = malloc(total_u32 * 4); - if (tmp_buff == NULL) - return ERROR_FAIL; - /* Mark register R0 as dirty, as it will be used * for transferring the data. * It will be restored automatically when exiting @@ -1995,41 +1992,53 @@ static int cortex_a8_read_apb_ab_memory(struct target *target, retval += mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, dscr); - /* Write R0 with value 'address' using write procedure for stall mode */ + /* Write R0 with value 'address' using write procedure for stall mode */ /* - Write the address for read access into DTRRX */ retval += mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRRX, address & ~0x3); /* - Copy value from DTRRX to R0 using instruction mrc p14, 0, r0, c5, c0 */ cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), &dscr); - /* Write the data transfer instruction (ldc p14, c5, [r0],4) * and the DTR mode setting to fast mode * in one combined write (since they are adjacent registers) */ - buff32[0] = ARMV4_5_LDC(0, 1, 0, 1, 14, 5, 0, 4); + u8buf_ptr = buf; + target_buffer_set_u32(target, u8buf_ptr, ARMV4_5_LDC(0, 1, 0, 1, 14, 5, 0, 4)); dscr = (dscr & ~DSCR_EXT_DCC_MASK) | DSCR_EXT_DCC_FAST_MODE; - buff32[1] = dscr; + target_buffer_set_u32(target, u8buf_ptr + 4, dscr); /* group the 2 access CPUDBG_ITR 0x84 and CPUDBG_DSCR 0x88 */ - retval += mem_ap_sel_write_buf_u32(swjdp, armv7a->debug_ap, (uint8_t *)buff32, 8, + retval += mem_ap_sel_write_buf(swjdp, armv7a->debug_ap, u8buf_ptr, 4, 2, armv7a->debug_base + CPUDBG_ITR); if (retval != ERROR_OK) goto error_unset_dtr_r; + /* Optimize the read as much as we can, either way we read in a single pass */ + if ((start_byte) || (end_byte)) { + /* The algorithm only copies 32 bit words, so the buffer + * should be expanded to include the words at either end. + * The first and last words will be read into a temp buffer + * to avoid corruption + */ + tmp_buff = malloc(total_u32 * 4); + if (!tmp_buff) + goto error_unset_dtr_r; + + /* use the tmp buffer to read the entire data */ + u8buf_ptr = tmp_buff; + } else + /* address and read length are aligned so read directely into the passed buffer */ + u8buf_ptr = buffer; - /* The last word needs to be handled separately - read all other words in one go. + /* Read the data - Each read of the DTRTX register causes the instruction to be reissued + * Abort flags are sticky, so can be read at end of transactions + * + * This data is read in aligned to 32 bit boundary. */ - if (total_u32 > 1) { - /* Read the data - Each read of the DTRTX register causes the instruction to be reissued - * Abort flags are sticky, so can be read at end of transactions - * - * This data is read in aligned to 32 bit boundary, hence may need shifting later. - */ - retval = mem_ap_sel_read_buf_u32_noincr(swjdp, armv7a->debug_ap, (uint8_t *)tmp_buff, (total_u32-1) * 4, + retval = mem_ap_sel_read_buf_noincr(swjdp, armv7a->debug_ap, u8buf_ptr, 4, total_u32, armv7a->debug_base + CPUDBG_DTRTX); - if (retval != ERROR_OK) + if (retval != ERROR_OK) goto error_unset_dtr_r; - } /* set DTR access mode back to non blocking b00 */ dscr = (dscr & ~DSCR_EXT_DCC_MASK) | DSCR_EXT_DCC_NON_BLOCKING; @@ -2046,7 +2055,6 @@ static int cortex_a8_read_apb_ab_memory(struct target *target, goto error_free_buff_r; } while ((dscr & DSCR_INSTR_COMP) == 0); - /* Check for sticky abort flags in the DSCR */ retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); @@ -2054,27 +2062,21 @@ static int cortex_a8_read_apb_ab_memory(struct target *target, goto error_free_buff_r; if (dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) { /* Abort occurred - clear it and exit */ - LOG_ERROR("abort occurred - dscr = 0x%08x", dscr); + LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr); mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DRCR, 1<<2); goto error_free_buff_r; } - /* Read the last word */ - retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, - armv7a->debug_base + CPUDBG_DTRTX, &tmp_buff[total_u32 - 1]); - if (retval != ERROR_OK) - goto error_free_buff_r; - - /* Copy and align the data into the output buffer */ - memcpy(buffer, (uint8_t *)tmp_buff + start_byte, total_bytes); - - free(tmp_buff); + /* check if we need to copy aligned data by applying any shift necessary */ + if (tmp_buff) { + memcpy(buffer, tmp_buff + start_byte, total_bytes); + free(tmp_buff); + } /* Done */ return ERROR_OK; - error_unset_dtr_r: /* Unset DTR mode */ mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, @@ -2104,7 +2106,7 @@ static int cortex_a8_read_phys_memory(struct target *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%x; size %d; count %d", + LOG_DEBUG("Reading memory at real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, size, count); if (count && buffer) { @@ -2112,21 +2114,7 @@ static int cortex_a8_read_phys_memory(struct target *target, if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) { /* read memory through AHB-AP */ - - switch (size) { - case 4: - retval = mem_ap_sel_read_buf_u32(swjdp, armv7a->memory_ap, - buffer, 4 * count, address); - break; - case 2: - retval = mem_ap_sel_read_buf_u16(swjdp, armv7a->memory_ap, - buffer, 2 * count, address); - break; - case 1: - retval = mem_ap_sel_read_buf_u8(swjdp, armv7a->memory_ap, - buffer, count, address); - break; - } + retval = mem_ap_sel_read_buf(swjdp, armv7a->memory_ap, buffer, size, count, address); } else { /* read memory through APB-AP */ @@ -2145,7 +2133,7 @@ static int cortex_a8_read_phys_memory(struct target *target, static int cortex_a8_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { - int enabled = 0; + int mmu_enabled = 0; uint32_t virt, phys; int retval; struct armv7a_common *armv7a = target_to_armv7a(target); @@ -2153,33 +2141,34 @@ static int cortex_a8_read_memory(struct target *target, uint32_t address, uint8_t apsel = swjdp->apsel; /* cortex_a8 handles unaligned memory access */ - LOG_DEBUG("Reading memory at address 0x%x; size %d; count %d", address, + LOG_DEBUG("Reading 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_a8_mmu(target, &mmu_enabled); + if (retval != ERROR_OK) + return retval; + } + if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) { - if (!armv7a->is_armv7r) { - retval = cortex_a8_mmu(target, &enabled); + if (mmu_enabled) { + virt = address; + retval = cortex_a8_virt2phys(target, virt, &phys); if (retval != ERROR_OK) return retval; - - if (enabled) { - virt = address; - retval = cortex_a8_virt2phys(target, virt, &phys); - if (retval != ERROR_OK) - return retval; - - LOG_DEBUG("Reading at virtual address. Translating v:0x%x to r:0x%x", - virt, phys); - address = phys; - } + LOG_DEBUG("Reading at virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32, + virt, phys); + address = phys; } retval = cortex_a8_read_phys_memory(target, address, size, count, buffer); } else { - if (!armv7a->is_armv7r) { + if (mmu_enabled) { retval = cortex_a8_check_address(target, address); if (retval != ERROR_OK) return retval; - /* enable mmu */ + /* enable MMU as we could have disabled it for phys access */ retval = cortex_a8_mmu_modify(target, 1); if (retval != ERROR_OK) return retval; @@ -2198,7 +2187,7 @@ static int cortex_a8_write_phys_memory(struct target *target, int retval = ERROR_COMMAND_SYNTAX_ERROR; uint8_t apsel = swjdp->apsel; - LOG_DEBUG("Writing memory to real address 0x%x; size %d; count %d", address, + LOG_DEBUG("Writing memory to real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, size, count); if (count && buffer) { @@ -2206,22 +2195,7 @@ static int cortex_a8_write_phys_memory(struct target *target, if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) { /* write memory through AHB-AP */ - - switch (size) { - case 4: - retval = mem_ap_sel_write_buf_u32(swjdp, armv7a->memory_ap, - buffer, 4 * count, address); - break; - case 2: - retval = mem_ap_sel_write_buf_u16(swjdp, armv7a->memory_ap, - buffer, 2 * count, address); - break; - case 1: - retval = mem_ap_sel_write_buf_u8(swjdp, armv7a->memory_ap, - buffer, count, address); - break; - } - + retval = mem_ap_sel_write_buf(swjdp, armv7a->memory_ap, buffer, size, count, address); } else { /* write memory through APB-AP */ @@ -2295,44 +2269,46 @@ static int cortex_a8_write_phys_memory(struct target *target, static int cortex_a8_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { - int enabled = 0; + int mmu_enabled = 0; uint32_t virt, phys; int retval; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; uint8_t apsel = swjdp->apsel; + /* cortex_a8 handles unaligned memory access */ - LOG_DEBUG("Writing memory at address 0x%x; size %d; count %d", address, + LOG_DEBUG("Writing memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, size, count); - if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) { - LOG_DEBUG("Writing memory to address 0x%x; size %d; count %d", address, size, + /* determine if MMU was enabled on target stop */ + if (!armv7a->is_armv7r) { + retval = cortex_a8_mmu(target, &mmu_enabled); + if (retval != ERROR_OK) + 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 (!armv7a->is_armv7r) { - retval = cortex_a8_mmu(target, &enabled); + if (mmu_enabled) { + virt = address; + retval = cortex_a8_virt2phys(target, virt, &phys); if (retval != ERROR_OK) return retval; - if (enabled) { - virt = address; - retval = cortex_a8_virt2phys(target, virt, &phys); - if (retval != ERROR_OK) - return retval; - LOG_DEBUG("Writing to virtual address. Translating v:0x%x to r:0x%x", - virt, - phys); - address = phys; - } + LOG_DEBUG("Writing to virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32, + virt, + phys); + address = phys; } - retval = cortex_a8_write_phys_memory(target, address, size, count, buffer); } else { - if (!armv7a->is_armv7r) { + if (mmu_enabled) { retval = cortex_a8_check_address(target, address); if (retval != ERROR_OK) return retval; - /* enable mmu */ + /* enable MMU as we could have disabled it for phys access */ retval = cortex_a8_mmu_modify(target, 1); if (retval != ERROR_OK) return retval; @@ -2696,7 +2672,7 @@ COMMAND_HANDLER(cortex_a8_handle_smp_gdb_command) target->gdb_service->core[1] = coreid; } - command_print(CMD_CTX, "gdb coreid %d -> %d", target->gdb_service->core[0] + command_print(CMD_CTX, "gdb coreid %" PRId32 " -> %" PRId32, target->gdb_service->core[0] , target->gdb_service->core[1]); } return ERROR_OK;