diff --git a/minichlink/minichlink.c b/minichlink/minichlink.c
index a69d711871f2e2f052d81b0980735c54f90c95ae..3548ed4f56b22b2c8064ce0ebf3d76ba755a7aee 100644
--- a/minichlink/minichlink.c
+++ b/minichlink/minichlink.c
@@ -355,27 +355,53 @@ int DefaultSetupInterface( void * dev )
 
 static int DefaultWriteWord( void * dev, uint32_t address_to_write, uint32_t data )
 {
-	printf( "Write Word %08x => %08x\n", data, address_to_write );
+//	printf( "Write Word %08x => %08x\n", data, address_to_write );
 	struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal);
 	uint32_t rrv;
 	int r;
 	int first = 0;
 
-	if( iss->statetag != STTAG( "WRSQ" ) || address_to_write != iss->currentstateval )
+	int flags = 0;
+	if( ( address_to_write & 0xff000000 ) == 0x08000000 )
+	{
+		flags = 1;
+	}
+
+	if( iss->statetag != STTAG( "WRSQ" ) || flags != iss->lastwriteflags )
 	{
 		MCF.WriteReg32( dev, DMABSTRACTAUTO, 0x00000000 ); // Disable Autoexec.
-		if(  iss->statetag != STTAG( "WRSQ" ) )
+		if( iss->statetag != STTAG( "WRSQ" ) || flags != iss->lastwriteflags )
 		{
 			// Different address, so we don't need to re-write all the program regs.
-			MCF.WriteReg32( dev, DMPROGBUF0, 0x0072a023 ); // sw x7,0(x5)
-			MCF.WriteReg32( dev, DMPROGBUF1, 0x00428293 ); // addi x5, x5, 4
-			MCF.WriteReg32( dev, DMPROGBUF2, 0x00100073 ); // ebreak
+			MCF.WriteReg32( dev, DMPROGBUF0, 0x00032283 ); // lw x5,0(x6)
+			MCF.WriteReg32( dev, DMPROGBUF1, 0x0072a023 ); // sw x7,0(x5)
+			MCF.WriteReg32( dev, DMPROGBUF2, 0x00428293 ); // addi x5, x5, 4
+			//MCF.WriteReg32( dev, DMPROGBUF3, 0x00532023 ); // sw x5,0(x6)
+			if( flags & 1 )
+			{
+				// After writing to memory, also hit up page load flag.
+				MCF.WriteReg32( dev, DMPROGBUF3, 0x00942023 ); // sw x9,0(x8)
+				MCF.WriteReg32( dev, DMPROGBUF4, 0x00100073 ); // ebreak
+
+				MCF.WriteReg32( dev, DMDATA0, (intptr_t)&FLASH->CTLR );
+				MCF.WriteReg32( dev, DMCOMMAND, 0x00231008 ); // Copy data to x8
+				MCF.WriteReg32( dev, DMDATA0, CR_PAGE_PG|CR_BUF_LOAD);
+				MCF.WriteReg32( dev, DMCOMMAND, 0x00231009 ); // Copy data to x9
+			}
+			else
+			{
+				MCF.WriteReg32( dev, DMPROGBUF3, 0x00100073 ); // ebreak
+			}
+
+
+			MCF.WriteReg32( dev, DMDATA0, 0xe00000f5); // Address of DATA1.
+			MCF.WriteReg32( dev, DMCOMMAND, 0x00231006 ); // Location of DATA1 to x6
 
 			// TODO: This code could also read from DATA1, and then that would go MUCH faster for random writes.
 		}
+		iss->lastwriteflags = flags;
 
-		MCF.WriteReg32( dev, DMDATA0, address_to_write );
-		MCF.WriteReg32( dev, DMCOMMAND, 0x00231005 ); // Copy data to x5
+		MCF.WriteReg32( dev, DMDATA1, address_to_write );
 
 		iss->statetag = STTAG( "WRSQ" );
 		iss->currentstateval = address_to_write;
@@ -384,6 +410,7 @@ static int DefaultWriteWord( void * dev, uint32_t address_to_write, uint32_t dat
 		MCF.WriteReg32( dev, DMCOMMAND, 0x00271007 ); // Copy data to x7, and execute program.
 		MCF.WriteReg32( dev, DMABSTRACTAUTO, 1 ); // Enable Autoexec.
 
+	/*
 		do
 		{
 			r = MCF.ReadReg32( dev, DMABSTRACTCS, &rrv );
@@ -394,9 +421,16 @@ static int DefaultWriteWord( void * dev, uint32_t address_to_write, uint32_t dat
 		{
 			fprintf( stderr, "Fault writing memory (DMABSTRACTS = %08x)\n", rrv );
 		}
+*/
 	}
 	else
 	{
+		if( address_to_write != iss->currentstateval )
+		{
+			MCF.WriteReg32( dev, DMABSTRACTAUTO, 0 ); // Disable Autoexec.
+			MCF.WriteReg32( dev, DMDATA1, address_to_write );
+			MCF.WriteReg32( dev, DMABSTRACTAUTO, 1 ); // Enable Autoexec.
+		}
 		MCF.WriteReg32( dev, DMDATA0, data );
 	}
 
@@ -408,6 +442,7 @@ static int DefaultWriteWord( void * dev, uint32_t address_to_write, uint32_t dat
 
 int DefaultWriteBinaryBlob( void * dev, uint32_t address_to_write, uint32_t blob_size, uint8_t * blob )
 {
+	uint32_t rw;
 	int timeout = 0;
 	struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal);
 	int is_flash = 0;
@@ -419,156 +454,78 @@ int DefaultWriteBinaryBlob( void * dev, uint32_t address_to_write, uint32_t blob
 		// Flash reg base = 0x40022000,
 		// FLASH_MODEKEYR => 0x40022024
 		// FLASH_KEYR => 0x40022004
-		printf( "UNLOCKING\n" );
-		MCF.WriteWord( dev, 0x40022004, 0x45670123 );
-		MCF.WriteWord( dev, 0x40022004, 0xCDEF89AB );
-		MCF.WriteWord( dev, 0x40022024, 0x45670123 );
-		MCF.WriteWord( dev, 0x40022024, 0xCDEF89AB );
-		uint32_t rv = 0xffffffff;
-
-		MCF.ReadWord( dev, 0x40022010, &rv );
-		printf( "FLASH CTR: %08x\n", rv );
-		is_flash = 1;
-	}
-/*
-	MCF.WriteReg32( dev, DMDATA0, address_to_write );
-	MCF.WriteReg32( dev, DMCOMMAND, 0x00231003 ); // Copy data to x3 (DATAADDRESS)
-	MCF.WriteReg32( dev, DMDATA0, FLASH_R_BASE + 0x10 );
-	MCF.WriteReg32( dev, DMCOMMAND, 0x00231004 ); // Copy data to x4 (CTLR)
-	MCF.WriteReg32( dev, DMDATA0, FLASH_R_BASE + 0x14 );
-	MCF.WriteReg32( dev, DMCOMMAND, 0x00231005 ); // Copy data to x5 (ADDR)
-
-	MCF.WriteReg32( dev, DMDATA0, CR_PAGE_ER );
-	MCF.WriteReg32( dev, DMCOMMAND, 0x00231006 ); // Copy flag 1 to x6 (CR_PAGE_ER)
-	MCF.WriteReg32( dev, DMDATA0, CR_STRT_Set | CR_PAGE_ER );
-	MCF.WriteReg32( dev, DMCOMMAND, 0x00231007 ); // Copy flag 2 to x7 (CR_STRT_Set)
-
-	MCF.WriteReg32( dev, DMPROGBUF0, 0x00022403 ); // lw x8,0(x4)
-	MCF.WriteReg32( dev, DMPROGBUF1, 0x00646433 ); // or x8, x8, x6
-	MCF.WriteReg32( dev, DMPROGBUF2, 0x00822023 ); // sw x8,0(x4)
-	MCF.WriteReg32( dev, DMPROGBUF3, 0x0032a023 ); // sw x3,0(x5)
-//	MCF.WriteReg32( dev, DMPROGBUF4, 0x00022023 ); // sw x0,0(x4)
-	MCF.WriteReg32( dev, DMPROGBUF4, 0x00100073 ); // ebreak
-	MCF.WriteReg32( dev, DMCOMMAND, 0x00250000 ); // Copy data to x7, and execute program.
-	MCF.WriteReg32( dev, DMABSTRACTAUTO, 1 ); // Enable Autoexec.
-	return 0;
 
-
-*/
-	uint32_t wp = address_to_write;
-	uint32_t ew = wp + blob_size;
-	int group = -1;
-	lastgroup = -1;
-
-	while( wp <= ew )
-	{
-		if( is_flash )
+		if( !iss->flash_unlocked )
 		{
-			group = (wp & 0xffffffc0);
-			if( group != lastgroup )
+			MCF.ReadWord( dev, 0x40022010, &rw ); 
+			if( rw & 0x8080 ) 
 			{
-				uint32_t rw = 0xffffffff;
-				// 16.4.7, Steps 1+2  (Make sure flash isn't locked)
+				MCF.WriteWord( dev, 0x40022004, 0x45670123 );
+				MCF.WriteWord( dev, 0x40022004, 0xCDEF89AB );
+				MCF.WriteWord( dev, 0x40022024, 0x45670123 );
+				MCF.WriteWord( dev, 0x40022024, 0xCDEF89AB );
 				MCF.ReadWord( dev, 0x40022010, &rw ); 
 				if( rw & 0x8080 ) 
 				{
 					fprintf( stderr, "Error: Flash is not unlocked\n" );
 					return -9;
 				}
+			}
+			iss->flash_unlocked = 1;
+		}
 
-				// 16.4.7, Step 3: Check the BSY bit of the FLASH_STATR register to confirm that there are no other programming operations in progress.
-				// skip (we make sure at the end)
-
-				// Step 4:  set PAGE_ER of FLASH_CTLR(0x40022010)
-				MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_PAGE_ER ); // Actually FTER
-
-				// Step 5: Write the first address of the fast erase page to the FLASH_ADDR register.
-				MCF.WriteWord( dev, (intptr_t)&FLASH->ADDR, group );
-
-				// Step 6: Set the STAT bit of FLASH_CTLR register to '1' to initiate a fast page erase (64 bytes) action.
-				MCF.ReadWord( dev, (intptr_t)&FLASH->CTLR, &rw ); 
-				printf( "FLASH_CTLR = %08x\n", rw );
-				MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_STRT_Set|CR_PAGE_ER );
-				do
-				{
-					rw = 0;
-					MCF.ReadWord( dev, (intptr_t)&FLASH->STATR, &rw ); // FLASH_STATR => 0x4002200C
-					printf( "FLASH_STATR %08x %d\n", rw,__LINE__ );
-					if( timeout++ > 100 ) goto timedout;
-				} while(rw & 1);  // BSY flag.
-
-				MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, 0 );
-
-				// Step 7: Wait for the BSY bit to become '0' or the EOP bit of FLASH_STATR register to be '1' to indicate the endof erase, and clear the EOP bit to 0.
-				do
-				{
-					rw = 0;
-					MCF.ReadWord( dev, (intptr_t)&FLASH->STATR, &rw ); // FLASH_STATR => 0x4002200C
-					printf( "FLASH_STATR %08x\n", rw );
-					if( timeout++ > 100 ) goto timedout;
-				} while(rw & 1);  // BSY flag.
-				if( rw & FLASH_STATR_WRPRTERR )
-				{
-					fprintf( stderr, "Memory Protection Error\n" );
-					return -44;
-				}
-
-				MCF.ReadWord( dev, (intptr_t)&FLASH->CTLR, &rw );
-				printf( "FLASH_CTLR = %08x\n", rw );
-
-
-				MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_BUF_RST | CR_PAGE_PG );
-				do
-				{
-					rw = 0;
-					MCF.ReadWord( dev, (intptr_t)&FLASH->STATR, &rw ); // FLASH_STATR => 0x4002200C
-					printf( "FLASH_STATR %08x\n", rw );
-					if( timeout++ > 100 ) goto timedout;
-				} while(rw & 1);  // BSY flag.
-
-				int j;
-				for( j = 0; j < 16; j++ )
-				{
-					MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_PAGE_PG );
-					MCF.WriteWord( dev, wp, 0x0000ffff );
-					wp += 4; 
+		is_flash = 1;
 
