⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memory.c

📁 一个简易调试器(支持ARM7TDMI)
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * 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"

/*
 * 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 "STM R9, {R1-R8}" running at debug-speed
		 * to read out the contents of registers R1-R8.
		 */
		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.
		 * 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);
		
		/* STRH R1, [R0] = 1110 0001 1100 0000 0001 0000 1011 0000 */
		sc1->writein[0] = 0xE1C010B0;
		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 "STM R9, {R1-R8}" running at debug-speed
		 * to read out the contents of registers R1-R8.
		 */
		jtag_select_scanchain(1);
		jtag_write_ireg(JTAG_INTEST);
		
		i++;
		addr += 2;
	} /* end of while (i < length) */

	/*
	 * Finally, clear breakpt ...
	 */
	arm7tdmi_ice_clear_breakpt();
	return 0;
} /* end of arm7tdmi_write16(...) */

int arm7tdmi_memory_read32(u32 *buf, u32 address, u32 length)
{
	int i, lines, 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 &= 0xFFFFFFFC; /* align address with word boundary */
	lines = 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 memory line (8 words) each time ...
	 *
	 * We use the instruction "LDMIA R0!, {R1-R8}", which is running at
	 * system-speed, to read a memory line. To make the instruction
	 * LDMIA run at system-speed, we insert a NOP with BREAKPT bit
	 * set HIGH, it will make the ARM7TDMI core resynchronize back to
	 * MCLK, and make LDMIA instruction executed at system-speed.
	 */
	while ((lines * 8) < length) {
		/*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -