www.pudn.com > jtag_src.rar > arm7tdmi.c


/* 
 * arm7tdmi.c:	implement the core routes for ARM7TDMI 
 * 
 * Copyright (C) 2004, OPEN-JTAG, All rights reserved. 
 */ 
 
#include  
#include "../tool.h" 
#include "../xjerr.h" 
#include "../tapctrl.h" 
#include "arm7tdmi.h" 
#include "ice.h" 
 
 
 
//Used to record some important staus of the arm7tdmi 
arm7tdmi_status_t arm7tdmi_status; 
static arm7tdmi_breakpt_list_t *arm7tdmi_breakpt_head = NULL; 
static arm7tdmi_watchpt_status_t arm7tdmi_watchpt_status = {0, 0}; 
 
/* 
 * arm7tdmi_init() - 
 *		Used to initialize the arm7tdmi's core status. 
 *		Please call this route before starting any debug 
 *		operations. 
 */ 
int arm7tdmi_init(void) 
{ 
	arm7tdmi_status.by = -1; 
	arm7tdmi_status.scanchain = 3;				//On reset, scan chain 3 is selected by default. 
	arm7tdmi_status.from = ARM7TDMI_FROM_ARM; 
	arm7tdmi_status.state = ARM7TDMI_SYSTEM_STATE; 
	arm7tdmi_status.endian = ARM7TDMI_LITTLE_END; 
	 
	return XJ_OK;	 
} 
 
 
/* 
 * arm7tdmi_connect_scanchain() -  
 *		Used to select specific scan chian of arm7tmi and put 
 *		the selected scan chain into test state. Before returning, 
 *		the avtive scan chain is updated. 
 * 
 *		@sc_num: the scan chain to be selected. 
 */ 
int arm7tdmi_connect_scanchain(int sc_num) 
{ 
	int status; 
	int shift_out; 
 
	if(sc_num < 0 || sc_num > ARM7TDMI_NUMOF_SCANCHAIN) 
		return XJ_ERROR; 
 
	/* 
	 * In SYSTEM state, select scan chain 0 and 1 is not allowed. Select scan 
	 * chain 0 or 1 when in SYSTEM state will affect the debug and put the debug 
	 * into unpredictable situation. 
	 */ 
	if( (arm7tdmi_status.state != ARM7TDMI_DEBUG_STATE) && (sc_num != 2) ) 
		return XJERR_TARGET_RUNNING; 
 
	status = tapctrl_acs_ireg(JTAG_SCAN_N); 
	if(status != XJ_OK) 
		return status; 
 
	status = tapctrl_acs_dreg(ARM7TDMI_REGLEN_SCSEL, &sc_num, &shift_out); 
	if(status != XJ_OK) 
		return status; 
	if(shift_out != 0x8)			//shift out should be b1000 
		return XJERR_SCANCHAIN_FAIL; 
 
	//Enter INTEST state 
	status = tapctrl_acs_ireg(JTAG_INTEST); 
	if(status != XJ_OK) 
		return status; 
	 
	//Update the active scan chain 
	arm7tdmi_status.scanchain = sc_num; 
 
	return XJ_OK; 
} 
 
 
/* 
 * arm7tdmi_acs_sc1() -  
 *		Used to acces scan chain 1. By calling this route, ARM/THUMB  
 *		instructions can be scaned into the databus and clocked into 
 *		the pipeline. When scan chain 1 is selected and put into  
 *		INTEST state, everytime enter the RUN-TEST/IDLE state, a DCLK 
 *		is generated. Please make sure scan chain 1 is selected and  
 *		put it into INTEST state before calling this route. 
 *  
 *		Due to the reverse bit sequence of scan chain 1 cells, 
 *		all the data shifted in and out from scan chain 1 should 
 *		be reversed. 
 * 
 *		@shift_in:  data shifted into scan chain 1 
 *		@shift_out: data shifted out from scan chain 1 
 */ 
int arm7tdmi_acs_sc1(u32 *shift_in, u32 *shift_out) 
{ 
	int status; 
	u32 in_temp[2]; 
	u32 out_temp[2]; 
 
	//In DEBUG state? 
	if(arm7tdmi_status.state != ARM7TDMI_DEBUG_STATE) 
		return XJERR_TARGET_RUNNING; 
	 
	//Scan chain 1 selected? 
	if(arm7tdmi_status.scanchain != 1) 
		return XJERR_SC1_NOT_SELECTED; 
	 
	tool_reverse_bit_order(ARM7TDMI_REGLEN_SC1, shift_in, in_temp);		//Revert shifted in 
	status = tapctrl_acs_dreg(ARM7TDMI_REGLEN_SC1, in_temp, out_temp); 
	tool_reverse_bit_order(ARM7TDMI_REGLEN_SC1, out_temp, shift_out);	//Revert shifted out 
	 
	return XJ_OK; 
} 
 
 
/* 
 * arm7tdmi_system_reste() - 
 *		This route use nRESET to reset the system. 
 *		To reset the system by nRESET, there must have a 
 *		connection between the jtag interface and nRESET 
 */ 
