* michel.jaouen@stericsson.com : smp minimum support *
* *
* Copyright (C) Broadcom 2012 *
- * ehunter@broadcom.com : Cortex R4 support *
+ * ehunter@broadcom.com : Cortex-R4 support *
* *
* Copyright (C) 2013 Kamal Dasu *
* kdasu.kdev@gmail.com *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
* Cortex-A8(tm) TRM, ARM DDI 0344H *
* Cortex-A9(tm) TRM, ARM DDI 0407F *
#include "target_request.h"
#include "target_type.h"
#include "arm_opcodes.h"
+#include "arm_semihosting.h"
#include <helper/time_support.h>
static int cortex_a_poll(struct target *target);
return retval;
}
-/*
- * Cortex-A Basic debug access, very low level assumes state is saved
- */
-static int cortex_a8_init_debug_access(struct target *target)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- int retval;
-
- LOG_DEBUG(" ");
-
- /* Unlocking the debug registers for modification
- * The debugport might be uninitialised so try twice */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
- if (retval != ERROR_OK) {
- /* try again */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
- if (retval == ERROR_OK)
- LOG_USER(
- "Locking debug access failed on first, but succeeded on second try.");
- }
-
- return retval;
-}
-
/*
* Cortex-A Basic debug access, very low level assumes state is saved
*/
{
struct armv7a_common *armv7a = target_to_armv7a(target);
int retval;
- uint32_t dbg_osreg;
- uint32_t cortex_part_num;
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
-
- LOG_DEBUG(" ");
- cortex_part_num = (cortex_a->cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >>
- CORTEX_A_MIDR_PARTNUM_SHIFT;
-
- switch (cortex_part_num) {
- case CORTEX_A7_PARTNUM:
- case CORTEX_A15_PARTNUM:
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_OSLSR,
- &dbg_osreg);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("DBGOSLSR 0x%" PRIx32, dbg_osreg);
-
- if (dbg_osreg & CPUDBG_OSLAR_LK_MASK)
- /* Unlocking the DEBUG OS registers for modification */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_OSLAR,
- 0);
- break;
-
- case CORTEX_A5_PARTNUM:
- case CORTEX_A8_PARTNUM:
- case CORTEX_A9_PARTNUM:
- default:
- retval = cortex_a8_init_debug_access(target);
- }
-
- if (retval != ERROR_OK)
- return retval;
- /* Clear Sticky Power Down status Bit in PRSR to enable access to
- the registers in the Core Power Domain */
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg);
- LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg);
+ /* lock memory-mapped access to debug registers to prevent
+ * software interference */
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_LOCKACCESS, 0);
if (retval != ERROR_OK)
return retval;
head = target->head;
while (head != (struct target_list *)NULL) {
curr = head->target;
- if ((curr != target) && (curr->state != TARGET_HALTED))
+ if ((curr != target) && (curr->state != TARGET_HALTED)
+ && target_was_examined(curr))
retval += cortex_a_halt(curr);
head = head->next;
}
if (retval != ERROR_OK)
return retval;
}
+
+ if (arm_semihosting(target, &retval) != 0)
+ return retval;
+
target_call_event_callbacks(target,
TARGET_EVENT_HALTED);
}
head = target->head;
while (head != (struct target_list *)NULL) {
curr = head->target;
- if ((curr != target) && (curr->state != TARGET_RUNNING)) {
+ if ((curr != target) && (curr->state != TARGET_RUNNING)
+ && target_was_examined(curr)) {
/* resume current address , not in step mode */
retval += cortex_a_internal_restore(curr, 1, &address,
handle_breakpoints, 0);
static int cortex_a_debug_entry(struct target *target)
{
int i;
- uint32_t regfile[16], cpsr, dscr;
+ uint32_t regfile[16], cpsr, spsr, dscr;
int retval = ERROR_OK;
struct working_area *regfile_working_area = NULL;
struct cortex_a_common *cortex_a = target_to_cortex_a(target);
if (cortex_a->fast_reg_read)
target_alloc_working_area(target, 64, ®file_working_area);
+
/* First load register acessible through core debug port*/
if (!regfile_working_area)
retval = arm_dpm_read_current_registers(&armv7a->dpm);
reg->dirty = reg->valid;
}
+ /* read Saved PSR */
+ retval = cortex_a_dap_read_coreregister_u32(target, &spsr, 17);
+ /* store current spsr */
+ if (retval != ERROR_OK)
+ return retval;
+
+ reg = arm->spsr;
+ buf_set_u32(reg->value, 0, 32, spsr);
+ reg->valid = 1;
+ reg->dirty = 0;
+
#if 0
/* TODO, Move this */
uint32_t cp15_control_register, cp15_cacr, cp15_nacr;
}
/* registers are now invalid */
- register_cache_invalidate(armv7a->arm.core_cache);
+ if (target_was_examined(target))
+ register_cache_invalidate(armv7a->arm.core_cache);
target->state = TARGET_RESET;
/* be certain SRST is off */
jtag_add_reset(0, 0);
- retval = cortex_a_poll(target);
- if (retval != ERROR_OK)
- return retval;
+ if (target_was_examined(target)) {
+ retval = cortex_a_poll(target);
+ if (retval != ERROR_OK)
+ return retval;
+ }
if (target->reset_halt) {
if (target->state != TARGET_HALTED) {
LOG_WARNING("%s: ran after reset and before halt ...",
target_name(target));
- retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
+ if (target_was_examined(target)) {
+ retval = target_halt(target);
+ if (retval != ERROR_OK)
+ return retval;
+ } else
+ target->state = TARGET_UNKNOWN;
}
}
/*
* Cortex-A Memory access
*
- * This is same Cortex M3 but we must also use the correct
+ * This is same Cortex-M3 but we must also use the correct
* ap number for every access.
*/
struct cortex_a_common *cortex_a = target_to_cortex_a(target);
struct armv7a_common *armv7a = &cortex_a->armv7a_common;
struct adiv5_dap *swjdp = armv7a->arm.dap;
+
int i;
int retval = ERROR_OK;
- uint32_t didr, ctypr, ttypr, cpuid, dbg_osreg;
+ uint32_t didr, cpuid, dbg_osreg;
retval = dap_dp_init(swjdp);
if (retval != ERROR_OK) {
armv7a->debug_base = target->dbgbase;
retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_CPUID, &cpuid);
- if (retval != ERROR_OK)
- return retval;
-
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_CPUID, &cpuid);
- if (retval != ERROR_OK) {
- LOG_DEBUG("Examine %s failed", "CPUID");
- return retval;
- }
-
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_CTYPR, &ctypr);
- if (retval != ERROR_OK) {
- LOG_DEBUG("Examine %s failed", "CTYPR");
- return retval;
- }
-
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_TTYPR, &ttypr);
+ armv7a->debug_base + CPUDBG_DIDR, &didr);
if (retval != ERROR_OK) {
- LOG_DEBUG("Examine %s failed", "TTYPR");
+ LOG_DEBUG("Examine %s failed", "DIDR");
return retval;
}
retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DIDR, &didr);
+ armv7a->debug_base + CPUDBG_CPUID, &cpuid);
if (retval != ERROR_OK) {
- LOG_DEBUG("Examine %s failed", "DIDR");
+ LOG_DEBUG("Examine %s failed", "CPUID");
return retval;
}
- LOG_DEBUG("cpuid = 0x%08" PRIx32, cpuid);
- LOG_DEBUG("ctypr = 0x%08" PRIx32, ctypr);
- LOG_DEBUG("ttypr = 0x%08" PRIx32, ttypr);
LOG_DEBUG("didr = 0x%08" PRIx32, didr);
+ LOG_DEBUG("cpuid = 0x%08" PRIx32, cpuid);
- cortex_a->cpuid = cpuid;
- cortex_a->ctypr = ctypr;
- cortex_a->ttypr = ttypr;
cortex_a->didr = didr;
+ cortex_a->cpuid = cpuid;
- /* Unlocking the debug registers */
- if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT ==
- CORTEX_A15_PARTNUM) {
-
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_OSLAR,
- 0);
-
- if (retval != ERROR_OK)
- return retval;
+ retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg);
+ if (retval != ERROR_OK)
+ return retval;
+ LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg);
+ if ((dbg_osreg & PRSR_POWERUP_STATUS) == 0) {
+ LOG_ERROR("target->coreid %" PRId32 " powered down!", target->coreid);
+ target->state = TARGET_UNKNOWN; /* TARGET_NO_POWER? */
+ return ERROR_TARGET_INIT_FAILED;
}
- /* Unlocking the debug registers */
- if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT ==
- CORTEX_A7_PARTNUM) {
-
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_OSLAR,
- 0);
- if (retval != ERROR_OK)
- return retval;
+ if (dbg_osreg & PRSR_STICKY_RESET_STATUS)
+ LOG_DEBUG("target->coreid %" PRId32 " was reset!", target->coreid);
- }
+ /* Read DBGOSLSR and check if OSLK is implemented */
retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg);
-
+ armv7a->debug_base + CPUDBG_OSLSR, &dbg_osreg);
if (retval != ERROR_OK)
return retval;
+ LOG_DEBUG("target->coreid %" PRId32 " DBGOSLSR 0x%" PRIx32, target->coreid, dbg_osreg);
- LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg);
+ /* check if OS Lock is implemented */
+ if ((dbg_osreg & OSLSR_OSLM) == OSLSR_OSLM0 || (dbg_osreg & OSLSR_OSLM) == OSLSR_OSLM1) {
+ /* check if OS Lock is set */
+ if (dbg_osreg & OSLSR_OSLK) {
+ LOG_DEBUG("target->coreid %" PRId32 " OSLock set! Trying to unlock", target->coreid);
+
+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_OSLAR,
+ 0);
+ if (retval == ERROR_OK)
+ retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
+ armv7a->debug_base + CPUDBG_OSLSR, &dbg_osreg);
+
+ /* if we fail to access the register or cannot reset the OSLK bit, bail out */
+ if (retval != ERROR_OK || (dbg_osreg & OSLSR_OSLK) != 0) {
+ LOG_ERROR("target->coreid %" PRId32 " OSLock sticky, core not powered?",
+ target->coreid);
+ target->state = TARGET_UNKNOWN; /* TARGET_NO_POWER? */
+ return ERROR_TARGET_INIT_FAILED;
+ }
+ }
+ }
armv7a->arm.core_type = ARM_MODE_MON;
struct target *target)
{
/* examine_first() does a bunch of this */
+ arm_semihosting_init(target);
return ERROR_OK;
}
/* REVISIT allow exporting VFP3 registers ... */
.get_gdb_reg_list = arm_get_gdb_reg_list,
- .read_memory = cortex_a_read_memory,
- .write_memory = cortex_a_write_memory,
+ .read_memory = cortex_a_read_phys_memory,
+ .write_memory = cortex_a_write_phys_memory,
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,