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

📄 nios_gdb_stub.c

📁 ALTERA的NIOS处理器!文件直接可以打开直接选择器件重新编译!
💻 C
📖 第 1 页 / 共 2 页
字号:
// File: nios_gdb_stub.c
// Date: 2000 June 20
// Author dvb \ Altera Santa Cruz

#include "nios.h"
#include "nios_gdb_stub.h"

#define na_debug_peripheral_irq 8

enum
{
  na_BreakpointTrap     = 3,
  na_SingleStepTrap     = 4,
  na_StartGDBTrap       = 5
};

// --------------------------------
// Local Prototypes

static void StringFit(char *s,int w);

// --------------------------------
// Debugging The Debugger

#if GDB_DEBUG_PRINT
void GDB_RawMessage(char *s)
	{
	StringFit(s,32);
	nr_pio_lcdwritescreen(s);
	}
#else
	#define GDB_RawMessage(a,b,c)	// define away to nothing
#endif

#if GDB_DEBUG_PRINT
void GDB_Print2(char *s,int n1,int n2)
	{
	char st[1000];

	sprintf(st,s,n1,n2);
	GDB_RawMessage(st);
	}
#else
	#define GDB_Print2(a,b,c)	// define away to nothing
#endif

// If string is longer than w, cut out the middle.

#if GDB_DEBUG_PRINT
int StringLen(char *s)
	{
	int l = 0;

	while(*s++)
		l++;
	return l;
	}

void StringFit(char *s,int w)
	{
	if(StringLen(s) > w)
		{
		int i;


		w = w / 2;

		for(i = 0; i < w; i++)
			{
			s[i + w] = s[StringLen(s) - w + i];
			}
		s[w + w] = 0;
		}
	}
#endif


// ---------------------------------------------
// Generic routines for dealing with
// hex input, output, and parsing
// (Adapted from other stubs.)

NiosGDBGlobals gdb; // (starts life == 0) not static: the ISR uses it!

static char dHexChars[16] = "0123456789abcdef";


/*
 * HexCharToValue -- convert a characters
 *                   to its hex value, or -1 if not.
 */
char HexCharToValue(char c)
{
	char result=0;

	if(c >= '0' && c <= '9')
		result = c - '0';
	else if(c >= 'a' && c <= 'f')
		result = c - 'a' + 10;
	else if(c >= 'A' && c <= 'A')
		result = c - 'A' + 10;
	else 
		result = -1;
	return result;
}

/*
 * HexStringToValue -- convert a 2*byte_width string of characters
 *                   to its little endian hex value, 
 *		     or -1 if not.
 *		This routine is for strings of hex values
 */
unsigned long HexStringToValue(char *c, int byte_width)
{
	unsigned long result=0;
	unsigned char a,b;
	int i=0;

	while (i < byte_width)
	{
		a = HexCharToValue(*c++);
		if (a & 0x80) return a;
		b = HexCharToValue(*c++);
		if (b & 0x80) return b;
		b = (a<<4) | (b&0x0f);
		result |= ((unsigned long)b) << (i*8);
		i++;
	}
	return result;
}

/*
 * Hex2Value -- convert a non-hex char delimited string 
 * 		to its big endian hex value.
 *		This routine is for address and byte count values
 */

char *Hex2Value(char *hexIn, int *valueOut)
	{
	char c;
	int digitValue;
	int value = 0;

	while(1)
		{
		c = *hexIn;
		digitValue = HexCharToValue(c);
		if(digitValue < 0)
			{
			*valueOut = value;
			return hexIn;
			}
		hexIn++;
		value = (value << 4) + digitValue;
		}
	}

/*
 * HexToMem -- convert a string to a specified
 *             number of bytes in memory.
 *
 *		JMB -- make this thing a bit smarter so
 *			   that it selects the byte width to
 *			   write based on the number of bytes
 *			   and the destination address alignment.
 *			   This is to support writes to non-byte enabled
 *			   peripheral registers...I don't like it.
 *			   Beware! there are cases where it wont work
 */