int arm7tdmi_system_reset(void) 
{ 
	return XJ_OK; 
} 
 
 
/* 
 * arm7tdmi_enter_dbgstat() -  
 *		This route is used to force the target enter DEBUG state by  
 *		forcing DEBUGRQ signal HIGH. The value of PC when entering 
 *		DEBUG state is recorded.  
 * 
 *		The obtained value of PC indicates the next instruction to  
 *		be executed on exit from DEBUG state, which is important and 
 *		critcal to resume the normal execution of program under debug. 
 *		It is for later use to return from the DEBUG state back to  
 *		the SYSTEM state. 
 * 
 *		Please modify this function carefully. 
 *  
 *		@pc:	used to return the value of PC which indicates the 
 *				next instruction to be execute on exit from DEBUG 
 *				state. 
 */ 
int arm7tdmi_enter_dbgstat(u32 *pc) 
{ 
	int status; 
	u32 r0; 
	u32 dbgstat; 
	u32 shift_in[2]; 
	u32 shift_out[2]; 
 
	if(pc == NULL) 
		return XJERR_INVALID_PARAMATER; 
 
	//Check whether already in DEBUG state? 
	if(arm7tdmi_status.state == ARM7TDMI_DEBUG_STATE) 
		return XJERR_TARGET_HALTED; 
 
	//Enter DEBUG state by forcing DEBUGRQ signal HIGH  
	 
	//Select scan chain 2 
	status = arm7tdmi_connect_scanchain(2); 
	if(status != XJ_OK) 
		return status; 
	 
	//Write DEBUG control register 
	status = arm7tdmi_ice_write(ARM7TDMI_ICE_DBGCTRL, 0x6); 
	status = tapctrl_runtest(); 
 
	//Check the DBGACK signal to judge whether operation success? 
	status = arm7tdmi_ice_read(ARM7TDMI_ICE_DBGSTAT, &dbgstat); 
	if(status != XJ_OK) 
		return status; 
	if( (dbgstat & 0x1) == 0 ) 
		return XJERR_ENTDBG_FAIL; 
 
	//Successful, update the arm7tdmi status 
	arm7tdmi_status.by = ARM7TDMI_BY_BREAKPT; 
	arm7tdmi_status.state = ARM7TDMI_DEBUG_STATE; 
	 
	if (dbgstat & 0x10) 
		arm7tdmi_status.from = ARM7TDMI_FROM_THUMB; 
	else 
		arm7tdmi_status.from = ARM7TDMI_FROM_ARM; 
 
	/* 
	 * Don't forget to clear the DEBUG control register to  
	 * avoid enter DEBUG state. This is necessary. 
	 */ 
	arm7tdmi_ice_write(ARM7TDMI_ICE_DBGCTRL, 0x0); 
 
 
	/* 
	 * Try to obtain the value of PC when entering DEBUG state. The obtained 
	 * value of PC indicates the next instruction to be executed on exit from 
	 * DEBUG state. 
	 */ 
 
	//Select scan chain 1 
	status = arm7tdmi_connect_scanchain(1); 
	if(status != XJ_OK) 
		return status; 
 
	if(arm7tdmi_status.from == ARM7TDMI_FROM_ARM){    //Enter DEBUG from ARM state 
 
		//Step 1 - Read R0 
 
		//STR R0, [R0] = 0xE5800000					 
		shift_in[0] = 0xE5800000;					//Instruction 1 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					//Instruction 2 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					//Instruction 3 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP; 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
		r0 = shift_out[0]; 
 
		//Step 2 - Move PC to R0 
 
		//MOV R0, PC = 0xE1A0000F 
		shift_in[0] = 0xE1A0000F;					//Instruction 4 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out);	 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//Step 3 - Read the value of PC from R0 
 
		//STR R0, [R0] = 0xE5800000 
		shift_in[0] = 0xE5800000;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
		*pc = shift_out[0]; 
 
		/*  
		 * Entry into DEBUG state through a debug request is similar to a  
		 * breakpoint. However, unlike a breakpoint, the last instruction  
		 * has completed execution and so must not be refetched on exit  
		 * from DEBUG state. You can assume that entry to DEBUG state adds 
		 * three addresses to the PC and every instruction executed in DEBUG 
		 * state adds one address. To move the value of PC to R0, 4 instructions 
		 * have been executed in DEBUG state. So, the value of PC which  
		 * indicates the next instruction should be executed on exit from  
		 * DEBUG state is 
		 *				pc - 4 x (3 + 4) 
		 */ 
		*pc -= 28; 
 
	}else{		//Enter DEBUG from THUMB state 
		 
		//Step 1 - Read R0  
 
		//STR R0, [R0] = 0x60006000 
		shift_in[0] = 0x60006000;					//Instruction 1 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					//Instruction 2 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					//Instruction 3 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//R0 
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
		r0 = shift_out[0]; 
 
		//Step 2 - Move PC to R0 
 
		//MOV R0, PC = 0x46784678 
		shift_in[0] = 0x46784678;					//Instruction 4			 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//Step 3 - Read the value of PC from R0 
 
		//STR R0, [R0] = 0x60006000 
		shift_in[0] = 0x60006000;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
		*pc = shift_out[0]; 
 
		/*  
		 * Entry into DEBUG state through a debug request is similar to a  
		 * breakpoint. However, unlike a breakpoint, the last instruction  
		 * has completed execution and so must not be refetched on exit  
		 * from DEBUG state. You can assume that entry to DEBUG state adds 
		 * three addresses to the PC and every instruction executed in DEBUG 
		 * state adds one address. To move the value of PC to R0, 4 instructions 
		 * have been executed in DEBUG state. So, the value of PC which  
		 * indicates the next instruction should be executed on exit from  
		 * DEBUG state is 
		 *				pc - 2 x (3 + 4) 
		 */ 
		*pc -= 14; 
 
		//Step4 - Switch from THUMB state to ARM state 
 
		/* 
		 * When enter DEBUG state from THUBM state, we make ARM7TDMI enter ARM  
		 * state before any other debug operation is performed. Before leave the 
		 * DEBUG state, we make ARM7TDMI return back to THUMB state before the 
		 * normal operation is resumed. 
		 */ 
 
		//BX PC = 0x47784778 
		shift_in[0] = 0x47784778;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
	} 
 
	//Last Step - Restore R0 
	arm7tdmi_core_wri_reg(ARM7TDMI_R0, r0); 
 
	return XJ_OK; 
} 
 
 
/*  
 * arm7tdmi_check_dbgstat() - 
 *		After some breakpts or watchpts are setting, this route is used 
 *		to check the DEBUG status register to check whether the ARM7TDMI 
 *		enter DEBUG state by breakpt/watchpt.  
 * 
 *		When DBGACK flag is not set, XJ_ERROR is returned. When DBGACK  
 *		flag is set, it means the ARM7TDMI is in DEBUG state. Next, try 
 *		to obtain the value of PC when entering the DEBUG state.  
 * 
 *		The obtained value of PC indicates the next instruction to be  
 *		executed on exit from DEBUG state, which is important and 
 *		critcal to resume the normal execution of program under debug. 
 *		It is for later use to return from the DEBUG state back to  
 *		the SYSTEM state. 
 * 
 *		Please modify this function carefully. 
 * 
 *		@pc:	used to return the value of PC which indicates the next  
 *				instruction to be execute on exit from DEBUG state. 
 */ 