-					MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_BUF_LOAD );
-					do
-					{
-						rw = 0;
-						MCF.ReadWord( dev, (intptr_t)&FLASH->STATR, &rw ); // FLASH_STATR => 0x4002200C
-						printf( "FLASH_STATR %08x\n", rw );
-						if( timeout++ > 100 ) goto timedout;
-					} while(rw & 1);  // BSY flag.
-				}
-				printf( "Group written.\n" );
+		uint32_t i;
+		for( i = address_to_write; i < address_to_write + blob_size; i+= 64 )
+		{
+			MCF.Erase( dev, i, 0 );
+		}
+	}
 
-				MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_PAGE_PG );
-				MCF.WriteWord( dev, (intptr_t)&FLASH->ADDR, group );
-				MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_PAGE_PG|CR_STRT_Set );
+	MCF.FlushLLCommands( dev );
+	MCF.DelayUS( dev, 100 ); // Why do we need this?
 
-				do
-				{
-					rw = 0;
-					MCF.ReadWord( dev, (intptr_t)&FLASH->STATR, &rw ); // FLASH_STATR => 0x4002200C
-					printf( "FLASH_STATR %08x\n", rw );
-					if( timeout++ > 100 ) goto timedout;
-				} while(rw & 1);  // BSY flag.
-				MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, 0 );
-				do
-				{
-					rw = 0;
-					MCF.ReadWord( dev, (intptr_t)&FLASH->STATR, &rw ); // FLASH_STATR => 0x4002200C
-					printf( "FLASH_STATR %08x\n", rw );
-					if( timeout++ > 100 ) goto timedout;
-				} while(rw & 1);  // BSY flag.
+	uint32_t wp = address_to_write;
+	uint32_t ew = wp + blob_size;
+	int group = -1;
+	lastgroup = -1;
 
