From c0f6abedc5280d4d7b2718edbaaab23162054420 Mon Sep 17 00:00:00 2001
From: cnlohr <lohr85@gmail.com>
Date: Thu, 4 May 2023 05:52:07 -0400
Subject: [PATCH] Update minichlink for use with vs code.

---
 minichlink/microgdbstub.h |  7 ++-
 minichlink/minichgdb.c    | 94 +++++++++++++++++++++++++++++++--------
 minichlink/minichlink.c   |  4 ++
 3 files changed, 85 insertions(+), 20 deletions(-)

diff --git a/minichlink/microgdbstub.h b/minichlink/microgdbstub.h
index 669c080..bf04bc1 100644
--- a/minichlink/microgdbstub.h
+++ b/minichlink/microgdbstub.h
@@ -33,6 +33,7 @@ int RVHandleBreakpoint( void * dev, int set, uint32_t address );
 int RVWriteRAM(void * dev, uint32_t memaddy, uint32_t length, uint8_t * payload );
 void RVHandleDisconnect( void * dev );
 void RVHandleGDBBreakRequest( void * dev );
+void RVHandleKillRequest( void * dev );
 
 #ifdef MICROGDBSTUB_SOCKETS
 int MicroGDBPollServer( void * dev );
@@ -170,6 +171,9 @@ void HandleGDBPacket( void * dev, char * data, int len )
 		// Handle disconnect.
 		RVHandleDisconnect( dev );
 		break;