int arm7tdmi_check_dbgstat(u32 *pc) 
{ 
	int status; 
	u32 r0; 
	u32 dbgstat; 
	u32 shift_in[2]; 
	u32 shift_out[2]; 
 
	if(pc == NULL) 
		return XJERR_INVALID_PARAMATER; 
 
	//In DEBUG state? 
	if(arm7tdmi_status.state == ARM7TDMI_DEBUG_STATE) 
		return XJERR_TARGET_HALTED; 
 
	//Select scan chain 2 
	status = arm7tdmi_connect_scanchain(2); 
	if(status != XJ_OK) 
		return status; 
 
	//Check DEBUG status register 
	arm7tdmi_ice_read(ARM7TDMI_ICE_DBGSTAT, &dbgstat); 
	if(dbgstat & 0x1){ 
		arm7tdmi_status.state = ARM7TDMI_DEBUG_STATE; 
		if (dbgstat & 0x10) 
			arm7tdmi_status.from = ARM7TDMI_FROM_THUMB; 
		else 
			arm7tdmi_status.from = ARM7TDMI_FROM_ARM; 
	}else 
		return XJERR_TARGET_RUNNING; 
 
	/* 
	 * Try to obtain the value of PC when entering DEBUG state. The obtained 
	 * value of PC indicates the next instruction to be executed on exit from 
	 * DEBUG state. 
	 */ 
 
	//Select scan chain 1 
	status = arm7tdmi_connect_scanchain(1); 
	if(status != XJ_OK) 
		return status; 
 
 
	if(arm7tdmi_status.from == ARM7TDMI_FROM_ARM){	//Enter DEBUG from ARM state 
 
		//Step 1 - Read R0  
 
		//STR R0, [R0] = 0xE5800000					 
		shift_in[0] = 0xE5800000;					//Instruction 1 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		/*  
		 * After the ARM7TDMI core has entered debug state from breakpt/watchpt, 
		 * the first time the 33rd bit is captured and scanned out, its value  
		 * tells the debugger if the core entered debug state due to a breakpoint 
		 * (bit 33 clear) or a watchpoint (bit 33 set). 
		 */ 
		if(shift_out[1] & 0x1) 
			arm7tdmi_status.by = ARM7TDMI_BY_WATCHPT; 
		else 
			arm7tdmi_status.by = ARM7TDMI_BY_BREAKPT; 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					//Instruction 2 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					//Instruction 3 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP; 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
		r0 = shift_out[0]; 
 
		//Step 2 - Move PC to R0 
 
		//MOV R0, PC = 0xE1A0000F 
		shift_in[0] = 0xE1A0000F;					//Instruction 4 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out);	 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//Step 3 - Read the value of PC from R0 
 
		//STR R0, [R0] = 0xE5800000 
		shift_in[0] = 0xE5800000;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
		*pc = shift_out[0]; 
 
		/* 
		 * Entry into DEBUG state from a breakpoint/watchpoint advances the  
		 * PC by four addresses. Each instruction executed in DEBUG state  
		 * advances the PC by one address.  
		 * 
		 * To move the value of PC to R0, 4 instructions have been executed in D 
		 * EBUG state. So,  the value of PC which indicates the next instruction 
		 * should be executed on exit from DEBUG state is 
		 *			pc - 4 x (4 + 4) 
		 */ 
		*pc -= 32; 
 
	}else{		//Enter DEBUG from THUMB state 
 
		//Step 1 - Read R0  
 
		//STR R0, [R0] = 0x60006000 
		shift_in[0] = 0x60006000;					//Instruction 1 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		/*  
		 * After the ARM7TDMI core has entered debug state from breakpt/watchpt, 
		 * the first time the 33rd bit is captured and scanned out, its value  
		 * tells the debugger if the core entered debug state due to a breakpoint 
		 * (bit 33 clear) or a watchpoint (bit 33 set). 
		 */ 
		if(shift_out[1] & 0x1) 
			arm7tdmi_status.by = ARM7TDMI_BY_WATCHPT; 
		else 
			arm7tdmi_status.by = ARM7TDMI_BY_BREAKPT; 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					//Instruction 2 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					//Instruction 3 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//R0 
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
		r0 = shift_out[0]; 
 
		//Step 2 - Move PC to R0 
 
		//MOV R0, PC = 0x46784678 
		shift_in[0] = 0x46784678;					//Instruction 4			 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//Step 3 - Read the value of PC from R0 
 
		//STR R0, [R0] = 0x60006000 
		shift_in[0] = 0x60006000;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
		*pc = shift_out[0]; 
 
		/* 
		 * Entry into DEBUG state from a breakpoint/watchpoint advances the  
		 * PC by four addresses. Each instruction executed in DEBUG state  
		 * advances the PC by one address.  
		 * 
		 * To move the value of PC to R0, 4 instructions have been executed in D 
		 * EBUG state. So,  the value of PC which indicates the next instruction 
		 * should be executed on exit from DEBUG state is 
		 *			pc - 2 x (4 + 4) 
		 */	 
		*pc -= 16; 
 
		//Step4 - Switch from THUMB state to ARM state 
 
		/* 
		 * When enter DEBUG state, we make ARM7TDMI enter ARM state before any 
		 * further debug is performed. When leave from DEBUG state, we make 
		 * ARM7TDMI return to THUMB state before the normal operation is resumed. 
		 */ 
 
		//BX PC = 0x47784778 
		shift_in[0] = 0x47784778;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
	} 
 
	//LastStep - Restore R0 
	arm7tdmi_core_wri_reg(ARM7TDMI_R0, r0); 
 
	return XJ_OK; 
} 
 
 
/* 
 * arm7tdmi_exit_dbgstat() -  
 *		This route is used to exit from the DEBUG state and return to the 
 *		normal SYSTEM state. The input pc indicates the next instruction 
 *		to be exectued on exit from DEBUG state. After some operations in 
 *		the DEBUG state, this route can be used to exit from the DEBUG state 
 *		and resume the execution of program under debug. 
 * 
 *		Please modify this function carefully. 
 * 
 *		@pc:	the value of pc which indicates the next instruction to 
 *				be executed on exit from DEBUG state. 
 */ 