-				lastgroup = group;
+	while( wp <= ew )
+	{
+		if( is_flash )
+		{
+			group = (wp & 0xffffffc0);
 
-				// Step 4:  set PAGE_ER of FLASH_CTLR(0x40022010)
-//				MCF.WriteWord( dev, FLASH_R_BASE + 0x10, 0 );
+			MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_PAGE_PG ); // THIS IS REQUIRED.
+			MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_BUF_RST | CR_PAGE_PG );
+			MCF.DelayUS( dev, 290 ); // 1us is sufficient.
+/*
+			do
+			{
+				rw = 0;
+				MCF.ReadWord( dev, (intptr_t)&FLASH->STATR, &rw ); // FLASH_STATR => 0x4002200C
+				if( timeout++ > 100 ) goto timedout;
+			} while(rw & 1);  // BSY flag.
+			MCF.WriteWord( dev, (intptr_t)&FLASH->STATR, rw );
+*/
+			int j;
+			for( j = 0; j < 16; j++ )
+			{
+				int index = (wp-address_to_write);
+				uint32_t data = 0xffffffff;
+				if( index + 3 < blob_size )
+					data = ((uint32_t*)blob)[index/4];
+				MCF.WriteWord( dev, wp, data );
+				wp += 4;
 			}
+			MCF.FlushLLCommands( dev );
+			MCF.WriteWord( dev, (intptr_t)&FLASH->ADDR, group );
+			MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_PAGE_PG|CR_STRT_Set );
+			MCF.DelayUS( dev, 200 ); // 1us is sufficient.
+			MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, 0 );
+//			MCF.FlushLLCommands( dev );
+			lastgroup = group;
 		}
 		//MCF.WriteWord( dev, wp, *(((uint32_t*)blob)+4) ); //Write data.
 		//MCF.WriteWord( dev, 0x40022010, (1<<16)|(1<<18) ); //Enable BUFLOAD.
@@ -578,6 +535,16 @@ int DefaultWriteBinaryBlob( void * dev, uint32_t address_to_write, uint32_t blob
 //	MCF.WriteReg32( dev, DMCONTROL, 0x80000001 ); // Make the debug module work properly.
 //	MCF.WriteReg32( dev, DMCONTROL, 0x80000001 ); // Initiate a halt request.
 //	MCF.WriteReg32( dev, DMCONTROL, 0x00000001 ); // Clear Halt Request.
+
+	if( is_flash )
+	{
+		MCF.ReadWord( dev, (intptr_t)&FLASH->STATR, &rw ); // FLASH_STATR => 0x4002200C
+		if( rw & FLASH_STATR_WRPRTERR )
+		{
+			fprintf( stderr, "Memory Protection Error\n" );
+			return -44;
+		}
+	}
 	return 0;
 timedout:
 	fprintf( stderr, "Timed out\n" );
@@ -635,6 +602,103 @@ static int DefaultReadWord( void * dev, uint32_t address_to_read, uint32_t * dat
 	return MCF.ReadReg32( dev, DMDATA0, data );
 }
 
+int DefaultErase( void * dev, uint32_t address, int type )
+{
+	struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal);
+	uint32_t rw;
+	uint32_t timeout = 0;
+
+	if( !iss->flash_unlocked )
+	{
+		MCF.ReadWord( dev, 0x40022010, &rw ); 
+		if( rw & 0x8080 ) 
+		{
+			MCF.WriteWord( dev, 0x40022004, 0x45670123 );
+			MCF.WriteWord( dev, 0x40022004, 0xCDEF89AB );
+			MCF.WriteWord( dev, 0x40022024, 0x45670123 );
+			MCF.WriteWord( dev, 0x40022024, 0xCDEF89AB );
+			MCF.ReadWord( dev, 0x40022010, &rw );
+			if( rw & 0x8080 ) 
+			{
+				fprintf( stderr, "Error: Flash is not unlocked\n" );
+				return -9;
+			}
+		}
+		iss->flash_unlocked = 1;
+	}
+
+	if( type == 1 )
+	{
+		// Whole-chip flash
+		printf( "Whole-chip erase\n" );
+		iss->statetag = STTAG( "XXXX" );
+		do
+		{
+			rw = 0;
+			MCF.ReadWord( dev, (intptr_t)&FLASH->STATR, &rw ); // FLASH_STATR => 0x4002200C
+			if( timeout++ > 100 ) goto timedout;
+		} while(rw & 1);  // BSY flag.
+		MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, 0 );
+		MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, FLASH_CTLR_MER  );
+		MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_STRT_Set|FLASH_CTLR_MER );
+		do
+		{
+			rw = 0;
+			MCF.ReadWord( dev, (intptr_t)&FLASH->STATR, &rw ); // FLASH_STATR => 0x4002200C
+			if( timeout++ > 100 ) goto timedout;
+		} while(rw & 1);  // BSY flag.
+		MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, 0 );
+
+		MCF.ReadWord( dev, (intptr_t)&FLASH->STATR, &rw ); // FLASH_STATR => 0x4002200C
+		if( rw & FLASH_STATR_WRPRTERR )
+		{
+			fprintf( stderr, "Memory Protection Error\n" );
+			return -44;
+		}
+	}
+	else
+	{
+		// 16.4.7, Step 3: Check the BSY bit of the FLASH_STATR register to confirm that there are no other programming operations in progress.
+		// skip (we make sure at the end)
+
+		// Step 4:  set PAGE_ER of FLASH_CTLR(0x40022010)
+		MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_PAGE_ER ); // Actually FTER
+
+		// Step 5: Write the first address of the fast erase page to the FLASH_ADDR register.
+		MCF.WriteWord( dev, (intptr_t)&FLASH->ADDR, address  );
+
+		// Step 6: Set the STAT bit of FLASH_CTLR register to '1' to initiate a fast page erase (64 bytes) action.
+//		MCF.ReadWord( dev, (intptr_t)&FLASH->CTLR, &rw ); 
+		MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_STRT_Set|CR_PAGE_ER );
+/*
+		do
+		{
+			rw = 0;
+			MCF.ReadWord( dev, (intptr_t)&FLASH->STATR, &rw ); // FLASH_STATR => 0x4002200C
+			printf( "FLASH_STATR %08x %d\n", rw,__LINE__ );
+			if( timeout++ > 100 ) goto timedout;
+		} while(rw & 1);  // BSY flag.
+*/
+		MCF.DelayUS( dev, 400 );
+		MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, 0  );
+		MCF.DelayUS( dev, 400 );
+
+		// Step 7: Wait for the BSY bit to become '0' or the EOP bit of FLASH_STATR register to be '1' to indicate the endof erase, and clear the EOP bit to 0.
+/*
+		do
+		{
+			rw = 0;
+			MCF.ReadWord( dev, (intptr_t)&FLASH->STATR, &rw ); // FLASH_STATR => 0x4002200C
+			printf( "FLASH_STATR %08x\n", rw );
+			if( timeout++ > 100 ) goto timedout;
+		} while(rw & 1);  // BSY flag.
+*/
+	}
+	return 0;
+timedout:
+	return -6;
+}
+
 int DefaultReadBinaryBlob( void * dev, uint32_t address_to_read_from, uint32_t read_size, uint8_t * blob )
 {
 	struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal);