char *HexToMem(char *hexIn, char *memOut, int memByteCount)
{
	int i;
	unsigned long x;
	short *memOutS = 0;
	long *memOutL = 0;
	int byte_width;

	//determine maximum byte width
	if (((memByteCount%2) != 0) || (((unsigned int)memOut%2) != 0))
		byte_width = 1;
	else if (((memByteCount % 4) != 0) || (((unsigned int)memOut % 4) != 0))
	{
		byte_width = 2;
		memOutS = (short *)memOut;
	}
	else 
	{
		byte_width = 4;
		memOutL = (long *)memOut;
	}
	for(i = 0; i < memByteCount; i+=byte_width)
	{
		x = HexStringToValue(hexIn,byte_width);
		hexIn += byte_width*2;
		switch (byte_width)
		{
		case 1:
			*memOut++ = (unsigned char) 0x000000ff & x;
			break;
		case 2:			
			*memOutS++ = (unsigned short) 0x0000ffff & x;
			break;
		case 4:			
			*memOutL++ = x;
			break;
		default:
			//How could this ever happen???
			break;
		}
	}

	return hexIn;
}

char *MemToHex(char *memIn, char *hexOut, int memByteCount)
{
	int i,j;
	int byte_width;
	unsigned long x = 0;
	unsigned short *memInS = 0;
	unsigned long *memInL = 0;

	//determine maximum byte width
	if (((memByteCount % 2) != 0) || (((unsigned int)memIn % 2) != 0))
		byte_width = 1;
	else if (((memByteCount % 4) != 0) || (((unsigned int)memIn % 4) != 0))
	{
		byte_width = 2;
		memInS = (short *)memIn;
	}
	else 
	{
		byte_width = 4;
		memInL = (long *)memIn;
	}

	for(i = 0; i < memByteCount; i+=byte_width)
	{
		switch (byte_width)
		{
		case 1:
			x = *memIn++;
			break;
		case 2:
			x = *memInS++;
			break;
		case 4:
			x = *memInL++;
			break;
		default:
			//How would we get here?
			break;
		}

		for (j=0; j<byte_width; j++)
		{
			*hexOut++ = dHexChars[(x&0x000000f0)>>4];
			*hexOut++ = dHexChars[x&0x0000000f];
			x = x>>8;
		}
	}

	*hexOut = 0;

	return hexOut;
}

//Send just the + or - to indicate
//ACK or NACK
void GDBPutAck (char ack)
{
	if (gdb.comlink == ne_gdb_serial)
		GDBPutChar (ack);
#ifdef ETHER_DEBUG
#ifdef ethernet_exists
	else
	{
		if (gdb.host_ip_address != 0)
			nr_plugs_send_to (gdb.gdb_eth_plug, &ack, 1, 0,
				gdb.host_ip_address,
				gdb.host_port_number);
	}
#endif
#endif
}

/*
 * Once a $ comes in, use GetGDBPacket to
 * retrieve a full gdb packet, and verify
 * checksum, and reply + or -.
 */
int GetGDBPacket(char *aBuffer)
{
	int checksum = 0;
	int length = 0;
	char c;
	int x = 0; // satisfy compiler

	if (gdb.comlink == ne_gdb_serial)
	{
		while ((c = GDBGetChar ()) != '$') ;

startPacket:
		while(((c = GDBGetChar()) != '#') && (length < kTextBufferSize))
		{
			if(c == '$')
				goto startPacket;
			checksum += c;
			aBuffer[length++] = c;
			aBuffer[length] = 0;
		}

		c = GDBGetChar();
		x = HexCharToValue(c) << 4;
		c = GDBGetChar();
		x += HexCharToValue(c);


		checksum &= 0xff;

		GDB_Print2("GetPacket %d",length,0);
	}
#ifdef ETHER_DEBUG
#ifdef ethernet_exists
	else
	{
		int srcidx;
		// wait till beginning of packet
		while (gdb.textBuffer[0] != '$') nr_plugs_idle_exclusive(gdb.gdb_eth_plug);
startEPacket:
		srcidx = 1;

		//loop until packet terminator
		//leave enough room for the checksum at the end
		while (((c = gdb.textBuffer[srcidx++]) != '#') && (srcidx < kTextBufferSize-2))
		{
			if (c == '$') 
				goto startEPacket;

			checksum += c;
			aBuffer[length++] = c;
		}

		c = gdb.textBuffer[srcidx++];
		x = HexCharToValue(c) << 4;
		c = gdb.textBuffer[srcidx++];
		x += HexCharToValue (c);

		aBuffer[length++] = 0;

		checksum &= 0xff;
		
		GDB_Print2("GetPacket %d",length,0);
	}
#endif
#endif

	if(checksum != x)
	{
		GDBPutAck('-');
		length = 0;
	}
	else
	{
		GDBPutAck('+');
	}
	return length;
}