+	case 'k':
+		RVHandleKillRequest( dev ); // no reply.
+		break;
 	case 'Z':
 	case 'z':
 	{
@@ -249,8 +253,7 @@ void HandleGDBPacket( void * dev, char * data, int len )
 		{
 			// Request a list of actions supported by the ‘vCont’ packet. 
 			// We don't support vCont
-			SendReplyFull( "vCont;s;c;t;" ); //no ;s
-			//SendReplyFull( "" );
+			SendReplyFull( "vCont;s;c;t;" ); //no ;s maybe?
 		}
 		else
 		{
diff --git a/minichlink/minichgdb.c b/minichlink/minichgdb.c
index c3f783a..0596f4f 100644
--- a/minichlink/minichgdb.c
+++ b/minichlink/minichgdb.c
@@ -17,7 +17,7 @@ const char* MICROGDBSTUB_MEMORY_MAP = "l<?xml version=\"1.0\"?>"
 "    <property name=\"blocksize\">64</property>"
 "  </memory>"
 "  <memory type=\"ram\" start=\"0x20000000\" length=\"0x800\">"
-"    <property name=\"blocksize\">4</property>"
+"    <property name=\"blocksize\">1</property>"
 "  </memory>"
 "</memory-map>";
 
@@ -41,6 +41,10 @@ uint32_t previous_word_at_breakpoint_address[MAX_SOFTWARE_BREAKPOINTS];
 
 int IsGDBServerInShadowHaltState( void * dev ) { return !shadow_running_state; }
 
+static int InternalClearFlashOfSoftwareBreakpoint( void * dev, int i );
+static int InternalWriteBreakpointIntoAddress( void * v, int i );
+
+
 void RVCommandPrologue( void * dev )
 {
 	if( !MCF.ReadCPURegister )
@@ -62,6 +66,7 @@ void RVCommandEpilogue( void * dev )
 	MCF.WriteReg32( dev, DMABSTRACTAUTO, 0 );   // Disable autoexec.
 	MCF.WriteAllCPURegisters( dev, backup_regs );
 	MCF.VoidHighLevelState( dev );
+	MCF.WriteReg32( dev, DMDATA0, 0 );
 }
 
 void RVNetConnect( void * dev )
@@ -109,8 +114,6 @@ void RVNetPoll(void * dev )
 		if( statusrunning == 0 )
 		{
 			RVCommandPrologue( dev );
-			//uint32_t dscr;
-			//MCF.ReadCPURegister( dev, 0x7b0, &dscr );
 			last_halt_reason = 5;//((dscr>>6)&3)+5;
 			RVSendGDBHaltReason( dev );
 		}
@@ -145,24 +148,50 @@ void RVDebugExec( void * dev, int halt_reset_or_resume )
 	// Special case halt_reset_or_resume = 4: Skip instruction and resume.
 	if( halt_reset_or_resume == 4 || halt_reset_or_resume == 2 )
 	{
+		// First see if we already know about this breakpoint
+		int matchingbreakpoint = -1;
 		// For this we want to advance PC.
 		uint32_t exceptionptr = backup_regs[16];
 		uint32_t instruction = 0;
-		if( exceptionptr & 2 )
+
+		int i;
+		for( i = 0; i < MAX_SOFTWARE_BREAKPOINTS; i++ )
+		{
+			if( exceptionptr == software_breakpoint_addy[i] && software_breakpoint_type[i] )
+			{
+				matchingbreakpoint = i;
+			}
+		}
+
+		if( matchingbreakpoint >= 0 )
 		{
-			uint32_t part1, part2;
-			MCF.ReadWord( dev, exceptionptr & ~3, &part1 );
-			MCF.ReadWord( dev, (exceptionptr & ~3)+4, &part2 );
-			instruction = (part1 >> 16) | (part2 << 16);
+			// This is a known breakpoint.  Need to set it back.  Single Step.  Then continue.
+			InternalClearFlashOfSoftwareBreakpoint( dev, matchingbreakpoint );
+			MCF.SetEnableBreakpoints( dev, 1, 1 );
+			InternalWriteBreakpointIntoAddress( dev, matchingbreakpoint );
 		}
 		else
 		{
-			MCF.ReadWord( dev, exceptionptr, &instruction );
+			// Unknown breakpoint (was originally in the firmware)
+			// Just proceed past it.
+			if( exceptionptr & 2 )
+			{
+				uint32_t part1, part2;
+				MCF.ReadWord( dev, exceptionptr & ~3, &part1 );
+				MCF.ReadWord( dev, (exceptionptr & ~3)+4, &part2 );
+				instruction = (part1 >> 16) | (part2 << 16);
+			}
+			else
+			{
+				MCF.ReadWord( dev, exceptionptr, &instruction );
+			}
+			if( instruction == 0x00100073 )
+				backup_regs[16]+=4;
+			else if( ( instruction & 0xffff ) == 0x9002 )
+				backup_regs[16]+=2;
+			else
+				; //No change, it is a normal instruction.
 		}
-		if( instruction == 0x00100073 )
-			backup_regs[16]+=4;
-		else if( ( instruction & 0xffff ) == 0x9002 )
-			backup_regs[16]+=2;
 		halt_reset_or_resume = 2;
 	}
 
@@ -197,7 +226,7 @@ int RVReadMem( void * dev, uint32_t memaddy, uint8_t * payload, int len )
 	return ret;
 }
 
-static int InternalDisableBreakpoint( void * dev, int i )
+static int InternalClearFlashOfSoftwareBreakpoint( void * dev, int i )
 {
 	int r;
 	if( software_breakpoint_type[i] == 1 )
@@ -210,6 +239,33 @@ static int InternalDisableBreakpoint( void * dev, int i )
 		//16-bit instruction
 		r = MCF.WriteBinaryBlob( dev, software_breakpoint_addy[i], 2, (uint8_t*)&previous_word_at_breakpoint_address[i] );
 	}
+
+	return r;
+}
+
+static int InternalWriteBreakpointIntoAddress( void * dev, int i )
+{
+	int r;
+	uint32_t address = software_breakpoint_addy[i];
+	if( software_breakpoint_type[i] == 1 )
+	{
+		//32-bit instruction
+		uint32_t ebreak = 0x00100073; // ebreak
+		r = MCF.WriteBinaryBlob( dev, address, 4, (uint8_t*)&ebreak );
+	}
+	else
+	{
+		//16-bit instruction
+		uint32_t ebreak = 0x9002; // c.ebreak
+		r = MCF.WriteBinaryBlob( dev, address, 2, (uint8_t*)&ebreak );
+	}
+	return r;
+}
+
+static int InternalDisableBreakpoint( void * dev, int i )
+{
+	int r;
+	r = InternalClearFlashOfSoftwareBreakpoint( dev, i );
 	previous_word_at_breakpoint_address[i] = 0;
 	software_breakpoint_type[i] = 0;
 	software_breakpoint_addy[i] = 0;
@@ -259,8 +315,6 @@ int RVHandleBreakpoint( void * dev, int set, uint32_t address )
 				software_breakpoint_type[i] = 1;
 				software_breakpoint_addy[i] = address;
 				previous_word_at_breakpoint_address[i] = readval_at_addy;
-				uint32_t ebreak = 0x00100073; // ebreak
-				MCF.WriteBinaryBlob( dev, address, 4, (uint8_t*)&ebreak );
 			}
 			else
 			{
@@ -268,9 +322,8 @@ int RVHandleBreakpoint( void * dev, int set, uint32_t address )
 				software_breakpoint_type[i] = 2;
 				software_breakpoint_addy[i] = address;
 				previous_word_at_breakpoint_address[i] = readval_at_addy & 0xffff;
-				uint32_t ebreak = 0x9002; // c.ebreak
-				MCF.WriteBinaryBlob( dev, address, 2, (uint8_t*)&ebreak );
 			}
+			InternalWriteBreakpointIntoAddress( dev, i );
 		}
 		else
 		{
@@ -341,4 +394,9 @@ int SetupGDBServer( void * dev )
 	return MicroGDBStubStartup( dev );
 }
 
+void RVHandleKillRequest( void * dev )
+{
+	// Do nothing.
+}
+
 
diff --git a/minichlink/minichlink.c b/minichlink/minichlink.c
index 0b44dea..03cabbe 100644
--- a/minichlink/minichlink.c
+++ b/minichlink/minichlink.c
@@ -171,6 +171,10 @@ keep_going:
 					printf( "Error: can't start GDB server\n" );
 					return -1;
 				}
+				if( argchar[1] == 'G' )
+				{
+					printf( "GDBServer Running\n" );
+				}
 
 				do
 				{
-- 
GitLab