@@ -656,6 +720,7 @@ void TestFunction(void * dev )
 	MCF.WriteReg32( dev, DMCONTROL, 0x80000001 ); // Initiate a halt request.
 	MCF.WriteReg32( dev, DMCONTROL, 0x00000001 ); // Clear Halt Request.
 
+	MCF.Erase( dev, 0, 1 );
 
 	r = MCF.WriteWord( dev, 0x20000100, 0xdeadbeef );
 	printf( "%d\n", r );
@@ -669,20 +734,39 @@ void TestFunction(void * dev )
 	printf( "%d\n", r );
 
 	r = MCF.ReadWord( dev, 0x20000100, &rv );
-	printf( "%d %08x\n", r, rv );
+	printf( ">>> %d %08x\n", r, rv );
 	r = MCF.ReadWord( dev, 0x20000104, &rv );
-	printf( "%d %08x\n", r, rv );
+	printf( ">>> %d %08x\n", r, rv );
 	r = MCF.ReadWord( dev, 0x20000108, &rv );
-	printf( "%d %08x\n", r, rv );
+	printf( ">>> %d %08x\n", r, rv );
+
+	MCF.WriteBinaryBlob( dev, 0x08000200, 16, "****************" );
+
+
 
-	
-	MCF.WriteBinaryBlob( dev, 0x08000300, 16, "hello, world!!\n" );
 	r = MCF.ReadWord( dev, 0x00000300, &rv );