int arm7tdmi_exit_dbgstat(u32 pc) 
{ 
	int status; 
	u32 r0; 
	u32 shift_in[2]; 
	u32 shift_out[2]; 
 
	//In SYSTEM state? 
	if(arm7tdmi_status.state == ARM7TDMI_SYSTEM_STATE) 
		return XJ_OK; 
	 
	//Clear the DEBUGRQ flag in DBGCTRL register  
	status = arm7tdmi_connect_scanchain(2); 
	if(status != XJ_OK) 
		return status; 
 
	status = arm7tdmi_ice_write(ARM7TDMI_ICE_DBGCTRL, 0x0); 
	if(status != XJ_OK) 
		return status; 
 
	//Select scan chain 1 
	status = arm7tdmi_connect_scanchain(1); 
	if(status != XJ_OK) 
		return status; 
 
	if(arm7tdmi_status.from == ARM7TDMI_FROM_ARM){	//Enter DEBUG from ARM state 
 
		//Step 1 - Read R0 & Write the new value of PC to R0 
 
		pc &= 0xFFFFFFFC;	//Align 
		status = arm7tdmi_core_rd_reg(ARM7TDMI_R0, &r0); 
		status = arm7tdmi_core_wri_reg(ARM7TDMI_R0, pc); 
 
		//Step 2 - Move R0 to PC 
 
		//MOV PC, R0 = 0xE1A0F000					 
		shift_in[0] = 0xE1A0F000;				 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					//Instruct 1 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					//Instruct 2 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//Step 3 - Restore R0 
 
		//MOV R0, #0 = 0xE3A00000 
		shift_in[0] = 0xE3A00000;					//Instruct 3 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					//Instruct 4 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					//Instruct 5 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//LDR R0, [R0] = 0xE5900000 
		shift_in[0] = 0xE5900000;					//Instruct 6 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					//Instruct 7 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					//Instruct 8 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//R0 - put the value of R0 to the data bus 
		shift_in[0] = r0; 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//Write the value obtained from data bus to R0 
		shift_in[0] = ARM7TDMI_NOP; 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//Step 4 - Set SYSTEM speed flag 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					//Instruct 9	 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP + SYSTEM SPEED 
		shift_in[0] = ARM7TDMI_NOP;					//Instruct 10		 
		shift_in[1] = ARM7TDMI_SYSTEM_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		/* 
		 * After move the new value to register PC, 10 instructions have been 
		 * executed so far. To exit from DEBUG state and resume the normal  
		 * operation of the program under debug, 10 instructions backwards. 
		 */ 
 
		//B -10 = 0xEAFFFFF6 
		shift_in[0] = 0xEAFFFFF6;					//Final branch 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	}else{	//Enter DEBUG from THUMB state 
 
		//Step 1 - Read R0 & Write the new value of PC to R0 
 
		pc &= 0xFFFFFFFE;	//Align 
		status = arm7tdmi_core_rd_reg(ARM7TDMI_R0, &r0); 
		status = arm7tdmi_core_wri_reg(ARM7TDMI_R0, pc + 1); 
 
		//Step 2 - Switch from ARM state back to THUMB state first 
 
		//BX R0 = 0xE12FFF10 
		shift_in[0] = 0xE12FFF10; 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP 
		shift_in[0] = ARM7TDMI_NOP;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//Step 3 - Sbbtract R0 by 1 
		 
		//SUB R0, #1 = 0x38013801 
		shift_in[0] = 0x38013801;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//Step 4 - Move R0 to PC 
		 
		//MOV PC, R0 = 0x46874687 
		shift_in[0] = 0x46874687;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;						//Instruct 1 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;						//Instruct 2 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//Step 5 - Restore R0 
 
		//MOV R0, #0 = 0x20002000 
		shift_in[0] = 0x20002000;						//Instruct 3				 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;						//Instruct 4				 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;						//Instruct 5			 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//LDR R0, [R0] = 0x68006800 
		shift_in[0] = 0x68006800;						//Instruct 6			 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;						//Instruct 7				 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;						//Instruct 8					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//R1 - put the value of R0 to the data bus 
		shift_in[0] = r0;									 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//Write the value obtained from data bus to R0  
		shift_in[0] = 0x1C001C00;					 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//Step 6 - Set SYSTEM speed flag 
 
		//NOP  
		shift_in[0] = 0x1C001C00;						//Instruct 9 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		//NOP  
		shift_in[0] = 0x1C001C00;						//Instruct 10 
		shift_in[1] = ARM7TDMI_SYSTEM_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
 
		/* 
		 * After move the new value to register PC, 10 instructions have been 
		 * executed so far. To exit from DEBUG state and resume the normal  
		 * operation of the program under debug, 10 instructions backwards. 
		 */ 
 
		//B -10 = 0xE7F6E7F6 
		shift_in[0] = 0xE7F6E7F6;						//Final branch 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
	} 
	 
	/* 
	 * Last Step - Use RESTART to Exit DEBUG state and  
	 *			   return back to SYSTEM state 
	 */ 
	status = tapctrl_acs_ireg(JTAG_BYPASS); 
	status = tapctrl_acs_ireg(JTAG_RESTART); 
	status = tapctrl_runtest(); 
 
	//Update the ARM7TDMI status 
	arm7tdmi_status.state = ARM7TDMI_SYSTEM_STATE; 
	arm7tdmi_status.by = -1; 
	arm7tdmi_status.scanchain = -1;	 //For safe purpose 
	 
	return XJ_OK; 
} 
 
 
/*  
 * arm7tdmi_set_swbreakpt() - 
 *		Used to set a software break point at a specific address. 
 * 
 *		ARM7TDMI supports two watchpoint units. Normally, WP0 for break point  
 *		and WP1 for watch point. If WP0 is used for hardware break point, then  
 *		no software break point can be supported. If WP0 is used for software  
 *		break point, it can support any number of software breakpoint. 
 * 
 *		@addr: address of software break point. 
 */ 
static int arm7tdmi_set_swbreakpt(u32 addr) 
{ 
	int status; 
	u32 temp; 
	u32 instruct; 
	u32 bit_pattern = 0xDEEEDEEE; 
	arm7tdmi_breakpt_list_t *breakpt_new; 
 
 
	//In DEBUG state? 
	if(arm7tdmi_status.state != ARM7TDMI_DEBUG_STATE) 
		return XJERR_TARGET_RUNNING; 
	 
	status = arm7tdmi_connect_scanchain(2); 
	if(status != XJ_OK) 
		return status; 
 
	/* 
	 * Check the possibility. 
	 * If watchpt-0 is already used as a hardware break point, 
	 * return ERROR. 
	 */ 
	if( (arm7tdmi_breakpt_head != NULL) &&  
		arm7tdmi_breakpt_head->type == HARDWARE_BREAKPT) 
		return XJERR_SET_BREAKPT_FAIL; 
 
 
	//First disable WP0  
	arm7tdmi_ice_write(ARM7TDMI_WP0_CTRLVAL, 0x0); 
 
	/* 
	 * Try to set it as software break point by replacing the instruction 
	 * at addr by a specific bit pattern 
	 */ 
	status = arm7tdmi_connect_scanchain(1); 
 
	arm7tdmi_mem_rd32(addr, &instruct, 1);		 
	arm7tdmi_mem_wri32(addr, &bit_pattern, 1); 
	arm7tdmi_mem_rd32(addr, &temp, 1);	 
 
	status = arm7tdmi_connect_scanchain(2); 
 
	//Fail, the target instruction can't be replaced 
	if(temp != bit_pattern){		 
		arm7tdmi_ice_write(ARM7TDMI_WP0_CTRLMSK, 0x0F7); 
		arm7tdmi_ice_write(ARM7TDMI_WP0_CTRLVAL, 0x100); 
		return XJERR_SET_BREAKPT_FAIL; 
	} 
 
	//Succesful 
	breakpt_new = (arm7tdmi_breakpt_list_t*)malloc(sizeof(arm7tdmi_breakpt_list_t)); 
	if(breakpt_new == NULL){ 
		arm7tdmi_ice_write(ARM7TDMI_WP0_CTRLMSK, 0x0F7); 
		arm7tdmi_ice_write(ARM7TDMI_WP0_CTRLVAL, 0x100); 
		return XJ_ERROR; 
	} 
 
	breakpt_new->address = addr; 
	breakpt_new->instruct = instruct; 
	breakpt_new->type = SOFTWARE_BREAKPT; 
	breakpt_new->next = NULL; 
	 
	breakpt_new->next = arm7tdmi_breakpt_head; 
	arm7tdmi_breakpt_head = breakpt_new; 
 
	//Configure WP0 
	arm7tdmi_ice_write(ARM7TDMI_WP0_ADDRMSK, 0xFFFFFFFF); 
	arm7tdmi_ice_write(ARM7TDMI_WP0_DATAVAL, bit_pattern); 
	arm7tdmi_ice_write(ARM7TDMI_WP0_DATAMSK, 0x00000000); 
	arm7tdmi_ice_write(ARM7TDMI_WP0_CTRLMSK, 0x0F7); 
	arm7tdmi_ice_write(ARM7TDMI_WP0_CTRLVAL, 0x102);		//nOPC = 0, Enable WP0 b4 exit 
	 
	return XJ_OK; 
}  
 
 
/*  
 * arm7tdmi_set_hwbreakpt() - 
 *		Used to set a hardware break point at a specific address. 
 * 
 *		ARM7TDMI supports two watchpoint units. Normally, WP0 for break point  
 *		and WP1 for watch point. If WP0 is used for hardware break point, then  
 *		no software break point can be supported. If WP0 is used for software  
 *		break point, it can support any number of software breakpoint. 
 * 
 *		@addr: address of hardware break point. 
 */ 
static int arm7tdmi_set_hwbreakpt(u32 addr) 
{ 
	int status;	 
	arm7tdmi_breakpt_list_t *breakpt_new; 
 
	//In DEBUG state? 
	if(arm7tdmi_status.state != ARM7TDMI_DEBUG_STATE) 
		return XJERR_TARGET_RUNNING; 
	 
	status = arm7tdmi_connect_scanchain(2); 
	if(status != XJ_OK) 
		return status; 
 
	/* 
	 * Check the possibility. 
	 * If watchpt-0 is already used as a hardware break point, 
	 * return ERROR. 
	 */ 
	if(arm7tdmi_breakpt_head != NULL) 
		return XJERR_SET_BREAKPT_FAIL; 
 
	//Add this hardware break point to the list of break point. 
	breakpt_new = (arm7tdmi_breakpt_list_t*)malloc(sizeof(arm7tdmi_breakpt_list_t)); 
	if(breakpt_new == NULL) 
		return XJ_ERROR; 
 
	breakpt_new->address = addr; 
	breakpt_new->instruct = 0; 
	breakpt_new->type = HARDWARE_BREAKPT; 
	breakpt_new->next = NULL; 
 
	arm7tdmi_breakpt_head = breakpt_new; 
 
 
	//Configure WP0 
	arm7tdmi_ice_write(ARM7TDMI_WP0_CTRLVAL, 0x0);		//Disable WP0 during the setting 
	arm7tdmi_ice_write(ARM7TDMI_WP0_ADDRVAL, addr); 
	arm7tdmi_ice_write(ARM7TDMI_WP0_ADDRMSK, 0x0); 
	arm7tdmi_ice_write(ARM7TDMI_WP0_DATAMSK, 0xFFFFFFFF); 
	arm7tdmi_ice_write(ARM7TDMI_WP0_CTRLMSK, 0x0F7); 
	arm7tdmi_ice_write(ARM7TDMI_WP0_CTRLVAL, 0x100);	//nOPC = 0, Enable WP0 b4 exit 
	 
	return XJ_OK; 
} 
 
 
/*  
 * arm7tdmi_set_breakpt() - 
 *		Used to set a break point at a specific address. 
 *		We prefer software break point. Everytime, we will try to 
 *		set it as a software break point first. If fail, then try 
 *		to set it as a hardware break point.		 
 * 
 *		@addr: address of break point. 
 */ 
int arm7tdmi_set_breakpt(u32 addr) 
{ 
	int status; 
	 
	status = arm7tdmi_set_swbreakpt(addr); 
 
	if(status == XJ_OK) 
		return XJ_OK; 
	else 
		status = arm7tdmi_set_hwbreakpt(addr); 
 
	return status; 
} 
 
 
/* 
 * arm7tdmi_clr_breakpt() - 
 *		Used to clear a break point located at a specific address 
 * 
 *		@addr: address of the break point to be cleared. 
 */ 
int arm7tdmi_clr_breakpt(u32 addr) 
{ 
	int status; 
	int type; 
	u32 instruct; 
	arm7tdmi_breakpt_list_t *breakpt_temp; 
	arm7tdmi_breakpt_list_t *breakpt_prev; 
 
	//In DEBUG state? 
	if(arm7tdmi_status.state != ARM7TDMI_DEBUG_STATE) 
		return XJERR_TARGET_RUNNING; 
	 
	status = arm7tdmi_connect_scanchain(2); 
	if(status != XJ_OK) 
		return status; 
 
	//Find the target break point first 
	breakpt_prev = NULL; 
	for(breakpt_temp = arm7tdmi_breakpt_head; breakpt_temp != NULL; breakpt_temp = breakpt_temp->next){ 
		if(breakpt_temp->address == addr){ 
			if(breakpt_prev == NULL){ 
				arm7tdmi_breakpt_head = breakpt_temp->next; 
			}else{ 
				breakpt_prev->next = breakpt_temp->next; 
			} 
			break; 
		} 
		breakpt_prev = breakpt_temp; 
	} 
 
	//Found?? 
	if(breakpt_temp == NULL) 
		return XJERR_CLR_BREAKPT_FAIL; 
 
	type = breakpt_temp->type; 
	instruct = breakpt_temp->instruct; 
	free(breakpt_temp);								//Delete breakpt_temp 
 
	if(type == SOFTWARE_BREAKPT){					//Software break point 
		status = arm7tdmi_connect_scanchain(1); 
		arm7tdmi_mem_wri32(addr, &instruct, 1); 
	}else{											//Hardware break point 
		status = arm7tdmi_connect_scanchain(2); 
		arm7tdmi_ice_write(ARM7TDMI_WP0_CTRLVAL, 0x0); 
	} 
 
	return XJ_OK; 
}  
 
 
/*  
 * arm7tdmi_set_watchpt() - 
 *		Used to set a watch point at a specific address. 
 * 
 *		ARM7TDMI supports two watchpoint units. Normally, WP0 for break point  
 *		and WP1 for watch point.  
 * 
 *		@addr: address of watch point to be set. 
 */ 
int arm7tdmi_set_watchpt(u32 addr) 
{ 
	int status; 
 
	//Is WP1 available? 
	if(arm7tdmi_watchpt_status.busy == 1) 
		return XJERR_SET_WATCHPT_FAIL; 
 
	//In DEBUG state? 
	if(arm7tdmi_status.state != ARM7TDMI_DEBUG_STATE) 
		return XJERR_TARGET_RUNNING; 
	 
	status = arm7tdmi_connect_scanchain(2); 
	if(status != XJ_OK) 
		return status; 
 
	//Configure WP1 
	arm7tdmi_ice_write(ARM7TDMI_WP1_CTRLVAL, 0x0);		//Disable WP1 during the setting 
	arm7tdmi_ice_write(ARM7TDMI_WP1_ADDRVAL, addr); 
	arm7tdmi_ice_write(ARM7TDMI_WP1_ADDRMSK, 0x0); 
	arm7tdmi_ice_write(ARM7TDMI_WP1_DATAMSK, 0xFFFFFFFF); 
	arm7tdmi_ice_write(ARM7TDMI_WP1_CTRLMSK, 0x0F7); 
	arm7tdmi_ice_write(ARM7TDMI_WP1_CTRLVAL, 0x108);	//nOPC = 1, Enable WP1 b4 exit 
 
	//Update the status of WP1 
	arm7tdmi_watchpt_status.busy = 1; 
	arm7tdmi_watchpt_status.addr = addr; 
	 
	return XJ_OK; 
} 
 
 
/*  
 * arm7tdmi_clr_watchpt() - 
 *		Used to clear a watch point at a specific address. 
 * 
 *		ARM7TDMI supports two watchpoint units. Normally, WP0 for break point  
 *		and WP1 for watch point.  
 * 
 *		@addr: address of watch point to be cleared. 
 */ 
int arm7tdmi_clr_watchpt(u32 addr) 
{ 
	int status; 
 
	//Match? 
	if( (arm7tdmi_watchpt_status.busy == 0) || (arm7tdmi_watchpt_status.addr != addr) ) 
		return XJERR_SET_WATCHPT_FAIL; 
 
	//In DEBUG state? 
	if(arm7tdmi_status.state != ARM7TDMI_DEBUG_STATE) 
		return XJERR_TARGET_RUNNING; 
	 
	status = arm7tdmi_connect_scanchain(2); 
	if(status != XJ_OK) 
		return status; 
 
	//Disable WP1 
	arm7tdmi_ice_write(ARM7TDMI_WP1_CTRLVAL, 0x0);		 
 
	//Update the status of WP1 
	arm7tdmi_watchpt_status.busy = 0; 
	arm7tdmi_watchpt_status.addr = 0;	 
 
	return XJ_OK; 
}