?? 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$ */
#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 + -