From df52af30c6179880a48c6a6e548e379f684d0b07 Mon Sep 17 00:00:00 2001
From: cnlohr <lohr85@gmail.com>
Date: Fri, 23 Jun 2023 15:27:40 -0400
Subject: [PATCH]  * Fix escape structure  * Fix checksum calculation for
 escape  * Add vFlashWrite, vFlashErase and vFlashDone

Closes #159
---
 minichlink/microgdbstub.h | 85 +++++++++++++++++++++++++++++++++------
 minichlink/minichgdb.c    | 21 ++++++++++
 2 files changed, 93 insertions(+), 13 deletions(-)

diff --git a/minichlink/microgdbstub.h b/minichlink/microgdbstub.h
index 6f6500a..ef39150 100644
--- a/minichlink/microgdbstub.h
+++ b/minichlink/microgdbstub.h
@@ -34,6 +34,8 @@ void RVCommandResetPart( void * dev );
 void RVHandleDisconnect( void * dev );
 void RVHandleGDBBreakRequest( void * dev );
 void RVHandleKillRequest( void * dev );
+int RVErase( void * dev, uint32_t memaddy, uint32_t length );
+int RVWriteFlash( void * dev, uint32_t memaddy, uint32_t length, uint8_t * payload );
 
 #ifdef MICROGDBSTUB_SOCKETS
 int MicroGDBPollServer( void * dev );
@@ -87,7 +89,7 @@ char gdbbuffer[65536];
 uint8_t gdbchecksum = 0;
 int gdbbufferplace = 0;
 int gdbbufferstate = 0;
-
+int gdbrunningcsum = 0;
 
 static inline char ToHEXNibble( int i )
 {
@@ -161,6 +163,7 @@ void SendReplyFull( const char * replyMessage )
 void HandleGDBPacket( void * dev, char * data, int len )
 {
 	int i;
+	char * odata = data;
 
 	// Got a packet?
 	if( data[0] != '$' ) return;
@@ -310,15 +313,58 @@ void HandleGDBPacket( void * dev, char * data, int len )
 		break;
 	}
 	case 'v':
-		if( StringMatch( data, "Cont?" ) )
+		if( StringMatch( data, "Cont" ) ) // vCont?
 		{
 			// Request a list of actions supported by the ‘vCont’ packet. 
 			// We don't support vCont
-			SendReplyFull( "vCont;;c;;" ); //no ;s or ;t because we don't implement them.
+			SendReplyFull( "vCont;s;c;;" ); //no ;t because we don't implement them.
+		}
+		else if( StringMatch( data, "MustReplyEmpty" ) ) //vMustReplyEmpty
+		{
+			SendReplyFull( "" );
+		}
+		else if( StringMatch( data, "FlashDone" ) )   //vFlashDone
+		{
+			SendReplyFull( "OK" );
+		}
+		else if( StringMatch( data, "FlashErase" ) ) //vFlashErase
+		{
+			data += 10; // FlashErase
+			if( *(data++) != ':' ) goto err;
+			uint32_t address_to_erase = 0;
+			uint32_t length_to_erase = 0;
+			if( ReadHex( &data, -1, &address_to_erase ) < 0 ) goto err;
+			if( *(data++) != ',' ) goto err;
+			if( ReadHex( &data, -1, &length_to_erase ) < 0 ) goto err;
+
+			if( RVErase( dev, address_to_erase, length_to_erase ) == 0 )
+				SendReplyFull( "OK" ); 
+			else
+				SendReplyFull( "E 93" );
+		}
+		else if( StringMatch( data, "FlashWrite" ) ) //vFlashWrite
+		{
+			data += 10; // FlashWrite
+
+			printf( "Write\n" );
+			if( *(data++) != ':' ) goto err;
+			uint32_t address_to_write = 0;
+			if( ReadHex( &data, -1, &address_to_write ) < 0 ) goto err;
+			if( *(data++) != ':' ) goto err;
+			int toflash = len - (data - odata) - 1;
+printf( "LEN: %08x %d %d %c\n", address_to_write, len, toflash, data[0] );
+			if( RVWriteFlash( dev, address_to_write, len, (uint8_t*)data ) == 0 )
+			{
+				printf( "Write OK\n" );
+				SendReplyFull( "OK" ); 
+			}
+			else
+				SendReplyFull( "E 93" );
 		}
 		else
 		{
-			SendReplyFull( "" ); //"vMustReplyEmpty"
+			printf( "Warning: Unknown v command %s\n", data );
+			SendReplyFull( "E 01" );
 		}
 		break;
 	case 'g':
@@ -381,6 +427,7 @@ void MicroGDBStubHandleClientData( void * dev, const uint8_t * rxdata, int len )
 		int c = rxdata[pl];
 		if( c == '$' && gdbbufferstate == 0 )
 		{
+			gdbrunningcsum = 0;
 			gdbbufferplace = 0;
 			gdbbufferstate = 1;
 		}
@@ -389,12 +436,12 @@ void MicroGDBStubHandleClientData( void * dev, const uint8_t * rxdata, int len )
 			RVHandleGDBBreakRequest( dev );
 			continue;
 		}
-
 		switch( gdbbufferstate )
 		{
 		default:
 			break;
 		case 1:
+			if( c != '#' ) gdbrunningcsum += (uint8_t)c;
 			if( gdbbufferplace < sizeof( gdbbuffer ) - 2 )
 			{
 				if( c == '}' ) { gdbbufferstate = 9; break; }
@@ -403,12 +450,18 @@ void MicroGDBStubHandleClientData( void * dev, const uint8_t * rxdata, int len )
 			if( c == '#' ) gdbbufferstate = 2;
 			break;
 		case 9: // escape
-			gdbbuffer[gdbbufferplace++] = c ^ 0x20;
+			gdbrunningcsum += (uint8_t)c;
+			if( gdbbufferplace < sizeof( gdbbuffer ) - 2 )
+			{
+				char escaped = c ^ 0x20;
+				gdbbuffer[gdbbufferplace++] = escaped;
+				printf( "ESCAPED @ %02x -> %c [%d]\n", gdbbufferplace, escaped, escaped );
+				gdbbufferstate = 1;
+			}
 			break;
 		case 2:
 		case 3:
 		{
-			int i;
 			c = fromhex( c );
 			if( gdbbufferstate == 2 )
 			{
@@ -420,18 +473,24 @@ void MicroGDBStubHandleClientData( void * dev, const uint8_t * rxdata, int len )
 			
 			gdbbuffer[gdbbufferplace] = 0;
 
-			uint8_t checkcsum = 0;
-			for( i = 1; i < gdbbufferplace - 1; i++ )
-			{
-				checkcsum += ((uint8_t*)gdbbuffer)[i];
-			}
-			if( checkcsum == gdbchecksum )
+			gdbrunningcsum = (gdbrunningcsum - '$')&0xff;
+
+			if( gdbrunningcsum == gdbchecksum )
 			{
 				MicroGDBStubSendReply( "+", -1, 0 );
 				HandleGDBPacket( dev, (char*)gdbbuffer, gdbbufferplace );
 			}
 			else
 			{
+				printf( "Checksum Error: Got %02x expected %02x / len: %d\n", gdbrunningcsum, gdbchecksum, gdbbufferplace );
+				int i;
+				for( i = 0; i < gdbbufferplace; i++ )
+				{
+					int c = ((uint8_t*)gdbbuffer)[i];
+					printf( "%02x [%c] ", c, (c>=32 && c < 128)?c:' ');
+					if( ( i & 0xf ) == 0xf ) printf( "\n" );
+				}
+				printf( "\n" );
 				MicroGDBStubSendReply( "-", -1, 0 );
 			}
 
diff --git a/minichlink/minichgdb.c b/minichlink/minichgdb.c
index 2943e96..2d839fd 100644
--- a/minichlink/minichgdb.c
+++ b/minichlink/minichgdb.c
@@ -391,6 +391,27 @@ int RVWriteRAM(void * dev, uint32_t memaddy, uint32_t length, uint8_t * payload
 	return r;
 }
 
+int RVWriteFlash(void * dev, uint32_t memaddy, uint32_t length, uint8_t * payload )
+{
+	if( (memaddy & 0xff000000 ) == 0 )
+	{
+		memaddy |= 0x08000000;
+	}
+	return RVWriteRAM( dev, memaddy, length, payload );
+}
+
+int RVErase( void * dev, uint32_t memaddy, uint32_t length )
+{
+	if( !MCF.Erase )
+	{
+		fprintf( stderr, "Error: Can't alter halt mode with this programmer.\n" );
+		exit( -6 );
+	}
+
+	int r = MCF.Erase( dev, memaddy, length, 0 ); // 0 = not whole chip.
+	return r;
+}
+
 void RVHandleDisconnect( void * dev )
 {
 	MCF.HaltMode( dev, 5 );
-- 
GitLab