//Wait for acknowledgement
//Should we have some way of timing out???
//return TRUE if ACK
//return FALSE if NACK
int GDBGetACK ()
{
	char c;
	if (gdb.comlink == ne_gdb_serial)
	{
		while (1)
		{
			c = GDBGetChar ();
			if (c == '+') return (1);
			else if (c == '-') return (0);
		}

	}
#ifdef ETHER_DEBUG
#ifdef ethernet_exists
	else
	{
		gdb.ACKstatus = ne_gdb_ack_waiting;
		while (1)
		{
			nr_plugs_idle_exclusive (gdb.gdb_eth_plug);
			if (gdb.ACKstatus == ne_gdb_ack_acked)
			{
				gdb.ACKstatus = ne_gdb_ack_notwaiting;
				return (1);
			}
			else if (gdb.ACKstatus == ne_gdb_ack_nacked) 
			{
				gdb.ACKstatus = ne_gdb_ack_notwaiting;
				return (0);
			}
		}
	}
#endif
#endif
	return 0; // satisfy compiler, never gets here
}

/*
 * Send a packet, preceded by $,
 * and followed by #checksum.
 */
void PutGDBPacket(char *aBuffer)
{
	int checksum;
	char c;
	int cnt=0;

	if (gdb.comlink == ne_gdb_serial)
	{
startPutSerial:
		GDBPutChar('$');
		checksum = 0;
		while((c = *aBuffer++) != 0)
		{
			checksum += c;
			GDBPutChar(c);
		}
		GDBPutChar('#');
		GDBPutChar(dHexChars[(checksum >> 4) & 15]);
		GDBPutChar(dHexChars[checksum & 15]);

		if (!GDBGetACK ()) 
		{
			if (++cnt < GDB_RETRY_CNT) goto startPutSerial;
		}
	}
#ifdef ETHER_DEBUG
#ifdef ethernet_exists
	else
	{
		if (gdb.host_ip_address != 0)
		{
			int i;
			int result;
			char c1;

			i = 0;
			c = aBuffer[i];
			if (c==0) return; //there is no data in packet, so why bother sending
			aBuffer[i++] = '$';
			checksum = 0;
			do 
			{
				checksum += c;
				c1 = aBuffer[i];
				aBuffer[i++] = c;
				c = c1;
			} while (c != 0);
	
			aBuffer[i++] = '#';
			aBuffer[i++] = dHexChars[(checksum >> 4) & 15];
			aBuffer[i++] = dHexChars[checksum & 15];
			aBuffer[i++] = 0;
startPutEth:
			result = nr_plugs_send_to (gdb.gdb_eth_plug, aBuffer, i, 0,
				gdb.host_ip_address,
				gdb.host_port_number);
			aBuffer[0] = 0; //clear packet to 

			if (!GDBGetACK ()) 
			{
				if (++cnt < GDB_RETRY_CNT) goto startPutEth;
			}
		}
	}
#endif
#endif
}

int PutTracePacket(char *aBuffer, int size)
{
	int checksum;
	char c;
	int i;
	int cnt=0;

	if (gdb.comlink == ne_gdb_serial)
	{
startPutSerial:
		GDBPutChar('$');
		checksum = 0;
		for (i=0; i<size; i++)
		{
			checksum += aBuffer[i];
			GDBPutChar (aBuffer[i]);
		}
		GDBPutChar('#');
		GDBPutChar(dHexChars[(checksum >> 4) & 15]);
		GDBPutChar(dHexChars[checksum & 15]);

		if (!GDBGetACK ()) 
		{
			if (++cnt < GDB_RETRY_CNT) goto startPutSerial;
		}
	}
#ifdef ETHER_DEBUG
#ifdef ethernet_exists
	else
	{
		int result;
		char c1;

		checksum = 0;
		c = '$';
		for (i=0; i<size; i++)
		{
			checksum += aBuffer[i];
			c1 = aBuffer[i];
			aBuffer[i] = c;
			c = c1;
		} 
		aBuffer[i++] = c;

		aBuffer[i++] = '#';
		aBuffer[i++] = dHexChars[(checksum >> 4) & 15];
		aBuffer[i++] = dHexChars[checksum & 15];
		aBuffer[i++] = 0;
ethResend:
		if (gdb.host_ip_address != 0)
		{
			result = nr_plugs_send_to (gdb.gdb_eth_plug, aBuffer, i, 0,
				gdb.host_ip_address,
				gdb.host_port_number);
			aBuffer[0]=0;
		}
		if (!GDBGetACK ()) 
		{
			if (++cnt < GDB_RETRY_CNT) goto ethResend;
		}
	}
#endif
#endif
	if (cnt < GDB_RETRY_CNT) return 1;
	else return 0;
}

void PutGDBOKPacket(char *aBuffer)
	{
	aBuffer[0] = 'O';
	aBuffer[1] = 'K';
	aBuffer[2] = 0;
	PutGDBPacket(aBuffer);
	}

#if nasys_debug_core

//some defines used exclusively for TRACE data xfer
#define stepsize (2*sizeof(int) + sizeof (char))
#define MAX_TRACE_BYTES	(((int)((2*MAX_DATA_SIZE-2)/stepsize))*stepsize)

int Trace_Read_Intercept (char *aBuffer)
{
	int cnt=0;
	unsigned int data;
	unsigned char code;
	int byteCount;
	unsigned char *w;
	unsigned short dataAccumulate;
	int status;

	w = aBuffer;
	w++;	//skip past the m
	if (*w++ == 't')  //see if this is a special "memory trace" packet
	{
		w = Hex2Value(w,&byteCount); //get the number of bytes to transfer

		//turn byteCount to a multiple of stepsize
		byteCount = ((int)(byteCount/stepsize))*stepsize; 

		//wait until fifo empties
		nm_debug_get_reg(status, np_debug_write_status);
		while (status&np_debug_write_status_writing_mask) nm_debug_get_reg(status,np_debug_write_status); 

		// loop through total size
		while (byteCount > 0)
		{
			w=aBuffer;	//reset w to beginning of buffer

			//calculate the number of bytes in this packet
			if (byteCount > MAX_TRACE_BYTES) dataAccumulate = MAX_TRACE_BYTES;
			else dataAccumulate = byteCount;

			//insert data size at beginning of packet
			*w++ = 0x00ff & dataAccumulate;
			*w++ = 0x00ff & (dataAccumulate >> 8);

			byteCount -= dataAccumulate; //decrement byteCount

			// accumulate a full buffer
			for (cnt=0; cnt<dataAccumulate; cnt+=stepsize)
			{
				int valid;
				nm_debug_set_reg (1, np_debug_read_sample); //begin transaction

				//wait until data is ready
				nm_debug_get_reg (valid, np_debug_data_valid);
				while (!valid) nm_debug_get_reg(valid,np_debug_data_valid) ; 

                nm_debug_get_reg (data, np_debug_trace_address);
				*w++ = (unsigned char) data & 0x000000ff;
				*w++ = (unsigned char) (data>>8) & 0x000000ff;
#ifdef __nios32__
				*w++ = (unsigned char) (data>>16) & 0x000000ff;
				*w++ = (unsigned char) (data>>24) & 0x000000ff;
#endif

				nm_debug_get_reg (data, np_debug_trace_data);
				*w++ = (unsigned char) data & 0x000000ff;
				*w++ = (unsigned char) (data>>8) & 0x000000ff;
#ifdef __nios32__
				*w++ = (unsigned char) (data>>16) & 0x000000ff;
				*w++ = (unsigned char) (data>>24) & 0x000000ff;
#endif

				nm_debug_get_reg (*w++, np_debug_trace_code);
			}

			*w++ = 0;
			//if one of our data packets doesn't make it, stop sending them
			if (PutTracePacket (aBuffer,dataAccumulate+2) != 1) //+2 for size filed
				byteCount = 0;
		}
		return 1;
	}
	return 0;
}

#undef stepsize 
#undef MAX_TRACE_BYTES	

#endif

void DoGDBCommand_m(char *aBuffer)
	{
	char *w;
	int startAddr,byteCount;

#if nasys_debug_core
	/* intercept some access to the dbg peripheral */
	if (Trace_Read_Intercept (aBuffer)) return;
#endif

	w = aBuffer;
	w++;				// past 'm'
	w = Hex2Value(w,&startAddr);
	w++;				// past ','
	w = Hex2Value(w,&byteCount);

	if (byteCount > MAX_DATA_SIZE) byteCount = MAX_DATA_SIZE;

	// mA,L -- request memory
	w = aBuffer;
	w = MemToHex((char *)startAddr,w,byteCount);
	PutGDBPacket(aBuffer);
	}

void DoGDBCommand_M(char *aBuffer)
	{
	char *w;
	int startAddr,byteCount;

	w = aBuffer;
	w++;				// past 'M'
	w = Hex2Value(w,&startAddr);
	w++;				// past ','
	w = Hex2Value(w,&byteCount);
	w++;				// past ':'

	GDB_Print2("M from %x to %x",startAddr,byteCount);

⌨️ 快捷键说明

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