/*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * * Copyright (C) 2006 by Magnus Lundin * * lundin@mlu.mine.nu * * * * Copyright (C) 2008 by Spencer Oliver * * spen@spen-soft.co.uk * * * * Copyright (C) 2009 by Dirk Behme * * dirk.behme@gmail.com - copy from cortex_m3 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * Cortex-A8(tm) TRM, ARM DDI 0344H * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "cortex_a8.h" #include "target_request.h" #include "target_type.h" /* cli handling */ int cortex_a8_register_commands(struct command_context_s *cmd_ctx); /* forward declarations */ int cortex_a8_target_create(struct target_s *target, Jim_Interp *interp); target_type_t cortexa8_target = { .name = "cortex_a8", .poll = NULL, .arch_state = armv7m_arch_state, .target_request_data = NULL, .halt = NULL, .resume = NULL, .step = NULL, .assert_reset = NULL, .deassert_reset = NULL, .soft_reset_halt = NULL, .get_gdb_reg_list = armv7m_get_gdb_reg_list, .read_memory = cortex_a8_read_memory, .write_memory = cortex_a8_write_memory, .bulk_write_memory = NULL, .checksum_memory = NULL, .blank_check_memory = NULL, .run_algorithm = armv7m_run_algorithm, .add_breakpoint = NULL, .remove_breakpoint = NULL, .add_watchpoint = NULL, .remove_watchpoint = NULL, .register_commands = cortex_a8_register_commands, .target_create = cortex_a8_target_create, .init_target = NULL, .examine = NULL, .quit = NULL }; int cortex_a8_dcc_read(swjdp_common_t *swjdp, uint8_t *value, uint8_t *ctrl) { uint16_t dcrdr; mem_ap_read_buf_u16( swjdp, (uint8_t*)&dcrdr, 1, DCB_DCRDR); *ctrl = (uint8_t)dcrdr; *value = (uint8_t)(dcrdr >> 8); LOG_DEBUG("data 0x%x ctrl 0x%x", *value, *ctrl); /* write ack back to software dcc register * signify we have read data */ if (dcrdr & (1 << 0)) { dcrdr = 0; mem_ap_write_buf_u16( swjdp, (uint8_t*)&dcrdr, 1, DCB_DCRDR); } return ERROR_OK; } int cortex_a8_read_memory(struct target_s *target, u32 address, u32 size, u32 count, uint8_t *buffer) { /* get pointers to arch-specific information */ armv7m_common_t *armv7m = target->arch_info; swjdp_common_t *swjdp = &armv7m->swjdp_info; int retval; /* sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) return ERROR_INVALID_ARGUMENTS; /* cortex_a8 handles unaligned memory access */ switch (size) { case 4: retval = mem_ap_read_buf_u32(swjdp, buffer, 4 * count, address); break; case 2: retval = mem_ap_read_buf_u16(swjdp, buffer, 2 * count, address); break; case 1: retval = mem_ap_read_buf_u8(swjdp, buffer, count, address); break; default: LOG_ERROR("BUG: we shouldn't get here"); exit(-1); } return retval; } int cortex_a8_write_memory(struct target_s *target, u32 address, u32 size, u32 count, uint8_t *buffer) { /* get pointers to arch-specific information */ armv7m_common_t *armv7m = target->arch_info; swjdp_common_t *swjdp = &armv7m->swjdp_info; int retval; /* sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) return ERROR_INVALID_ARGUMENTS; switch (size) { case 4: retval = mem_ap_write_buf_u32(swjdp, buffer, 4 * count, address); break; case 2: retval = mem_ap_write_buf_u16(swjdp, buffer, 2 * count, address); break; case 1: retval = mem_ap_write_buf_u8(swjdp, buffer, count, address); break; default: LOG_ERROR("BUG: we shouldn't get here"); exit(-1); } return retval; } int cortex_a8_handle_target_request(void *priv) { target_t *target = priv; if (!target_was_examined(target)) return ERROR_OK; armv7m_common_t *armv7m = target->arch_info; swjdp_common_t *swjdp = &armv7m->swjdp_info; if (!target->dbg_msg_enabled) return ERROR_OK; if (target->state == TARGET_RUNNING) { uint8_t data; uint8_t ctrl; cortex_a8_dcc_read(swjdp, &data, &ctrl); /* check if we have data */ if (ctrl & (1 << 0)) { u32 request; /* we assume target is quick enough */ request = data; cortex_a8_dcc_read(swjdp, &data, &ctrl); request |= (data << 8); cortex_a8_dcc_read(swjdp, &data, &ctrl); request |= (data << 16); cortex_a8_dcc_read(swjdp, &data, &ctrl); request |= (data << 24); target_request(target, request); } } return ERROR_OK; } int cortex_a8_init_arch_info(target_t *target, cortex_a8_common_t *cortex_a8, jtag_tap_t *tap) { armv7m_common_t *armv7m; armv7m = &cortex_a8->armv7m; /* prepare JTAG information for the new target */ cortex_a8->jtag_info.tap = tap; cortex_a8->jtag_info.scann_size = 4; armv7m->swjdp_info.dp_select_value = -1; armv7m->swjdp_info.ap_csw_value = -1; armv7m->swjdp_info.ap_tar_value = -1; armv7m->swjdp_info.jtag_info = &cortex_a8->jtag_info; /* initialize arch-specific breakpoint handling */ cortex_a8->common_magic = CORTEX_A8_COMMON_MAGIC; cortex_a8->arch_info = NULL; /* register arch-specific functions */ armv7m->examine_debug_reason = NULL; armv7m->pre_debug_entry = NULL; armv7m->post_debug_entry = NULL; armv7m->pre_restore_context = NULL; armv7m->post_restore_context = NULL; armv7m_init_arch_info(target, armv7m); armv7m->arch_info = cortex_a8; armv7m->load_core_reg_u32 = NULL; armv7m->store_core_reg_u32 = NULL; target_register_timer_callback(cortex_a8_handle_target_request, 1, 1, target); return ERROR_OK; } int cortex_a8_target_create(struct target_s *target, Jim_Interp *interp) { cortex_a8_common_t *cortex_a8 = calloc(1,sizeof(cortex_a8_common_t)); cortex_a8_init_arch_info(target, cortex_a8, target->tap); return ERROR_OK; } int cortex_a8_register_commands(struct command_context_s *cmd_ctx) { int retval; retval = armv7m_register_commands(cmd_ctx); register_command(cmd_ctx, NULL, "cortex_a8", NULL, COMMAND_ANY, "cortex_a8 specific commands"); return retval; }