📄 memory.c
字号:
/* * target/arm7tdmi/memory.c: implements the ARM7TDMI 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"int arm7tdmi_memory_read8(u8 *buf, u32 address, u32 length){ int i, retval; u32 addr = address; scan_chain_t *sc1 = &arm7tdmi_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; arm7tdmi_ice_set_breakpt(); /* * 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) { /* * Load R0 with the address to read. * LDR R0, PC+xx = 0xE59F0000 */ sc1->writein[0] = 0xE59F0000; sc1->writein[1] = DEBUG_SPEED; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = ARM_NOP; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = addr; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = ARM_NOP; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); /* two NOPs are needed, and i don't know why? */ arm7tdmi_exec_instruction(sc1->writein, sc1->readout); arm7tdmi_exec_instruction(sc1->writein, sc1->readout); /* NOP with bit33 set HIGH */ sc1->writein[0] = ARM_NOP; sc1->writein[1] = SYSTEM_SPEED; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); /* LDRB R1, [R0] = 1110 0101 1101 0000 0001 0000 0000 0000 */ sc1->writein[0] = 0xE5D01000; sc1->writein[1] = DEBUG_SPEED; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); /* Write RESTART instruction into the TAP controller. * When the state machine enters the Run-Test/Idle state, * the ARM7TDMI core will revert back to system mode, * and it will resynchronize clock to MCLK. */ jtag_write_ireg(JTAG_RESTART); /* * Now, the ARM7TDMI 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_select_scanchain(1); jtag_write_ireg(JTAG_INTEST); /* STR R1, [R1] = 1110 0101 1000 0001 0001 0000 0000 0000 */ sc1->writein[0] = 0xE5811000; sc1->writein[1] = DEBUG_SPEED; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = ARM_NOP; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); arm7tdmi_exec_instruction(sc1->writein, sc1->readout); arm7tdmi_exec_instruction(sc1->writein, sc1->readout); buf[i] = (u8)(sc1->readout[0] & 0x000000FF); i++; addr++; } /* end of while (i < length) */ /* * Finally, clear breakpt ... */ arm7tdmi_ice_clear_breakpt(); return 0;} /* end of arm7tdmi_memory_read8(...) */int arm7tdmi_memory_write8(u8 *buf, u32 address, u32 length){ int i, retval; u32 addr = address; scan_chain_t *sc1 = &arm7tdmi_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; arm7tdmi_ice_set_breakpt(); /* * 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) { /* * Load R0 with the address to read. * LDR R0, PC+xx = 0xE59F0000 */ sc1->writein[0] = 0xE59F0000; sc1->writein[1] = DEBUG_SPEED; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = ARM_NOP; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = addr; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = ARM_NOP; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); /* * Clear R1 to zero. If not doing this step, when i write * even number into R1, i always read back wrong result * from R1. Damn it. * LDR R1, [R1] = 1110 0101 1001 0001 0001 0000 0000 0000 */ sc1->writein[0] = 0xE5911000; sc1->writein[1] = DEBUG_SPEED; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = ARM_NOP; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = 0; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = ARM_NOP; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); /* * 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] = DEBUG_SPEED; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = ARM_NOP; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = (u32)buf[i]; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = ARM_NOP; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); /* two NOPs are needed, and i don't know why? */ arm7tdmi_exec_instruction(sc1->writein, sc1->readout); arm7tdmi_exec_instruction(sc1->writein, sc1->readout); /* NOP with bit33 set HIGH */ sc1->writein[0] = ARM_NOP; sc1->writein[1] = SYSTEM_SPEED; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); /* STRB R1, [R0] = 1110 0101 1100 0000 0001 0000 0000 0000 */ sc1->writein[0] = 0xE5C01000; sc1->writein[1] = DEBUG_SPEED; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); /* Write RESTART instruction into the TAP controller. * When the state machine enters the Run-Test/Idle state, * the ARM7TDMI core will revert back to system mode, * and it will resynchronize clock to MCLK. */ jtag_write_ireg(JTAG_RESTART); /* * Now, the ARM7TDMI core re-entered the debug state. * Before the debug session continues, we must load the * TAP controller with the INTEST instruction. */ jtag_select_scanchain(1); jtag_write_ireg(JTAG_INTEST); i++; addr++; } /* end of while (i < length) */ /* * Finally, clear breakpt ... */ arm7tdmi_ice_clear_breakpt(); return 0;} /* end of arm7tdmi_memory_write8(...) *//* * NOTE: this function has very slow read speed. */int arm7tdmi_memory_read16(u16 *buf, u32 address, u32 length){ int i, retval; u32 addr = address; scan_chain_t *sc1 = &arm7tdmi_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; arm7tdmi_ice_set_breakpt(); /* * 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) { /* * Load R0 with the address to read. * LDR R0, PC+xx = 0xE59F0000 */ sc1->writein[0] = 0xE59F0000; sc1->writein[1] = DEBUG_SPEED; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = ARM_NOP; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = addr; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = ARM_NOP; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); /* two NOPs are needed, and i don't know why? */ arm7tdmi_exec_instruction(sc1->writein, sc1->readout); arm7tdmi_exec_instruction(sc1->writein, sc1->readout); /* NOP with bit33 set HIGH */ sc1->writein[0] = ARM_NOP; sc1->writein[1] = SYSTEM_SPEED; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); /* LDRH R1, [R0] = 1110 0001 1101 0000 0001 0000 1011 0000 */ sc1->writein[0] = 0xE1D010B0; sc1->writein[1] = DEBUG_SPEED; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); /* Write RESTART instruction into the TAP controller. * When the state machine enters the Run-Test/Idle state, * the ARM7TDMI core will revert back to system mode, * and it will resynchronize clock to MCLK. */ jtag_write_ireg(JTAG_RESTART); /* * Now, the ARM7TDMI 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_select_scanchain(1); jtag_write_ireg(JTAG_INTEST); /* STR R1, [R1] = 1110 0101 1000 0001 0001 0000 0000 0000 */ sc1->writein[0] = 0xE5811000; sc1->writein[1] = DEBUG_SPEED; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = ARM_NOP; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); arm7tdmi_exec_instruction(sc1->writein, sc1->readout); arm7tdmi_exec_instruction(sc1->writein, sc1->readout); buf[i] = (u16)(sc1->readout[0] & 0x0000FFFF); i++; addr += 2; } /* end of while (i < length) */ /* * Finally, clear breakpt ... */ arm7tdmi_ice_clear_breakpt(); return 0;} /* end of arm7tdmi_read16(...) *//* * NOTE: this function has very slow write speed. */int arm7tdmi_memory_write16(u16 *buf, u32 address, u32 length){ int i, retval; u32 addr = address; scan_chain_t *sc1 = &arm7tdmi_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; arm7tdmi_ice_set_breakpt(); /* * 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 half-word each time */ while (i < length) { /* * Load R0 with the address to read. * LDR R0, PC+xx = 0xE59F0000 */ sc1->writein[0] = 0xE59F0000; sc1->writein[1] = DEBUG_SPEED; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = ARM_NOP; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = addr; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); sc1->writein[0] = ARM_NOP; arm7tdmi_exec_instruction(sc1->writein, sc1->readout); /* * Clear R1 to zero. If not doing this step, when i write * even number into R1, i always read back wrong result * from R1. Damn it.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -