Browse Source

cortex a9: merge cortex a9 and a8 code

better to keep this in a single file.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
tags/v0.5.0-rc1
Øyvind Harboe 13 years ago
parent
commit
fc574c64bb
6 changed files with 289 additions and 2512 deletions
  1. +1
    -3
      src/target/Makefile.am
  2. +286
    -114
      src/target/cortex_a8.c
  3. +2
    -1
      src/target/cortex_a8.h
  4. +0
    -2303
      src/target/cortex_a9.c
  5. +0
    -89
      src/target/cortex_a9.h
  6. +0
    -2
      src/target/target.c

+ 1
- 3
src/target/Makefile.am View File

@@ -73,8 +73,7 @@ ARMV7_SRC = \
armv7m.c \
cortex_m3.c \
armv7a.c \
cortex_a8.c \
cortex_a9.c
cortex_a8.c

ARM_DEBUG_SRC = \
arm_dpm.c \
@@ -137,7 +136,6 @@ noinst_HEADERS = \
breakpoints.h \
cortex_m3.h \
cortex_a8.h \
cortex_a9.h \
embeddedice.h \
etb.h \
etm.h \


+ 286
- 114
src/target/cortex_a8.c View File

@@ -30,6 +30,7 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* Cortex-A8(tm) TRM, ARM DDI 0344H *
* Cortex-A9(tm) TRM, ARM DDI 0407F *
* *
***************************************************************************/
#ifdef HAVE_CONFIG_H
@@ -692,7 +693,7 @@ static int cortex_a8_poll(struct target *target)
}
cortex_a8->cpudbg_dscr = dscr;

if ((dscr & 0x3) == 0x3)
if (DSCR_RUN_MODE(dscr) == (DSCR_CORE_HALTED | DSCR_CORE_RESTARTED))
{
if (prev_target_state != TARGET_HALTED)
{
@@ -722,7 +723,7 @@ static int cortex_a8_poll(struct target *target)
}
}
}
else if ((dscr & 0x3) == 0x2)
else if (DSCR_RUN_MODE(dscr) == DSCR_CORE_RESTARTED)
{
target->state = TARGET_RUNNING;
}
@@ -747,7 +748,7 @@ static int cortex_a8_halt(struct target *target)
* and then wait for the core to be halted.
*/
retval = mem_ap_sel_write_atomic_u32(swjdp, swjdp_debugap,
armv7a->debug_base + CPUDBG_DRCR, 0x1);
armv7a->debug_base + CPUDBG_DRCR, DRCR_HALT);
if (retval != ERROR_OK)
return retval;

@@ -870,14 +871,30 @@ static int cortex_a8_resume(struct target *target, int current,
}

#endif
/* Restart core and wait for it to be started
* NOTE: this clears DSCR_ITR_EN and other bits.

/*
* Restart core and wait for it to be started. Clear ITRen and sticky
* exception flags: see ARMv7 ARM, C5.9.
*
* REVISIT: for single stepping, we probably want to
* disable IRQs by default, with optional override...
*/

retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
armv7a->debug_base + CPUDBG_DSCR, &dscr);
if (retval != ERROR_OK)
return retval;

if ((dscr & DSCR_INSTR_COMP) == 0)
LOG_ERROR("DSCR InstrCompl must be set before leaving debug!");

retval = mem_ap_sel_write_atomic_u32(swjdp, swjdp_debugap,
armv7a->debug_base + CPUDBG_DRCR, 0x2);
armv7a->debug_base + CPUDBG_DSCR, dscr & ~DSCR_ITR_EN);
if (retval != ERROR_OK)
return retval;

retval = mem_ap_sel_write_atomic_u32(swjdp, swjdp_debugap,
armv7a->debug_base + CPUDBG_DRCR, DRCR_RESTART | DRCR_CLEAR_EXCEPTIONS);
if (retval != ERROR_OK)
return retval;

@@ -1443,32 +1460,101 @@ static int cortex_a8_read_phys_memory(struct target *target,
uint32_t address, uint32_t size,
uint32_t count, uint8_t *buffer)
{
struct armv7a_common *armv7a = target_to_armv7a(target);
struct adiv5_dap *swjdp = &armv7a->dap;
int retval = ERROR_INVALID_ARGUMENTS;

/* cortex_a8 handles unaligned memory access */

// ??? dap_ap_select(swjdp, swjdp_memoryap);
LOG_DEBUG("Reading memory at real address 0x%x; size %d; count %d", address, size, count);
if (count && buffer) {
switch (size) {
case 4:
retval = mem_ap_sel_read_buf_u32(swjdp, swjdp_memoryap,
buffer, 4 * count, address);
break;
case 2:
retval = mem_ap_sel_read_buf_u16(swjdp, swjdp_memoryap,
buffer, 2 * count, address);
break;
case 1:
retval = mem_ap_sel_read_buf_u8(swjdp, swjdp_memoryap,
buffer, count, address);
break;
}
}
struct armv7a_common *armv7a = target_to_armv7a(target);
struct adiv5_dap *swjdp = &armv7a->dap;
int retval = ERROR_INVALID_ARGUMENTS;
uint8_t apsel = swjdp->apsel;

LOG_DEBUG("Reading memory at real address 0x%x; size %d; count %d", address, size, count);

if (count && buffer) {

if ( apsel == swjdp_memoryap ) {

/* read memory through AHB-AP */

switch (size) {
case 4:
retval = mem_ap_sel_read_buf_u32(swjdp, swjdp_memoryap,
buffer, 4 * count, address);
break;
case 2:
retval = mem_ap_sel_read_buf_u16(swjdp, swjdp_memoryap,
buffer, 2 * count, address);
break;
case 1:
retval = mem_ap_sel_read_buf_u8(swjdp, swjdp_memoryap,
buffer, count, address);
break;
}

return retval;
} else {

/* read memory through APB-AP */

uint32_t saved_r0, saved_r1;
int nbytes = count * size;
uint32_t data;
int enabled = 0;

if (target->state != TARGET_HALTED)
{
LOG_WARNING("target not halted");
return ERROR_TARGET_NOT_HALTED;
}

retval = cortex_a8_mmu(target, &enabled);
if (retval != ERROR_OK)
return retval;

if (enabled)
{
LOG_WARNING("Reading physical memory through APB with MMU enabled is not yet implemented");
return ERROR_TARGET_FAILURE;
}

/* 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;
}

static int cortex_a8_read_memory(struct target *target, uint32_t address,
@@ -1480,7 +1566,6 @@ static int cortex_a8_read_memory(struct target *target, uint32_t address,

/* cortex_a8 handles unaligned memory access */

// ??? dap_ap_select(swjdp, swjdp_memoryap);
LOG_DEBUG("Reading memory at address 0x%x; size %d; count %d", address, size, count);
retval = cortex_a8_mmu(target, &enabled);
if (retval != ERROR_OK)
@@ -1504,88 +1589,162 @@ static int cortex_a8_write_phys_memory(struct target *target,
uint32_t address, uint32_t size,
uint32_t count, uint8_t *buffer)
{
struct armv7a_common *armv7a = target_to_armv7a(target);
struct adiv5_dap *swjdp = &armv7a->dap;
int retval = ERROR_INVALID_ARGUMENTS;

// ??? dap_ap_select(swjdp, swjdp_memoryap);

LOG_DEBUG("Writing memory to real address 0x%x; size %d; count %d", address, size, count);
if (count && buffer) {
switch (size) {
case 4:
retval = mem_ap_sel_write_buf_u32(swjdp, swjdp_memoryap,
buffer, 4 * count, address);
break;
case 2:
retval = mem_ap_sel_write_buf_u16(swjdp, swjdp_memoryap,
buffer, 2 * count, address);
break;
case 1:
retval = mem_ap_sel_write_buf_u8(swjdp, swjdp_memoryap,
buffer, count, address);
break;
}
}
struct armv7a_common *armv7a = target_to_armv7a(target);
struct adiv5_dap *swjdp = &armv7a->dap;
int retval = ERROR_INVALID_ARGUMENTS;
uint8_t apsel = swjdp->apsel;

LOG_DEBUG("Writing memory to real address 0x%x; size %d; count %d", address, size, count);

if (count && buffer) {

if ( apsel == swjdp_memoryap ) {

/* write memory through AHB-AP */

switch (size) {
case 4:
retval = mem_ap_sel_write_buf_u32(swjdp, swjdp_memoryap,
buffer, 4 * count, address);
break;
case 2:
retval = mem_ap_sel_write_buf_u16(swjdp, swjdp_memoryap,
buffer, 2 * count, address);
break;
case 1:
retval = mem_ap_sel_write_buf_u8(swjdp, swjdp_memoryap,
buffer, count, address);
break;
}

/* REVISIT this op is generic ARMv7-A/R stuff */
if (retval == ERROR_OK && target->state == TARGET_HALTED)
{
struct arm_dpm *dpm = armv7a->armv4_5_common.dpm;

retval = dpm->prepare(dpm);
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-A8 has fixed 64 byte line length.
*
* REVISIT per ARMv7, these may trigger watchpoints ...
*/

/* invalidate I-Cache */
if (armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
{
/* ICIMVAU - Invalidate Cache single entry
* with MVA to PoU
* MCR p15, 0, r0, c7, c5, 1
*/
for (uint32_t cacheline = address;
cacheline < address + size * count;
cacheline += 64) {
retval = dpm->instr_write_data_r0(dpm,
ARMV4_5_MCR(15, 0, 0, 7, 5, 1),
cacheline);
if (retval != ERROR_OK)
return retval;
}
}

/* invalidate D-Cache */
if (armv7a->armv4_5_mmu.armv4_5_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 = address;
cacheline < address + size * count;
cacheline += 64) {
retval = dpm->instr_write_data_r0(dpm,
ARMV4_5_MCR(15, 0, 0, 7, 6, 1),
cacheline);
if (retval != ERROR_OK)
return retval;
}
}

/* (void) */ dpm->finish(dpm);
}
} else {

return retval;
/* write memory through APB-AP */

uint32_t saved_r0, saved_r1;
int nbytes = count * size;
uint32_t data;
int enabled = 0;

if (target->state != TARGET_HALTED)
{
LOG_WARNING("target not halted");
return ERROR_TARGET_NOT_HALTED;
}

retval = cortex_a8_mmu(target, &enabled);
if (retval != ERROR_OK)
return retval;

if (enabled)
{
LOG_WARNING("Writing physical memory through APB with MMU enabled is not yet implemented");
return ERROR_TARGET_FAILURE;
}

/* 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;
}
}


/* REVISIT this op is generic ARMv7-A/R stuff */
if (retval == ERROR_OK && target->state == TARGET_HALTED)
{
struct arm_dpm *dpm = armv7a->armv4_5_common.dpm;

retval = dpm->prepare(dpm);
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-A8 has fixed 64 byte line length.
*
* REVISIT per ARMv7, these may trigger watchpoints ...
*/

/* invalidate I-Cache */
if (armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
{
/* ICIMVAU - Invalidate Cache single entry
* with MVA to PoU
* MCR p15, 0, r0, c7, c5, 1
*/
for (uint32_t cacheline = address;
cacheline < address + size * count;
cacheline += 64) {
retval = dpm->instr_write_data_r0(dpm,
ARMV4_5_MCR(15, 0, 0, 7, 5, 1),
cacheline);
if (retval != ERROR_OK)
return retval;
}
}

/* invalidate D-Cache */
if (armv7a->armv4_5_mmu.armv4_5_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 = address;
cacheline < address + size * count;
cacheline += 64) {
retval = dpm->instr_write_data_r0(dpm,
ARMV4_5_MCR(15, 0, 0, 7, 6, 1),
cacheline);
if (retval != ERROR_OK)
return retval;
}
}

/* (void) */ dpm->finish(dpm);
}

return retval;
}

static int cortex_a8_write_memory(struct target *target, uint32_t address,
@@ -1595,8 +1754,6 @@ static int cortex_a8_write_memory(struct target *target, uint32_t address,
uint32_t virt, phys;
int retval;

// ??? dap_ap_select(swjdp, swjdp_memoryap);

LOG_DEBUG("Writing memory to address 0x%x; size %d; count %d", address, size, count);
retval = cortex_a8_mmu(target, &enabled);
if (retval != ERROR_OK)
@@ -1724,6 +1881,21 @@ static int cortex_a8_examine_first(struct target *target)
if (retval != ERROR_OK)
return retval;

#if 0
/*
* FIXME: assuming omap4430
*
* APB DBGBASE reads 0x80040000, but this points to an empty ROM table.
* 0x80000000 is cpu0 coresight region
*/
if (target->coreid > 3) {
LOG_ERROR("cortex_a8 supports up to 4 cores");
return ERROR_INVALID_ARGUMENTS;
}
armv7a->debug_base = 0x80000000 |
((target->coreid & 0x3) << CORTEX_A8_PADDRDBG_CPU_SHIFT);
#endif

retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
armv7a->debug_base + CPUDBG_CPUID, &cpuid);
if (retval != ERROR_OK)


+ 2
- 1
src/target/cortex_a8.h View File

@@ -33,7 +33,6 @@

#define CORTEX_A8_COMMON_MAGIC 0x411fc082

/* See Cortex-A8 TRM section 12.5 */
#define CPUDBG_CPUID 0xD00
#define CPUDBG_CTYPR 0xD04
#define CPUDBG_TTYPR 0xD0C
@@ -43,6 +42,8 @@
#define BRP_NORMAL 0
#define BRP_CONTEXT 1

#define CORTEX_A8_PADDRDBG_CPU_SHIFT 13

struct cortex_a8_brp
{
int used;


+ 0
- 2303
src/target/cortex_a9.c
File diff suppressed because it is too large
View File


+ 0
- 89
src/target/cortex_a9.h View File

@@ -1,89 +0,0 @@
/***************************************************************************
* 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. *
***************************************************************************/
#ifndef CORTEX_A9_H
#define CORTEX_A9_H

#include "armv7a.h"

#define CORTEX_A9_COMMON_MAGIC 0x411fc082

#define CPUDBG_CPUID 0xD00
#define CPUDBG_CTYPR 0xD04
#define CPUDBG_TTYPR 0xD0C
#define CPUDBG_LOCKACCESS 0xFB0
#define CPUDBG_LOCKSTATUS 0xFB4

#define BRP_NORMAL 0
#define BRP_CONTEXT 1

#define CORTEX_A9_PADDRDBG_CPU_SHIFT 13

struct cortex_a9_brp
{
int used;
int type;
uint32_t value;
uint32_t control;
uint8_t BRPn;
};

struct cortex_a9_common
{
int common_magic;
struct arm_jtag jtag_info;

/* Context information */
uint32_t cpudbg_dscr;

/* Saved cp15 registers */
uint32_t cp15_control_reg;

/* Breakpoint register pairs */
int brp_num_context;
int brp_num;
int brp_num_available;
struct cortex_a9_brp *brp_list;

/* Use cortex_a9_read_regs_through_mem for fast register reads */
int fast_reg_read;

/* Flag that helps to resolve what ttb to use: user or kernel */
int current_address_mode;

struct armv7a_common armv7a_common;
};

static inline struct cortex_a9_common *
target_to_cortex_a9(struct target *target)
{
return container_of(target->arch_info, struct cortex_a9_common,
armv7a_common.armv4_5_common);
}

#endif /* CORTEX_A9_H */

+ 0
- 2
src/target/target.c View File

@@ -70,7 +70,6 @@ extern struct target_type dragonite_target;
extern struct target_type xscale_target;
extern struct target_type cortexm3_target;
extern struct target_type cortexa8_target;
extern struct target_type cortexa9_target;
extern struct target_type arm11_target;
extern struct target_type mips_m4k_target;
extern struct target_type avr_target;
@@ -93,7 +92,6 @@ static struct target_type *target_types[] =
&xscale_target,
&cortexm3_target,
&cortexa8_target,
&cortexa9_target,
&arm11_target,
&mips_m4k_target,
&avr_target,


Loading…
Cancel
Save