-	printf( "%d %08x\n", r, rv );
+	printf( "F %d %08x\n", r, rv );
 	r = MCF.ReadWord( dev, 0x00000304, &rv );
-	printf( "%d %08x\n", r, rv );
+	printf( "F %d %08x\n", r, rv );
 	r = MCF.ReadWord( dev, 0x00000308, &rv );
-	printf( "%d %08x\n", r, rv );
+	printf( "F %d %08x\n", r, rv );
+
+	MCF.WriteBinaryBlob( dev, 0x08000300, 16, "                " );
+
+	r = MCF.ReadWord( dev, 0x00000300, &rv );
+	printf( "F %d %08x\n", r, rv );
+	r = MCF.ReadWord( dev, 0x00000304, &rv );
+	printf( "F %d %08x\n", r, rv );
+	r = MCF.ReadWord( dev, 0x00000308, &rv );
+	printf( "F %d %08x\n", r, rv );
+
+
+	r = MCF.ReadWord( dev, 0x00000200, &rv );
+	printf( "F %d %08x\n", r, rv );
+	r = MCF.ReadWord( dev, 0x00000204, &rv );
+	printf( "F %d %08x\n", r, rv );
+	r = MCF.ReadWord( dev, 0x00000208, &rv );
+	printf( "F %d %08x\n", r, rv );
 
 }
 
@@ -706,6 +790,8 @@ int SetupAutomaticHighLevelFunctions( void * dev )
 		MCF.WriteWord = DefaultWriteWord;
 	if( !MCF.ReadWord )
 		MCF.ReadWord = DefaultReadWord;
+	if( !MCF.Erase )
+		MCF.Erase = DefaultErase;
 
 	struct InternalState * iss = malloc( sizeof( struct InternalState ) );
 	iss->statetag = 0;
diff --git a/minichlink/minichlink.h b/minichlink/minichlink.h
index 76f571b6167fe1e518354e93478235f83dbfa9d2..eac52b227b3e9b14db1506555d4ae6c63521bee1 100644
--- a/minichlink/minichlink.h
+++ b/minichlink/minichlink.h
@@ -28,9 +28,10 @@ struct MiniChlinkFunctions
 	// WARNING: Writing binary blobs may write groups of 64-bytes.
 	int (*WriteBinaryBlob)( void * dev, uint32_t address_to_write, uint32_t blob_size, uint8_t * blob );
 	int (*ReadBinaryBlob)( void * dev, uint32_t address_to_read_from, uint32_t read_size, uint8_t * blob );
+	int (*Erase)( void * dev, uint32_t address, int type ); //type = 0 for fast, 1 for whole-chip
 
 	// MUST be 4-byte-aligned.
-	int (*WriteWord)( void * dev, uint32_t address_to_write, uint32_t data );
+	int (*WriteWord)( void * dev, uint32_t address_to_write, uint32_t data ); // Flags = 1 for "doing a fast FLASH write."
 	int (*ReadWord)( void * dev, uint32_t address_to_read, uint32_t * data );
 };
 
@@ -47,6 +48,8 @@ struct InternalState
 {
 	uint32_t statetag;
 	uint32_t currentstateval;
+	uint32_t flash_unlocked;
+	int lastwriteflags;
 };
 
 
diff --git a/minichlink/pgm-esp32s2-ch32xx.c b/minichlink/pgm-esp32s2-ch32xx.c
index e12fabd661dc98ef937814e39c6e3eb2219805d5..91d0e568f6620f9f1ae83e537d37fc54937df5fa 100644
--- a/minichlink/pgm-esp32s2-ch32xx.c
+++ b/minichlink/pgm-esp32s2-ch32xx.c
@@ -18,7 +18,7 @@ int ESPFlushLLCommands( void * dev );
 
 static inline int SRemain( struct ESP32ProgrammerStruct * e )
 {
-	return sizeof( e->commandbuffer ) - e->commandplace - 1; //Need room for EOF.
+	return sizeof( e->commandbuffer ) - e->commandplace - 2; //Need room for EOF.
 }
 
 static inline void Write4LE( struct ESP32ProgrammerStruct * e, uint32_t val )
@@ -90,6 +90,7 @@ int ESPFlushLLCommands( void * dev )
 	}
 	int r;
 
+	printf( "FLUSH: %d\n", eps->commandplace );
 	eps->commandbuffer[0] = 0xad; // Key report ID
 	eps->commandbuffer[eps->commandplace] = 0xff;
 	r = hid_send_feature_report( eps->hd, eps->commandbuffer, 255 );