📄 memory.c
字号:
/* * target/arm9tdmi/memory.c: implements the ARM9TDMI target's memory read/write * operations. * * Copyright (C) 2003, 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: memory.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"/* * NOTE: this function has very slow read speed. */int arm9tdmi_memory_read8(u8 *buf, u32 address, u32 length){ int i, retval; u32 addr = address; scan_chain_t *sc1 = &arm9tdmi_target.sc[1]; if ((buf == NULL) || (length == 0)) return -ERR_INVALID_PARAM; else if (target->status == TARGET_STATUS_RUNNING) return -ERR_TARGET_IS_RUNNING; else if (target->mode == TARGET_MODE_THUMB) return -ERR_TARGET_IN_THUMB_MODE; i = retval = 0; /* * Select scan chain 1, and use INTEST instruction to make scan * chain 1 into the internal test mode. */ retval = jtag_select_scanchain(1); if (retval) return retval; retval = jtag_write_ireg(JTAG_INTEST); if (retval) return retval; /* read one byte each time */ while (i < length) { /* * Zero R0 * If not doing this step, things are wrong. I don't know why? */ sc1->writein[0] = 0xE5900000; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* scan in the address */ sc1->writein[0] = ARM_NOP; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* * Load R0 with the address to read. * LDR R0, [R0] = 0xE5900000 */ sc1->writein[0] = 0xE5900000; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* scan in the address */ sc1->writein[0] = ARM_NOP; sc1->writein[1] = addr; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* LDRB R1, [R0] = 1110 0101 1101 0000 0001 0000 0000 0000 */ sc1->writein[0] = 0xE5D01000; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; arm9tdmi_exec_instruction(sc1->writein, sc1->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); /* * Now, the ARM9TDMI core re-entered the debug state. * Before the debug session continues, we must load the * TAP controller with the INTEST instruction. We can use * the instruction "STR R1, [R1]" running at debug-speed * to read out the contents of register R1. */ jtag_write_ireg(JTAG_INTEST); /* STR R1, [R1] = 1110 0101 1000 0001 0001 0000 0000 0000 */ sc1->writein[0] = 0xE5811000; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); buf[i] = (u8)(sc1->readout[0] & 0x000000FF); i++; addr++; } /* end of while (i < length) */ return 0;} /* end of arm9tdmi_memory_read8(...) *//* * NOTE: this function has very slow write speed. */int arm9tdmi_memory_write8(u8 *buf, u32 address, u32 length){ int i, retval; u32 addr = address; scan_chain_t *sc1 = &arm9tdmi_target.sc[1]; if ((buf == NULL) || (length == 0)) return -ERR_INVALID_PARAM; else if (target->status == TARGET_STATUS_RUNNING) return -ERR_TARGET_IS_RUNNING; else if (target->mode == TARGET_MODE_THUMB) return -ERR_TARGET_IN_THUMB_MODE; retval = i = 0; /* * Select scan chain 1, and use INTEST instruction to make scan * chain 1 into the internal test mode. */ retval = jtag_select_scanchain(1); if (retval) return retval; retval = jtag_write_ireg(JTAG_INTEST); if (retval) return retval; /* write one byte each time */ while (i < length) { /* * Zero R0 * If not doing this step, things are wrong. I don't know why? */ sc1->writein[0] = 0xE5900000; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* scan in the address */ sc1->writein[0] = ARM_NOP; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* * Load R0 with the address. * LDR R0, [R0] = 0xE5900000 */ sc1->writein[0] = 0xE5900000; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* scan in the address */ sc1->writein[0] = ARM_NOP; sc1->writein[1] = addr; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* * Zero R1 */ sc1->writein[0] = 0xE5911000; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* scan in the data */ sc1->writein[0] = ARM_NOP; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* * Load R1 with the data to write. * LDR R1, [R1] = 1110 0101 1001 0001 0001 0000 0000 0000 */ sc1->writein[0] = 0xE5911000; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* scan in the data */ sc1->writein[0] = ARM_NOP; sc1->writein[1] = (u32)buf[i]; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* STRB R1, [R0] = 1110 0101 1100 0000 0001 0000 0000 0000 */ sc1->writein[0] = 0xE5C01000; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; arm9tdmi_exec_instruction(sc1->writein, sc1->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); /* * Now, the ARM9TDMI core re-entered the debug state. * Before the debug session continues, we must load the * TAP controller with the INTEST instruction. */ jtag_write_ireg(JTAG_INTEST); i++; addr++; } /* end of while (i < length) */ return 0;} /* end of arm9tdmi_memory_write8(...) *//* * NOTE: this function has very slow read speed. */int arm9tdmi_memory_read16(u16 *buf, u32 address, u32 length){ int i, retval; u32 addr = address; scan_chain_t *sc1 = &arm9tdmi_target.sc[1]; if ((buf == NULL) || (length == 0)) return -ERR_INVALID_PARAM; else if (target->status == TARGET_STATUS_RUNNING) return -ERR_TARGET_IS_RUNNING; else if (target->mode == TARGET_MODE_THUMB) return -ERR_TARGET_IN_THUMB_MODE; addr &= 0xFFFFFFFE; /* align address with half word boundary */ retval = i = 0; /* * Select scan chain 1, and use INTEST instruction to make scan * chain 1 into the internal test mode. */ retval = jtag_select_scanchain(1); if (retval) return retval; retval = jtag_write_ireg(JTAG_INTEST); if (retval) return retval; /* read one half-word each time */ while (i < length) { /* * Zero R0 -- It is needed !!! * If not doing this step, things are wrong. I don't know why? */ sc1->writein[0] = 0xE5900000; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* scan in the address */ sc1->writein[0] = ARM_NOP; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* * Load R0 with the address to read. * LDR R0, [R0] = 0xE5900000 */ sc1->writein[0] = 0xE5900000; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* scan in the address */ sc1->writein[0] = ARM_NOP; sc1->writein[1] = addr; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); /* LDRH R1, [R0] = 1110 0001 1101 0000 0001 0000 1011 0000 */ sc1->writein[0] = 0xE1D010B0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; arm9tdmi_exec_instruction(sc1->writein, sc1->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); /* * Now, the ARM9TDMI core re-entered the debug state. * Before the debug session continues, we must load the * TAP controller with the INTEST instruction. We can use * the instruction "STR R1, [R1]" running at debug-speed * to read out the contents of register R1. */ jtag_write_ireg(JTAG_INTEST); /* STR R1, [R1] = 1110 0101 1000 0001 0001 0000 0000 0000 */ sc1->writein[0] = 0xE5811000; sc1->writein[1] = 0; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); sc1->writein[0] = ARM_NOP; arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); arm9tdmi_exec_instruction(sc1->writein, sc1->readout, DEBUG_SPEED); buf[i] = (u16)(sc1->readout[0] & 0x0000FFFF); i++; addr += 2; } /* end of while (i < length) */ return 0;} /* end of arm9tdmi_read16(...) *//* * NOTE: this function has very slow write speed. */int arm9tdmi_memory_write16(u16 *buf, u32 address, u32 length){ int i, retval; u32 addr = address; scan_chain_t *sc1 = &arm9tdmi_target.sc[1]; if ((buf == NULL) || (length == 0))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -