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


/* 
 * core.c:	implement the routes used to access the core 
 *			registers under DEBUG state. 
 * 
 * Copyright (C) 2004, OPEN-JTAG, All rights reserved. 
 */ 
 
 
#include  
#include "../types.h" 
#include "../xjerr.h" 
#include "../tapctrl.h" 
#include "arm7tdmi.h" 
 
 
 
/* 
 * ARM7TDMI inlcudes 18 regisgers: R0-R14, PC, CPSR & SPSR 
 * Plz note that SPSR is unavailable when the ARM7TDMI is in 
 * the System/User state.  
 */ 
u32 arm7tdmi_register[18][2] = { 
	{0x0, 0}, {0x0, 0}, {0x0, 0}, {0x0, 0}, {0x0, 0}, {0x0, 0}, 
	{0x0, 0}, {0x0, 0}, {0x0, 0}, {0x0, 0}, {0x0, 0}, {0x0, 0}, 
	{0x0, 0}, {0x0, 0}, {0x0, 0} 
}; 
 
 
 
static int arm7tdmi_core_rd_r0(u32 *r0) 
{ 
	u32 shift_in[2]; 
	u32 shift_out[2]; 
 
	//In DEBUG state? 
	if(arm7tdmi_status.state != ARM7TDMI_DEBUG_STATE) 
		return XJERR_TARGET_RUNNING; 
	 
	//Select scan chain 1 
	if(arm7tdmi_status.scanchain != 1) 
			return XJERR_SC1_NOT_SELECTED; 
 
	// STR R0, [R0] = 0xE5800000 
	shift_in[0] = 0xE5800000; 
	shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	shift_in[0] = ARM7TDMI_NOP; 
	shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	shift_in[0] = ARM7TDMI_NOP; 
	shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	shift_in[0] = ARM7TDMI_NOP; 
	shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	*r0 = shift_out[0]; 
 
	return XJ_OK; 
} 
 
 
static int arm7tdmi_core_wri_r0(u32 r0) 
{ 
	u32 shift_in[2]; 
	u32 shift_out[2]; 
 
	//In DEBUG state? 
	if(arm7tdmi_status.state != ARM7TDMI_DEBUG_STATE) 
		return XJERR_TARGET_RUNNING; 
	 
	//Select scan chain 1 
	if(arm7tdmi_status.scanchain != 1) 
			return XJERR_SC1_NOT_SELECTED; 
 
	/*  
	 * Step 1: clear R0 
	 * MOV R0, #0 = 0xE3A00000 
	 */ 
	shift_in[0] = 0xE3A00000; 
	shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	shift_in[0] = ARM7TDMI_NOP; 
	shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	shift_in[0] = ARM7TDMI_NOP; 
	shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
 
	/*  
	 * Step 2: set R0 
	 * LDR R0, [R0] = 0xE5900000 
	 */ 
	shift_in[0] = 0xE5900000; 
	shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	shift_in[0] = ARM7TDMI_NOP; 
	shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	shift_in[0] = ARM7TDMI_NOP; 
	shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	shift_in[0] = r0;				//New value 
	shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	shift_in[0] = ARM7TDMI_NOP; 
	shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
	 
	return XJ_OK; 
} 
 
 
//Read a specific core register 
int arm7tdmi_core_rd_reg(int reg_idx, u32 *cur_val) 
{ 
	int status; 
	u32 r0; 
	u32 cpsr; 
	u32 shift_in[2]; 
	u32 shift_out[2]; 
 
	if(cur_val == NULL) 
		return XJERR_INVALID_PARAMATER; 
 
	//In DEBUG state? 
	if(arm7tdmi_status.state != ARM7TDMI_DEBUG_STATE) 
		return XJERR_TARGET_RUNNING; 
	 
	//Check the validity of the register according to the register index 
	if(reg_idx < ARM7TDMI_R0 || reg_idx > ARM7TDMI_SPSR) 
		return XJERR_INVALID_COREREG; 
 
	//Select scan chain 1 
	if(arm7tdmi_status.scanchain != 1){ 
		status = arm7tdmi_connect_scanchain(1); 
		if(status != XJ_OK) 
			return status; 
	} 
 
	//Anyway, read the value of R0 first. 
	arm7tdmi_core_rd_r0(&r0); 
	 
	//If R0 is the target register, return directly 
	if(reg_idx == ARM7TDMI_R0){ 
		*cur_val = r0; 
		return XJ_OK; 
	} 
 
	//Execute all the instructions at the DEBUG speed 
	shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
 
	if(reg_idx == ARM7TDMI_CPSR){			//Read CPSR 
		// MRS R0, CPSR = 0xE10F0000 
		shift_in[0] = 0xE10F0000;	 
	}else if(reg_idx == ARM7TDMI_SPSR){		//Read SPSR 
		// Make sure SPSR is available 
		arm7tdmi_core_rd_reg(ARM7TDMI_CPSR, &cpsr); 
		if( (cpsr & 0x1F) == 0x10 || (cpsr & 0x1F) == 0x1F ) 
			return XJERR_COREREG_UNAVAILABLE; 
 
		// MRS R0, SPSR = 0xE14F0000 
		shift_in[0] = 0xE14F0000; 
	}else{									//Read R1-R15 
		// MOV R0, Rx = 0xE1A0000x 
		shift_in[0] = (0xE1A00000 | reg_idx); 
	} 
 
	//Move the value of the target register to R0 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	/* 
	 * Next, use STR R0, [R0] to make the value of R0 apear 
	 * on the data bus 
	 */ 
	//STR R0, [R0] = 0xE5800000, fetch cycle of STR R0, [R0] 
	shift_in[0] = 0xE5800000;				 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	//NOP, decode cycle of STR R0, [R0] 
	shift_in[0] = ARM7TDMI_NOP; 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	//NOP, execute cycle STR R0, [R0] 
	shift_in[0] = ARM7TDMI_NOP; 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	//NOP, now the value of R0 appears on the data bus 
	shift_in[0] = ARM7TDMI_NOP; 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	*cur_val = shift_out[0]; 
 
	//Restore R0 before return 
	arm7tdmi_core_wri_r0(r0); 
 
	return XJ_OK; 
} 
 
 
//Write a specific core register 
int arm7tdmi_core_wri_reg(int reg_idx, u32 new_val) 
{ 
	int status; 
	u32 r0; 
	u32 cpsr; 
	u32 shift_in[2]; 
	u32 shift_out[2]; 
 
	//In DEBUG state? 
	if(arm7tdmi_status.state != ARM7TDMI_DEBUG_STATE) 
		return XJERR_TARGET_RUNNING; 
	 
	//Check the validity of the register according to the register index 
	if(reg_idx < ARM7TDMI_R0 || reg_idx > ARM7TDMI_SPSR) 
		return XJERR_INVALID_COREREG; 
 
	//Select scan chain 1 
	if(arm7tdmi_status.scanchain != 1){ 
		status = arm7tdmi_connect_scanchain(1); 
		if(status != XJ_OK) 
			return status; 
	} 
 
 
	if(reg_idx == ARM7TDMI_R0){			//If R0 is the target, write and return 
		arm7tdmi_core_wri_r0(new_val); 
		return XJ_OK; 
	}else{								//Else, backup R0 and write the new value to R0 
		arm7tdmi_core_rd_r0(&r0); 
		arm7tdmi_core_wri_r0(new_val); 
	} 
	 
	//Execute all the instructions at the DEBUG speed 
	shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
 
	if(reg_idx == ARM7TDMI_CPSR){		//WriteCPSR 
		// MSR CPSR, R0 = 0xE12FF000 
		shift_in[0] = 0xE12FF000; 
	}else if(reg_idx == ARM7TDMI_SPSR){	//Write SPSR 
		// Make sure SPSR is available 
		arm7tdmi_core_rd_reg(ARM7TDMI_CPSR, &cpsr); 
		if( (cpsr & 0x1F) == 0x10 || (cpsr & 0x1F) == 0x1F ) 
			return XJERR_COREREG_UNAVAILABLE; 
 
		// MSR SPSR, R0 = 0xE16FF000 
		shift_in[0] = 0xE16FF000; 
	}else{								//Write R1-R15 
		//MOV R?, R0 = 0xE1A0?000 
		shift_in[0] = 0xE1A00000;		 
		shift_in[0] |= ((reg_idx - ARM7TDMI_R0)*0x1000); 
	} 
 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	//NOP 
	shift_in[0] = ARM7TDMI_NOP; 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	//NOP 
	shift_in[0] = ARM7TDMI_NOP; 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	//NOP 
	shift_in[0] = ARM7TDMI_NOP; 
	arm7tdmi_acs_sc1(shift_in, shift_out); 
 
	//Restore R0 before return 
	arm7tdmi_core_wri_r0(r0); 
 
	return XJ_OK; 
} 
 
 
//Read all the core registers 
int arm7tdmi_core_rd_all(void) 
{ 
	int index; 
	int status; 
	u32 cpsr; 
	u32 spsr; 
	u32 shift_in[2]; 
	u32 shift_out[2]; 
	 
	//In DEBUG state? 
	if(arm7tdmi_status.state != ARM7TDMI_DEBUG_STATE) 
		return XJERR_TARGET_RUNNING; 
	 
	//Select scan chain 1 
	if(arm7tdmi_status.scanchain != 1){ 
		status = arm7tdmi_connect_scanchain(1); 
		if(status != XJ_OK) 
			return status; 
	} 
	 
 
	//1. Read R0-R15 
 
	//STM R0, {R0-R15} = 0xE880FFFF 
	shift_in[0] = 0xE880FFFF; 
	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); 
 
	for(index = 0; index <= 15; index++){ 
		shift_in[0] = ARM7TDMI_NOP; 
		shift_in[1] = ARM7TDMI_DEBUG_SPEED; 
		arm7tdmi_acs_sc1(shift_in, shift_out); 
		arm7tdmi_register[index][0] = shift_out[0]; 
	} 
 
	//2. Read CPSR and SPSR 
	status = arm7tdmi_core_rd_reg(ARM7TDMI_CPSR, &cpsr); 
	if(status == XJ_OK) 
		arm7tdmi_register[ARM7TDMI_CPSR][0] = cpsr; 
 
	status = arm7tdmi_core_rd_reg(ARM7TDMI_SPSR, &spsr); 
	if(status == XJ_OK) 
		arm7tdmi_register[ARM7TDMI_SPSR][0] = spsr; 
 
	for(index = 0; index <=17; index++) 
		printf("0x%0.8x\n", arm7tdmi_register[index][0]); 
 
	return XJ_OK; 
}