?? arm9tdmi.c
字號:
/* * target/arm9tdmi/arm9tdmi.c: implements arm9tdmi target * * Copyright (C) 2003 2004, Rongkai zhan <zhanrk@163.com> * * 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 *//* $Id: arm9tdmi.c,v 1.3 2004/10/17 13:54:32 zhanrk Exp $ */#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include "jtager.h"#include "jtag.h"#include "target.h"extern core_register_t arm9tdmi_regs[];extern ice_register_t arm9tdmi_ice_regs[];target_t arm9tdmi_target = { .type = TARGET_TYPE_ARM9TDMI, .mode = TARGET_MODE_ARM, .status = TARGET_STATUS_RUNNING, .halt_reason = TARGET_HALTED_NONE, /* * These two pointers are initialized in the function arm9tdmi_setup() */ .regs = &arm9tdmi_regs[0], .ice_regs = &arm9tdmi_ice_regs[0], /* BYPASS register always output 0 */ .bypass = {ARM9TDMI_BYPASS_REG_BITNR, 0, 0}, .idcode = {ARM9TDMI_IDCODE_REG_BITNR, 0, 0}, /* INSTRUCTION register always output b0001 during CAPTURE-DR stage */ .instruction = {ARM9TDMI_INSTRUCTION_REG_BITNR, 0xffffffff, 0x01}, /* The scan path select register always output b10000 during CAPTURE-DR stage. */ .scanpath = {ARM9TDMI_SCANPATH_REG_BITNR, 0x0, 0x10}, /* scan chains of ARM9TDMI */ .sc_num = 3, /* scan chain 0, 1, 2 */ .active_sc = 0, .sc = { {"ARM9TDMI CPU core logic", ARM9TDMI_SCANCHAIN0_BITNR, {0, }, {0, }, NULL}, {"ARM9TDMI CPU core debug subset", ARM9TDMI_SCANCHAIN1_BITNR, {0, }, {0, }, NULL}, {"ARM9TDMI EmbeddedICE-RT logic", ARM9TDMI_SCANCHAIN2_BITNR, {0, }, {0, }, NULL} }, .private = NULL,};/* * arm_halt - Halt the ARM target and make it into the debug mode */int arm9tdmi_halt(void){ u32 status; int success, retval; int temp = 0; if (target->status != TARGET_STATUS_RUNNING) { printf("The target cpu has been halted!\n"); return 0; } /* * We halt the target by setting the DBGRQ bit (bit[1]) of the debug * control register of ARM9TDMI EmbeddedICE-RT logic. We also set the * INTDIS bit (bit[2]) of the ICE debug control register for disabling * the interrupt on the target. * * NOTICE: Do not set DBGACK bit, please. The reason is: * When a system-speed access from debug state occurs, the core will * temporarily drop out of debug state, so DBGACK might go LOW. * But if set the DBGACK bit of the debug control register, * the DBGACK signal will always go HIGH. */ /* select scan chain 2 -- EmbeddedICE-RT */ retval = jtag_select_scanchain(2); if (retval) return retval; retval = jtag_write_ireg(JTAG_INTEST); /* internal test mode */ if (retval) return retval; /* set DBGRQ bit and disable interrupts */ retval = arm9tdmi_ice_write(ARM9TDMI_ICE_DBGCTL, 0x3); if (retval) return retval; /* After sending DBGRQ, Run-Test/Idle state must be entered: */ retval = jtag_write_ireg(JTAG_RESTART); if (retval) return retval; /* Read debug status register to see whether the DBGACK signal * is asserted. If the DBGACK siganl goes HIGH, then the target * has entered the debug state. */ success = 0; printf("Requesting HALT target ..."); fflush(stdout); while (temp++ < 10) { retval = arm9tdmi_ice_read(ARM9TDMI_ICE_DBGSTAT, &status); if (retval) return retval; if (status & 0x01) { /* success */ success = 1; break; } jtag_write_ireg(JTAG_RESTART); printf("."); fflush(stdout); usleep(100); } /* Whatever happens, the DBGRQ bit flag must be cleared */ arm9tdmi_ice_write(ARM9TDMI_ICE_DBGCTL, 0x00); if (success) { printf(" [OK]\n"); target->status = TARGET_STATUS_HALTED; target->halt_reason = TARGET_HALTED_BY_DBGRQ; /* * When the bit[4] of the debug status register of ARM9TDMI * EmbeddedICE-RT logic is HIGH, the ARM9TDMI core has * entered the debug state from THUMB mode. Otherwise the * ARM9TDMI core has entered the debug state from ARM mode. */ printf("The target is halted in "); if (status & 0x10) { printf("THUMB mode.\n"); target->mode = TARGET_MODE_THUMB; } else { printf("ARM mode.\n"); target->mode = TARGET_MODE_ARM; } retval = 0; //retval = arm9tdmi_regs_read(); } else { /* make the TAP controller into the Run-Test/Idle state */ jtag_write_ireg(JTAG_RESTART); printf(" [FAILED]\n"); retval = -ERR_TARGET_HALT_FAILED; } return retval;} /* end of target_halt() *//* * arm9tdmi_exec_instruction - Execute an instruction on the ARM9TDMI core * while in debug state by scan chain 1 * @writein: writein[0] contains the instruction opcode to be executed, * writein[1] contains the data to be inputted. * @readout: used to return the data read out from scan chain 1 * @type: DEBUG_SPEED or SYSTEM_SPEED * * Return Value: the value of BREAKPT signal. * * NOTE: We assume that the target has been halted - the target has * been in debug state. And scan chain 1 has been selected, the INTEST * instruction has been written into the instruction register. * * The bit order of Scan chain 1 for ARM9TDMI core: * * -------------- * | | * | V * | +------------+ * | | bit[66] | ID[0] * | +------------+ * | | | * | | ...... | * | | | * | +------------+ * | | bit[35] | ID[31] * | +------------+ * | | bit[34] | SYSSPPEED * | +------------+ * | | bit[33] | (ARM9TDMI: unused, ARM920T: WPTANDBKPT) * | +------------+ * | | bit[32] | DDEN * | +------------+ * | | bit[31] | DD[31] * | +------------+ * | | | * | | ...... | * | | | * | +------------+ * | | bit[0] | DD[0] * | +------------+ * | | * | | * | V * TDI TDO */int arm9tdmi_exec_instruction(u32 *writein, u32 *readout, int type){ u32 indata[3] = {0, }; u32 outdata[3] = {0, }; int bitnr = arm9tdmi_target.sc[1].bitnr; int temp, retval; /* do a long (67 bit) access */ indata[0] = writein[1]; indata[1] = 0; indata[2] = 0; if (type == SYSTEM_SPEED) indata[1] = 1 << 2; /* need to reverse the bit order for the command */ for (temp = 3; temp < 32; temp ++) { if (writein[0] & (1 << temp)) indata[1] = indata[1] | (1 << (34 - temp)); } for (temp = 0; temp < 3; temp ++) { if (writein[0] & (1 << temp)) indata[2] = indata[2] | (1 << (2 - temp)); } /* * OK, write in and read out * read or write JTAG data register will always change its state * from Update-DR to Run-Test/Idle. Therefore, it will also pulse * DCLK signal. */ retval = jtag_rw_dreg(bitnr, indata, outdata); if (retval) return retval; /* * DD[0] of scan chain 1 is scanned out at first, so there is no * need to reverse the bit order of the readout data. The readout[0] * is just the DD[31:0] - that is we want. */ readout[0] = outdata[0]; return retval;} /* end of arm9tdmi_exec_instruction() *//* * target_restart - Exit from the debug state, and return to * the normal system state. */int arm9tdmi_restart(u32 pc){ if (target->status == TARGET_STATUS_RUNNING) return -ERR_TARGET_IS_RUNNING; if (target->mode == TARGET_MODE_THUMB) { printf("Error: %s: THUMB mode is not yet implemented.\n", __FUNCTION__); return -1; } /* Cancel the DBGRQ and enable interrupts */ jtag_select_scanchain(2); arm9tdmi_ice_write(0x00, 0x00); /* Select scan chain 1 and use INTEST instruction */ jtag_select_scanchain(1); jtag_write_ireg(JTAG_INTEST); /* write the PC into R0 */ arm9tdmi_r0_write(pc); /* MOV PC, R0 = 0xE1A0F000 */ target->sc[1].writein[0] = 0xE1A0F000; target->sc[1].writein[1] = 0; arm9tdmi_exec_instruction(target->sc[1].writein, target->sc[1].readout, DEBUG_SPEED); /* * The penultimate instruction must be scanned in with bit33 set HIGH. * insert NOP instruction: MOV R0, R0 = 0xE1A00000 */ target->sc[1].writein[0] = ARM_NOP; arm9tdmi_exec_instruction(target->sc[1].writein, target->sc[1].readout, SYSTEM_SPEED); /* Write RESTART instruction into the TAP controller. * When the state machine enters the Run-Test/Idle state, * the ARM9TDMI core will revert back to system mode, * and it will resynchronize clock to MCLK. */ jtag_write_ireg(JTAG_RESTART); /* also make TAP controller into Run-Test/Idle state */ enter_next_state(0); /* Run-Test/Idle --> Run-Test/Idle */ target->status = TARGET_STATUS_RUNNING; return 0;} /* end of arm9tdmi_restart() */struct target_operation arm9tdmi_tops = { /* ARM9TDMI EmbeddedICE-RT logic register read/write operations */ .ice_read = arm9tdmi_ice_read, .ice_write = arm9tdmi_ice_write, /* ARM9TDMI cpu core operations */ .halt = arm9tdmi_halt, .restart = arm9tdmi_restart, /* ARM9TDMI core registers read/write operations */ .get_core_state = arm9tdmi_get_core_state, .register_read = arm9tdmi_register_read, .register_write = arm9tdmi_register_write, /* ARM9TDMI target memory read/write operations */ .mem_read8 = arm9tdmi_memory_read8, .mem_write8 = arm9tdmi_memory_write8, .mem_read16 = arm9tdmi_memory_read16, .mem_write16 = arm9tdmi_memory_write16, .mem_read32 = arm9tdmi_memory_read32, .mem_write32 = arm9tdmi_memory_write32,};int arm9tdmi_setup(void){ target = &arm9tdmi_target; t_op = &arm9tdmi_tops; return 0;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -