source code for all my flash stuff, now finally in cvs


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4083 a1c6a512-1295-4272-9138-f99709370657
diff --git a/flash/uart_boot/README b/flash/uart_boot/README
new file mode 100644
index 0000000..edfa20c
--- /dev/null
+++ b/flash/uart_boot/README
@@ -0,0 +1,8 @@
+(c) 2003 by Jörg Hohensohn
+
+This is the client side for MiniMon, a command line program that communicates with it.
+It can be used to reflash a box from ground up, load a program like gdb stub or Rockbox, 
+and other diagnostics.
+
+Current implementation is for Windows, but with a different UART implementation
+it should work for other platforms (Linux) as well.
diff --git a/flash/uart_boot/client.c b/flash/uart_boot/client.c
new file mode 100644
index 0000000..a98edc6
--- /dev/null
+++ b/flash/uart_boot/client.c
@@ -0,0 +1,738 @@
+// client.cpp : functions for monitor download and communication.
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "scalar_types.h" // (U)INT8/16/32
+#include "Uart.h" // platform abstraction for UART
+#include "minimon.h" // protocol of my little monitor
+
+// do the baudrate configuration for the Player
+int ConfigFirstlevelPlayer (tUartHandle serial_handle)
+{
+	UINT32 result_nbr;
+
+	if(!UartConfig(serial_handle, 4800, eMARKPARITY, eTWOSTOPBITS, 8))
+	{
+		UINT32 dwErr = GET_LAST_ERR();
+		printf("Error %d setting up COM params for baudrate byte\n", dwErr);
+		exit(1);
+	}
+
+	// this will read as 0x19 when viewed with 2300 baud like the player does
+	result_nbr = UartWrite(serial_handle, (UINT8*)"\x86\xC0", 2);
+	if (result_nbr != 2)
+	{
+		UINT32 dwErr = GET_LAST_ERR();
+		printf("Error %d setting up COM params for baudrate byte\n", dwErr);
+	}
+
+	SLEEP(100); // wait for the chars to be sent, is there a better way?
+
+	// the read 0x19 means 14423 baud with 12 MHz
+	if(!UartConfig(serial_handle, 14400, eNOPARITY, eONESTOPBIT, 8))
+	{
+		printf("Error setting up COM params for 1st level loader\n");
+		exit(1);
+	}
+
+	return 0;
+}
+
+
+// do the baudrate configuration for the Recoder/FM
+int ConfigFirstlevelRecorder (tUartHandle serial_handle)
+{
+	UINT32 result_nbr;
+
+	if(!UartConfig(serial_handle, 4800, eNOPARITY, eTWOSTOPBITS, 8))
+	{
+		UINT32 dwErr = GET_LAST_ERR();
+		printf("Error %d setting up COM params for baudrate byte\n", dwErr);
+		exit(1);
+	}
+
+	// this will read as 0x08 when viewed with 2120 baud like the recorder does
+	result_nbr = UartWrite(serial_handle, (UINT8*)"\x00\x00", 2);
+	if(result_nbr != 2)
+	{
+		printf("Error transmitting baudrate byte\n");
+		exit(1);
+	}
+
+	SLEEP(100); // wait for the chars to be sent, is there a better way?
+
+	// the read 0x08 means 38400 baud with 11.0592 MHz
+	if(!UartConfig(serial_handle, 38400, eNOPARITY, eONESTOPBIT, 8))
+	{
+		UINT32 dwErr = GET_LAST_ERR();
+		printf("Error %d setting up COM params for 1st level loader\n", dwErr);
+		exit(1);
+	}
+
+	return 0;
+}
+
+
+// transfer a byte for the monitor download, with or without acknowledge
+int DownloadByte(tUartHandle serial_handle, unsigned char byte, bool bAck)
+{
+	unsigned char received;
+	bool bRecorder = true; // false for player
+
+	while (1)
+	{
+		UartWrite(serial_handle, &byte, 1);
+		if (bAck)
+		{
+			UartRead(serial_handle, &received, 1);
+			if (received == byte)
+			{
+				UartWrite(serial_handle, (UINT8*)"\x01", 1); // ack success
+				break; // exit the loop
+			}
+			else
+			{
+				printf("Error transmitting monitor byte 0x%02X, got 0x%0X\n", byte, received);
+				UartWrite(serial_handle, (UINT8*)"\x00", 1); // ack fail, try again
+			}
+		}
+		else
+			break; // no loop
+	}
+	return 1;
+}
+
+
+// download our little monitor, the box must have been just freshly switched on for this to work
+int DownloadMonitor(tUartHandle serial_handle, bool bRecorder, char* szFilename)
+{
+	FILE* pFile;
+	size_t filesize;
+	UINT8 byte;
+	unsigned i;
+
+	// hard-coded parameters
+	bool bAck = true; // configure if acknowledged download (without useful for remote pin boot)
+	UINT32 TargetLoad = 0x0FFFF000; // target load address
+
+	pFile = fopen(szFilename, "rb");
+	if (pFile == NULL)
+	{
+		printf("\nMonitor file %s not found, exiting\n", szFilename);
+		exit(1);
+	}
+
+	// determine file size
+	fseek(pFile, 0, SEEK_END);
+	filesize = ftell(pFile);
+	fseek(pFile, 0, SEEK_SET);
+
+	// This is _really_ tricky! The box expects a BRR value in a nonstandard baudrate,
+	//	which a PC can't generate. I'm using a higher one with some wild settings
+	//	to generate a pulse series that:
+	//	1) looks like a stable byte when sampled with the nonstandard baudrate
+	//	2) gives a BRR value to the box which results in a baudrate the PC can also use
+	if (bRecorder)
+	{
+		ConfigFirstlevelRecorder(serial_handle);
+	}
+	else
+	{
+		ConfigFirstlevelPlayer(serial_handle);
+	}
+
+	UartWrite(serial_handle, bAck ? (UINT8*)"\x01" : (UINT8*)"\x00", 1); // ACK mode
+
+	// transmit the size, little endian
+	DownloadByte(serial_handle, (UINT8)( filesize	   & 0xFF), bAck);
+	DownloadByte(serial_handle, (UINT8)((filesize>>8)  & 0xFF), bAck);
+	DownloadByte(serial_handle, (UINT8)((filesize>>16) & 0xFF), bAck);
+	DownloadByte(serial_handle, (UINT8)((filesize>>24) & 0xFF), bAck);
+
+	// transmit the load address, little endian
+	DownloadByte(serial_handle, (UINT8)( TargetLoad 	 & 0xFF), bAck);
+	DownloadByte(serial_handle, (UINT8)((TargetLoad>>8)  & 0xFF), bAck);
+	DownloadByte(serial_handle, (UINT8)((TargetLoad>>16) & 0xFF), bAck);
+	DownloadByte(serial_handle, (UINT8)((TargetLoad>>24) & 0xFF), bAck);
+
+	// transmit the command byte
+	DownloadByte(serial_handle, 0xFF, bAck); // 0xFF means execute the transferred image
+
+	// transmit the image
+	for (i=0; i<filesize; i++)
+	{
+		fread(&byte, 1, 1, pFile);
+		DownloadByte(serial_handle, byte, bAck);
+	}
+
+	fclose (pFile);
+
+	// now the image should have been started, red LED off
+
+	return 0;
+}
+
+
+// wait for a fixed string to be received (no foolproof algorithm,
+//	may overlook if the searched string contains repeatitions)
+int WaitForString(tUartHandle serial_handle, char* pszWait)
+{
+	int i = 0;
+	unsigned char received;
+	
+	while(pszWait[i] != '\0')
+	{
+		UartRead(serial_handle, &received, 1);
+
+		printf("%c", received); // debug
+
+		if (received == pszWait[i])
+			i++; // continue
+		else 
+			i=0; // mismatch, start over
+	}
+	return 0;
+}
+
+
+// send a sting and check the echo
+int SendWithEcho(tUartHandle serial_handle, char* pszSend)
+{
+	int i = 0;
+	unsigned char received;
+	
+	while(pszSend[i] != '\0')
+	{
+		UartWrite(serial_handle, (unsigned char*)(pszSend + i), 1); // send char
+		do
+		{
+			UartRead(serial_handle, &received, 1); // receive echo
+			printf("%c", received); // debug
+		}
+		while (received != pszSend[i]); // should normally be equal
+		i++; // next char
+	}
+	return 0;
+}
+
+
+// rarely used variant: download our monitor using the built-in Archos monitor
+int DownloadArchosMonitor(tUartHandle serial_handle, char* szFilename)
+{
+	FILE* pFile;
+	size_t filesize;
+	UINT8 byte;
+	UINT16 checksum = 0;
+	unsigned i;
+
+	// the onboard monitor uses 115200 baud
+	if(!UartConfig(serial_handle, 115200, eNOPARITY, eONESTOPBIT, 8))
+	{
+		UINT32 dwErr = GET_LAST_ERR();
+		printf("Error %d setting up COM params for baudrate %d\n", dwErr, 115200);
+		exit(1);
+	}
+
+	// wait for receiving "#SERIAL#"
+	WaitForString(serial_handle, "#SERIAL#");
+	
+	// send magic "SRL" command to get interactive mode
+	SendWithEcho(serial_handle, "SRL\r");
+	
+	// wait for menu completion: "ROOT>" at the end
+	WaitForString(serial_handle, "ROOT>");
+	
+	// send upload command "UP"
+	SendWithEcho(serial_handle, "UP\r");
+	
+	pFile = fopen(szFilename, "rb");
+	if (pFile == NULL)
+	{
+		printf("\nMonitor file %s not found, exiting\n", szFilename);
+		exit(1);
+	}
+
+	// determine file size
+	fseek(pFile, 0, SEEK_END);
+	filesize = ftell(pFile);
+	fseek(pFile, 0, SEEK_SET);
+	
+	// calculate checksum
+	for (i=0; i<filesize; i++)
+	{
+		fread(&byte, 1, 1, pFile);
+		checksum += byte;
+	}
+	fseek(pFile, 0, SEEK_SET);
+	
+	// send header
+
+	// size as 32 bit little endian
+	byte = (UINT8)( filesize	  & 0xFF);
+	UartWrite(serial_handle, &byte, 1);
+	byte = (UINT8)((filesize>>8)  & 0xFF);
+	UartWrite(serial_handle, &byte, 1);
+	byte = (UINT8)((filesize>>16) & 0xFF);
+	UartWrite(serial_handle, &byte, 1);
+	byte = (UINT8)((filesize>>24) & 0xFF);
+	UartWrite(serial_handle, &byte, 1);
+
+	// checksum as 16 bit little endian
+	byte = (UINT8)( checksum	  & 0xFF);
+	UartWrite(serial_handle, &byte, 1);
+	byte = (UINT8)((checksum>>8)  & 0xFF);
+	UartWrite(serial_handle, &byte, 1);
+	
+	UartWrite(serial_handle, (unsigned char*)"\x00", 1); // kind (3 means flash)
+	UartWrite(serial_handle, (unsigned char*)"\x00", 1); // ignored byte
+
+	// wait for monitor to accept data
+	WaitForString(serial_handle, "#OKCTRL#");
+	
+	// transmit the image
+	for (i=0; i<filesize; i++)
+	{
+		fread(&byte, 1, 1, pFile);
+		UartWrite(serial_handle, &byte, 1); // payload
+	}
+	fclose (pFile);
+	
+	UartWrite(serial_handle, (unsigned char*)"\x00", 1); // ignored byte
+
+	// wait for menu completion: "ROOT>" at the end
+	WaitForString(serial_handle, "ROOT>");
+
+	// send start program command "SPRO"
+	SendWithEcho(serial_handle, "SPRO\r");
+
+	SLEEP(100); // wait a little while for startup
+
+	return 0;
+}
+
+
+/********** Target functions using the Monitor Protocol **********/
+
+// read a byte using the target monitor
+UINT8 ReadByte(tUartHandle serial_handle, UINT32 addr)
+{
+	UINT8 send;
+	UINT8 received;
+
+	// send the address command
+	send = ADDRESS;
+	UartWrite(serial_handle, &send, 1);
+
+	// transmit the address, big endian
+	send = (UINT8)((addr>>24) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)((addr>>16) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)((addr>>8) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)(addr & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+
+	UartRead(serial_handle, &received, 1); // response
+	if (received != ADDRESS)
+	{
+		printf("Protocol error!\n");
+		return 1;
+	}
+
+	// send the read command
+	send = BYTE_READ;
+	UartWrite(serial_handle, &send, 1);
+
+	UartRead(serial_handle, &received, 1); // response
+
+	return received;
+}
+
+
+// write a byte using the target monitor
+int WriteByte(tUartHandle serial_handle, UINT32 addr, UINT8 byte)
+{
+	UINT8 send;
+	UINT8 received;
+
+	// send the address command
+	send = ADDRESS;
+	UartWrite(serial_handle, &send, 1);
+
+	// transmit the address, big endian
+	send = (UINT8)((addr>>24) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)((addr>>16) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)((addr>>8) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)(addr & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+
+	UartRead(serial_handle, &received, 1); // response
+	if (received != ADDRESS)
+	{
+		printf("Protocol error, receiced 0x%02X!\n", received);
+		return 1;
+	}
+
+	// send the write command
+	send = BYTE_WRITE;
+	UartWrite(serial_handle, &send, 1);
+
+	// transmit the data
+	UartWrite(serial_handle, &byte, 1);
+	
+	UartRead(serial_handle, &received, 1); // response
+
+	if (received != BYTE_WRITE)
+	{
+		printf("Protocol error!\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+
+// read many bytes using the target monitor
+int ReadByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer)
+{
+	UINT8 send, received;
+
+	// send the address command
+	send = ADDRESS;
+	UartWrite(serial_handle, &send, 1);
+
+	// transmit the address, big endian
+	send = (UINT8)((addr>>24) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)((addr>>16) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)((addr>>8) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)(addr & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+
+	UartRead(serial_handle, &received, 1); // response
+	if (received != ADDRESS)
+	{
+		printf("Protocol error!\n");
+		return 1;
+	}
+
+	while (size)
+	{
+		if (size >= 16)
+		{	// we can use a "burst" command
+			send = BYTE_READ16;
+			UartWrite(serial_handle, &send, 1); // send the read command
+			UartRead(serial_handle, pBuffer, 16); // data response
+			pBuffer += 16;
+			size -= 16;
+		}
+		else
+		{	// use single byte command
+			send = BYTE_READ;
+			UartWrite(serial_handle, &send, 1); // send the read command
+			UartRead(serial_handle, pBuffer++, 1); // data response
+			size--;
+		}
+	}
+
+	return 0;
+}
+
+
+// write many bytes using the target monitor
+int WriteByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer)
+{
+	UINT8 send, received;
+
+	// send the address command
+	send = ADDRESS;
+	UartWrite(serial_handle, &send, 1);
+
+	// transmit the address, big endian
+	send = (UINT8)((addr>>24) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)((addr>>16) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)((addr>>8) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)(addr & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+
+	UartRead(serial_handle, &received, 1); // response
+	if (received != ADDRESS)
+	{
+		printf("Protocol error!\n");
+		return 1;
+	}
+
+	while (size)
+	{
+		if (size >= 16)
+		{	// we can use a "burst" command
+			send = BYTE_WRITE16;
+			UartWrite(serial_handle, &send, 1); // send the write command
+			UartWrite(serial_handle, pBuffer, 16); // transmit the data
+			UartRead(serial_handle, &received, 1); // response
+			if (received != BYTE_WRITE16)
+			{
+				printf("Protocol error!\n");
+				return 1;
+			}
+			pBuffer += 16;
+			size -= 16;
+		}
+		else
+		{	// use single byte command
+			send = BYTE_WRITE;
+			UartWrite(serial_handle, &send, 1); // send the write command
+			UartWrite(serial_handle, pBuffer++, 1); // transmit the data
+			UartRead(serial_handle, &received, 1); // response
+			if (received != BYTE_WRITE)
+			{
+				printf("Protocol error!\n");
+				return 1;
+			}
+			size--;
+		}
+	}
+
+	return 0;
+}
+
+
+// write many bytes using the target monitor
+int FlashByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer)
+{
+	UINT8 send, received;
+
+	// send the address command
+	send = ADDRESS;
+	UartWrite(serial_handle, &send, 1);
+
+	// transmit the address, big endian
+	send = (UINT8)((addr>>24) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)((addr>>16) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)((addr>>8) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)(addr & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+
+	UartRead(serial_handle, &received, 1); // response
+	if (received != ADDRESS)
+	{
+		printf("Protocol error!\n");
+		return 1;
+	}
+
+	while (size)
+	{
+		if (size >= 16)
+		{	// we can use a "burst" command
+			send = BYTE_FLASH16;
+			UartWrite(serial_handle, &send, 1); // send the write command
+			UartWrite(serial_handle, pBuffer, 16); // transmit the data
+			UartRead(serial_handle, &received, 1); // response
+			if (received != BYTE_FLASH16)
+			{
+				printf("Protocol error!\n");
+				return 1;
+			}
+			pBuffer += 16;
+			size -= 16;
+		}
+		else
+		{	// use single byte command
+			send = BYTE_FLASH;
+			UartWrite(serial_handle, &send, 1); // send the write command
+			UartWrite(serial_handle, pBuffer++, 1); // transmit the data
+			UartRead(serial_handle, &received, 1); // response
+			if (received != BYTE_FLASH)
+			{
+				printf("Protocol error!\n");
+				return 1;
+			}
+			size--;
+		}
+	}
+
+	return 0;
+}
+
+
+// read a 16bit halfword using the target monitor
+UINT16 ReadHalfword(tUartHandle serial_handle, UINT32 addr)
+{
+	UINT8 send;
+	UINT8 received;
+	UINT16 halfword;
+
+	// send the address command
+	send = ADDRESS;
+	UartWrite(serial_handle, &send, 1);
+
+	// transmit the address, big endian
+	send = (UINT8)((addr>>24) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)((addr>>16) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)((addr>>8) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)(addr & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+
+	UartRead(serial_handle, &received, 1); // response
+	if (received != ADDRESS)
+	{
+		printf("Protocol error!\n");
+		return 1;
+	}
+
+	// send the read command
+	send = HALFWORD_READ;
+	UartWrite(serial_handle, &send, 1);
+
+	UartRead(serial_handle, &received, 1); // response
+	halfword = received << 8; // highbyte
+	UartRead(serial_handle, &received, 1);
+	halfword |= received; // lowbyte
+
+	return halfword;
+}
+
+
+// write a 16bit halfword using the target monitor
+int WriteHalfword(tUartHandle serial_handle, UINT32 addr, UINT16 halfword)
+{
+	UINT8 send;
+	UINT8 received;
+
+	// send the address command
+	send = ADDRESS;
+	UartWrite(serial_handle, &send, 1);
+
+	// transmit the address, big endian
+	send = (UINT8)((addr>>24) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)((addr>>16) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)((addr>>8) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)(addr & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+
+	UartRead(serial_handle, &received, 1); // response
+	if (received != ADDRESS)
+	{
+		printf("Protocol error!\n");
+		return 1;
+	}
+
+	// send the write command
+	send = HALFWORD_WRITE;
+	UartWrite(serial_handle, &send, 1);
+
+	// transmit the data
+	send = halfword >> 8; // highbyte
+	UartWrite(serial_handle, &send, 1);
+	send = halfword & 0xFF; // lowbyte
+	UartWrite(serial_handle, &send, 1);
+	
+	UartRead(serial_handle, &received, 1); // response
+
+	if (received != HALFWORD_WRITE)
+	{
+		printf("Protocol error!\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+
+// change baudrate using target monitor
+int SetTargetBaudrate(tUartHandle serial_handle, long lClock, long lBaudrate)
+{
+	UINT8 send;
+	UINT8 received;
+	UINT8 brr;
+	long lBRR;
+
+	lBRR = lClock / lBaudrate;
+	lBRR = ((lBRR + 16) / 32) - 1; // with rounding
+	brr = (UINT8)lBRR;
+
+	// send the command
+	send = BAUDRATE;
+	UartWrite(serial_handle, &send, 1);
+	UartWrite(serial_handle, &brr, 1); // send the BRR value
+	UartRead(serial_handle, &received, 1); // response ack
+
+	if (received != BAUDRATE)
+	{	// bad situation, now we're unclear about the baudrate of the target
+		printf("Protocol error!\n");
+		return 1;
+	}
+
+	SLEEP(100); // give it some time to settle
+
+	// change our baudrate, too
+	UartConfig(serial_handle, lBaudrate, eNOPARITY, eONESTOPBIT, 8); 
+
+	return 0;
+}
+
+
+// call a subroutine using the target monitor
+int Execute(tUartHandle serial_handle, UINT32 addr, bool bReturns)
+{
+	UINT8 send;
+	UINT8 received;
+
+	// send the address command
+	send = ADDRESS;
+	UartWrite(serial_handle, &send, 1);
+
+	// transmit the address, big endian
+	send = (UINT8)((addr>>24) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)((addr>>16) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)((addr>>8) & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+	send = (UINT8)(addr & 0xFF);
+	UartWrite(serial_handle, &send, 1);
+
+	UartRead(serial_handle, &received, 1); // response
+	if (received != ADDRESS)
+	{
+		printf("Protocol error!\n");
+		return 1;
+	}
+
+	// send the execute command
+	send = EXECUTE;
+	UartWrite(serial_handle, &send, 1);
+	if (bReturns)
+	{	// we expect the call to return control to minimon
+		UartRead(serial_handle, &received, 1); // response
+
+		if (received != EXECUTE)
+		{
+			printf("Protocol error!\n");
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+
diff --git a/flash/uart_boot/client.h b/flash/uart_boot/client.h
new file mode 100644
index 0000000..d2ef29a
--- /dev/null
+++ b/flash/uart_boot/client.h
@@ -0,0 +1,21 @@
+#ifndef _CLIENT_H
+#define _CLIENT_H
+
+
+// setup function for monitor download
+int DownloadMonitor(tUartHandle serial_handle, bool bRecorder, char* szFilename);
+int DownloadArchosMonitor(tUartHandle serial_handle, char* szFilename);
+
+// target functions using the Monitor Protocol
+UINT8 ReadByte(tUartHandle serial_handle, UINT32 addr);
+int WriteByte(tUartHandle serial_handle, UINT32 addr, UINT8 byte);
+int ReadByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer);
+int WriteByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer);
+int FlashByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer);
+UINT16 ReadHalfword(tUartHandle serial_handle, UINT32 addr);
+int WriteHalfword(tUartHandle serial_handle, UINT32 addr, UINT16 halfword);
+int SetTargetBaudrate(tUartHandle serial_handle, long lClock, long lBaudrate);
+int Execute(tUartHandle serial_handle, UINT32 addr, bool bReturns);
+
+
+#endif
\ No newline at end of file
diff --git a/flash/uart_boot/flash.c b/flash/uart_boot/flash.c
new file mode 100644
index 0000000..f27bb7e
--- /dev/null
+++ b/flash/uart_boot/flash.c
@@ -0,0 +1,77 @@
+// flash.cpp : higher-level functions for flashing the chip
+//
+
+#include "scalar_types.h" // (U)INT8/16/32
+#include "Uart.h" // platform abstraction for UART
+#include "client.h" // client functions
+
+
+// read the manufacturer and device ID
+int ReadID(tUartHandle serial_handle, UINT32 base, UINT8* pManufacturerID, UINT8* pDeviceID)
+{
+	base &= 0xFFF80000; // round down to 512k align, to make shure
+
+	WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
+	WriteByte(serial_handle, base + 0x2AAA, 0x55);
+	WriteByte(serial_handle, base + 0x5555, 0x90); // ID command
+	SLEEP(20); // Atmel wants 20ms pause here
+
+	*pManufacturerID = ReadByte(serial_handle, base + 0);
+	*pDeviceID		 = ReadByte(serial_handle, base + 1);
+
+	WriteByte(serial_handle, base + 0, 0xF0);	// reset flash (back to normal read mode)
+	SLEEP(20); // Atmel wants 20ms pause here
+
+	return 0;
+}
+
+
+// erase the sector which contains the given address
+int EraseSector(tUartHandle serial_handle, UINT32 address)
+{
+	UINT32 base = address & 0xFFF80000; // round down to 512k align
+	
+	WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
+	WriteByte(serial_handle, base + 0x2AAA, 0x55);
+	WriteByte(serial_handle, base + 0x5555, 0x80); // eraze command
+	WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
+	WriteByte(serial_handle, base + 0x2AAA, 0x55);
+	WriteByte(serial_handle, address, 0x30); // eraze the sector
+	SLEEP(25); // sector eraze time: 25ms
+
+	return 0;
+}
+
+
+// erase the whole flash
+int EraseChip(tUartHandle serial_handle, UINT32 base)
+{
+	base &= 0xFFF80000; // round down to 512k align, to make shure
+	
+	WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
+	WriteByte(serial_handle, base + 0x2AAA, 0x55);
+	WriteByte(serial_handle, base + 0x5555, 0x80); // eraze command
+	WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
+	WriteByte(serial_handle, base + 0x2AAA, 0x55);
+	WriteByte(serial_handle, base + 0x5555, 0x10); // chip eraze command
+	SLEEP(100); // chip eraze time: 100ms
+
+	return 0;
+}
+
+
+// program a bunch of bytes "by hand"
+int ProgramBytes(tUartHandle serial_handle, UINT32 address, UINT8* pData, UINT32 size)
+{
+	UINT32 base = address & 0xFFF80000; // round down to 512k align
+
+	while (size--)
+	{
+		WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
+		WriteByte(serial_handle, base + 0x2AAA, 0x55);
+		WriteByte(serial_handle, base + 0x5555, 0xA0); // byte program command
+		WriteByte(serial_handle, address++, *pData++);
+		// UART protocol is slow enough such that I don't have to wait 20us here
+	}
+	return 0;
+}
\ No newline at end of file
diff --git a/flash/uart_boot/flash.h b/flash/uart_boot/flash.h
new file mode 100644
index 0000000..70c6201
--- /dev/null
+++ b/flash/uart_boot/flash.h
@@ -0,0 +1,9 @@
+#ifndef _FLASH_H
+#define _FLASH_H
+
+int ReadID(tUartHandle serial_handle, UINT32 base, UINT8* pManufacturerID, UINT8* pDeviceID);
+int EraseSector(tUartHandle serial_handle, UINT32 address);
+int EraseChip(tUartHandle serial_handle, UINT32 base);
+int ProgramBytes(tUartHandle serial_handle, UINT32 address, UINT8* pData, UINT32 size);
+
+#endif
\ No newline at end of file
diff --git a/flash/uart_boot/minimon.h b/flash/uart_boot/minimon.h
new file mode 100644
index 0000000..51406d4
--- /dev/null
+++ b/flash/uart_boot/minimon.h
@@ -0,0 +1,23 @@
+#ifndef _MINIMON_H
+#define _MINIMON_H
+
+
+// Commands
+// all multibyte values (address, halfwords) are passed as big endian 
+//  (most significant of the bytes first)
+
+// set the address (all read/write commands will auto-increment it)
+#define BAUDRATE       0x00 // followed by BRR value; response: command byte
+#define ADDRESS        0x01 // followed by 4 bytes address; response: command byte
+#define BYTE_READ      0x02 // response: 1 byte content
+#define BYTE_WRITE     0x03 // followed by 1 byte content; response: command byte
+#define BYTE_READ16    0x04 // response: 16 bytes content
+#define BYTE_WRITE16   0x05 // followed by 16 bytes; response: command byte
+#define BYTE_FLASH     0x06 // followed by 1 byte content; response: command byte
+#define BYTE_FLASH16   0x07 // followed by 16 bytes; response: command byte
+#define HALFWORD_READ  0x08 // response: 2 byte content
+#define HALFWORD_WRITE 0x09 // followed by 2 byte content; response: command byte
+#define EXECUTE        0x0A // response: command byte if call returns
+
+
+#endif // _MINIMON_H
diff --git a/flash/uart_boot/scalar_types.h b/flash/uart_boot/scalar_types.h
new file mode 100644
index 0000000..88d82c4
--- /dev/null
+++ b/flash/uart_boot/scalar_types.h
@@ -0,0 +1,44 @@
+// this is meant to resolve platform dependency
+
+#ifndef _SCALAR_TYPES_H
+#define _SCALAR_TYPES_H
+
+
+#ifdef WIN32
+#include <windows.h>
+#define SLEEP Sleep
+#define GET_LAST_ERR GetLastError
+#endif
+// ToDo: add stuff for Linux
+
+
+
+#ifndef UINT8
+#define UINT8 unsigned char
+#endif
+
+#ifndef UINT16
+#define UINT16 unsigned short
+#endif
+
+#ifndef UINT32
+#define UINT32 unsigned long
+#endif
+
+#ifndef bool
+#define bool int
+#endif
+
+#ifndef true
+#define true 1
+#endif
+
+#ifndef false
+#define false 0
+#endif
+
+
+
+
+
+#endif
\ No newline at end of file
diff --git a/flash/uart_boot/uart.h b/flash/uart_boot/uart.h
new file mode 100644
index 0000000..46b082c
--- /dev/null
+++ b/flash/uart_boot/uart.h
@@ -0,0 +1,56 @@
+// A general definition for the required UART functionality.
+// This will be used to gain platform abstraction.
+
+#ifndef _UART_H
+#define _UART_H
+
+// data types
+
+typedef void* tUartHandle;
+#define INVALID_UART_HANDLE (tUartHandle)-1
+
+typedef enum
+{
+	eNOPARITY,
+	eODDPARITY, 
+	eEVENPARITY,
+	eMARKPARITY,
+	eSPACEPARITY,
+} tParity;
+
+typedef enum
+{
+	eONESTOPBIT,
+	eONE5STOPBITS,
+	eTWOSTOPBITS,
+} tStopBits;
+
+
+// prototypes
+
+tUartHandle UartOpen(   // returns NULL on error
+	char* szPortName);  // COMx for windows
+
+bool UartConfig(         // returns true on success, false on error
+	tUartHandle handle,  // the handle returned from UartOpen()
+	long lBaudRate,      // must be one of the "standard" baudrates
+	tParity nParity,     // what kind of parity
+	tStopBits nStopBits, // how many stop bits
+	int nByteSize);      // size of the "payload", can be 5 to 8
+
+long UartWrite(           // returns how much data was actually transmitted
+	tUartHandle handle,   // the handle returned from UartOpen()
+	unsigned char* pData, // pointer to the data to be transmitted
+	long lSize);          // how many bytes
+
+long UartRead(              // returns how much data was actually received
+	tUartHandle handle,     // the handle returned from UartOpen()
+	unsigned char* pBuffer, // pointer to the destination
+	long lSize);            // how many bytes to read (pBuffer must have enough room)
+
+
+void UartClose(tUartHandle handle);
+
+
+
+#endif // _UART_H
\ No newline at end of file
diff --git a/flash/uart_boot/uart_boot.c b/flash/uart_boot/uart_boot.c
new file mode 100644
index 0000000..8110e9b
--- /dev/null
+++ b/flash/uart_boot/uart_boot.c
@@ -0,0 +1,337 @@
+// uart_boot.cpp : Defines the entry point for the console application.
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "scalar_types.h" // (U)INT8/16/32
+#include "Uart.h" // platform abstraction for UART
+#include "client.h" // client functions
+#include "flash.h" // flash high level functions
+
+// command line configuration: what shall we do?
+struct
+{
+	char* szPort; // COM port to use
+	bool bRecorder; // it's a recorder
+	bool bArchos; // use the Archos monitor to load, instead of UART boot
+	bool bSpindown; // spindown the harddisk
+	bool bReadID; // read manufacturer+device ID
+	char* szFlashfile; // file to be programmed
+	char* szDumpfile; // file to dump into
+	char* szExecfile; // file with the executable
+	bool bTest; // debug action
+	bool bBlink; // blink red LED
+	bool bNoDownload;
+} gCmd;
+
+
+int ProcessCmdLine(int argc, char* argv[])
+{
+	argc--; // exclude our name
+	argv++;
+
+	memset(&gCmd, 0, sizeof(gCmd));
+
+	if (argc == 0)
+	{
+		printf("Usage: uart_boot [-option {filename}]\n");
+		printf("  uses activated UART boot mod, box has to be fresh started\n");
+		printf("The order of the options does not matter, one letter is sufficient.\n");
+		printf("Possible options are (in the order of later processing):\n");
+		printf("-port <name of COM port to use>\n");
+		printf("-recorder  (this is a recorder/FM, default is player if not specified)\n");
+		printf("-archos  (use Archos bootloader, this one needs powerup while program waits)\n");
+		printf("-nodownload  (no MiniMon download, it's already active)\n");
+		printf("-spindown  (spindown the harddisk, else it stays on by default)\n");
+		printf("-id  (read manufacturer and device ID of flash, no checks)\n");
+		printf("-flash <filename of binary to program into flash>\n");
+		printf("-dump <filename to write flash content to>\n");
+		printf("-exec <filename of executable for 0x09000000:0x09000200>\n");
+		printf("-test  (some test action currently under development, don't use!)\n");
+		printf("-blink (blink red LED forever, meant as diagnostics)\n");
+		printf("\n");
+		printf("Examples:\n");
+		printf("uart_boot -r -p COM1 -s -f flashfile.bin -d dumpfile.bin\n");
+		printf("  recorder on COM1, spindown HD, program and dump (for e.g. offline verify)\n");
+		printf("uart_boot -r -p COM2 -e rockbox.bin\n");
+		printf("  recorder on COM2, load Rockbox from file and start it\n");
+		exit (0);
+	}
+
+
+	while (argc)
+	{
+		if (!strncmp("-port", *argv, 2))
+		{
+			gCmd.szPort = *++argv;
+			if (--argc <= 0 || **argv == '-')
+			{	
+				printf("No argument given for option %s, aborting.\n", argv[-1]);
+				exit (-2);
+			}
+		}
+		else if (!strncmp("-recorder", *argv, 2))
+		{
+			gCmd.bRecorder = true;
+		}
+		else if (!strncmp("-archos", *argv, 2))
+		{
+			gCmd.bArchos = true;
+		}
+		else if (!strncmp("-nodownload", *argv, 2))
+		{
+			gCmd.bNoDownload = true;
+		}
+		else if (!strncmp("-spindown", *argv, 2))
+		{
+			gCmd.bSpindown = true;
+		}
+		else if (!strncmp("-id", *argv, 2))
+		{
+			gCmd.bReadID = true;
+		}
+		else if (!strncmp("-flash", *argv, 2))
+		{
+			gCmd.szFlashfile = *++argv;
+			if (--argc <= 0 || **argv == '-')
+			{	
+				printf("No argument given for option %s, aborting.\n", argv[-1]);
+				exit (-2);
+			}
+		}
+		else if (!strncmp("-dump", *argv, 2))
+		{
+			gCmd.szDumpfile = *++argv;
+			if (--argc <= 0 || **argv == '-')
+			{	
+				printf("No argument given for option %s, aborting.\n", argv[-1]);
+				exit (-3);
+			}
+		}
+		else if (!strncmp("-exec", *argv, 2))
+		{
+			gCmd.szExecfile = *++argv;
+			if (--argc <= 0 || **argv == '-')
+			{	
+				printf("No argument given for option %s, aborting.\n", argv[-1]);
+				exit (-4);
+			}
+		}
+		else if (!strncmp("-test", *argv, 2))
+		{
+			gCmd.bTest = true;
+		}
+		else if (!strncmp("-blink", *argv, 2))
+		{
+			gCmd.bBlink = true;
+		}
+		else
+		{
+			printf("Unknown option %s, aborting. Use 'uart_boot' without options for help.\n", *argv);
+			exit(-1);
+		}
+
+		argv++;
+		argc--;
+	}
+	
+	return 0;
+}
+
+
+int main(int argc, char* argv[])
+{
+	tUartHandle serial_handle;
+	UINT16 reg;
+	FILE* pFile;
+	size_t size;
+	UINT8 abFirmware[512*1024]; // blocksize
+	memset(abFirmware, 0xFF, sizeof(abFirmware));
+
+	ProcessCmdLine(argc, argv); // what to do
+
+	if (!gCmd.szPort)
+	{
+		printf("No serial port given, use 'uart_boot' without parameters for options.\n");
+		exit(-1);
+	}
+
+	serial_handle = UartOpen(gCmd.szPort); // opening serial port
+	if (serial_handle == NULL)
+	{
+		printf("Cannot open port %s\n", gCmd.szPort);
+		return -1;
+	}
+		
+	if (gCmd.bNoDownload)
+	{	// just set our speed
+		if (!UartConfig(serial_handle, gCmd.bRecorder ? 115200 : 14400, eNOPARITY, eONESTOPBIT, 8))
+		{
+			printf("Error setting up COM params\n");
+			exit(1);
+		}
+	}
+	else
+	{	// download the monitor program
+		if (gCmd.bArchos)
+		{
+			printf("Waiting for box startup to download monitor...");
+			DownloadArchosMonitor(serial_handle, "minimon_v2.bin"); // load the monitor image
+			printf("\b\b\b done.\n");
+		}
+		else
+		{
+			printf("Downloading monitor...");
+			DownloadMonitor(serial_handle, gCmd.bRecorder, "minimon.bin"); // load the monitor image
+			// From now on, we can talk to the box.
+			printf("\b\b\b done.\n");
+
+			if (gCmd.bRecorder)
+			{	// we can be faster
+				SetTargetBaudrate(serial_handle, 11059200, 115200); // set to 115200
+			}
+		}
+	}
+
+	// do the action
+
+	if (gCmd.bSpindown)
+	{
+		// spindown the disk (works only for master)
+		UINT32 ata; // address of ATA_ALT_STATUS
+		printf("Harddisk spindown...");
+		ata = (gCmd.bRecorder && (ReadHalfword(serial_handle, 0x020000FC) & 0x0100)) ? 0x06200206 : 0x06200306;
+		WriteHalfword(serial_handle, 0x05FFFFCA, 0xBF99); // PACR2 (was 0xFF99)
+		WriteHalfword(serial_handle, 0x05FFFFC4, 0x0280); // PAIOR (was 0x0000)
+		WriteHalfword(serial_handle, 0x05FFFFC0, 0xA27F); // PADR  (was 0xA0FF)
+		while (ReadByte(serial_handle, ata) & 0x80); // ATA_ALT_STATUS & STATUS_BSY
+		WriteByte(serial_handle, 0x06100107, 0xE0); // ATA_COMMAND = CMD_STANDBY_IMMEDIATE;
+		//while (ReadByte(serial_handle, ata) & 0x80); // ATA_ALT_STATUS & STATUS_BSY
+		printf("\b\b\b done.\n");
+	}
+
+
+	if (gCmd.bReadID)
+	{
+		UINT8 bMan, bID;
+		ReadID(serial_handle, 0x02000000, &bMan, &bID);
+		printf("Manufacturer ID = 0x%02X, Device ID = 0x%02X\n", bMan, bID);
+	}
+
+
+	if (gCmd.szFlashfile)
+	{
+		// flash a firmware file
+		printf("Flashing file %s...", gCmd.szFlashfile);
+		pFile = fopen(gCmd.szFlashfile, "rb");
+		if (pFile == NULL)
+		{
+			printf("\nFlash file %s not found, exiting.\n", gCmd.szFlashfile);
+			return -2;
+		}
+		size = fread(abFirmware, 1, sizeof(abFirmware), pFile);
+		fclose (pFile);
+		
+		EraseChip(serial_handle, 0x02000000);
+		FlashByteMultiple(serial_handle, 0x02000000, size, abFirmware);
+		printf("\b\b\b done.\n");
+	}
+
+
+	if (gCmd.szDumpfile)
+	{
+		// dump the flash content
+		printf("Writing flash dump into file %s...", gCmd.szDumpfile);
+		ReadByteMultiple(serial_handle, 0x02000000, sizeof(abFirmware), abFirmware);
+		pFile = fopen(gCmd.szDumpfile, "wb");
+		if (pFile == NULL)
+		{
+			printf("\nDump file %s cannot be opened, exiting.\n", gCmd.szDumpfile);
+			return -3;
+		}
+		fwrite(abFirmware, 1, sizeof(abFirmware), pFile);
+		fclose (pFile);
+		printf("\b\b\b done.\n");
+	}
+
+
+	if (gCmd.szExecfile)
+	{
+		UINT32 size;
+		
+		printf("Downloading program...");
+
+		// init the DRAM controller like the flash boot does
+		reg = ReadHalfword(serial_handle, 0x05FFFFCA); // PACR2
+		reg &= 0xFFFB; // PA1 config: /RAS
+		reg |= 0x0008;
+		WriteHalfword(serial_handle, 0x05FFFFCA, reg); // PACR2
+		reg = 0xAFFF; // CS1, CS3 config: /CASH. /CASL
+		WriteHalfword(serial_handle, 0x05FFFFEE, reg); // CASCR
+		reg = ReadHalfword(serial_handle, 0x05FFFFA0); // BCR  
+		reg |= 0x8000; // DRAM enable, default bus 
+		WriteHalfword(serial_handle, 0x05FFFFA0, reg); // BCR 
+		reg = ReadHalfword(serial_handle, 0x05FFFFA2); // WCR1	 
+		reg &= 0xFDFD; // 1-cycle CAS 
+		WriteHalfword(serial_handle, 0x05FFFFA2, reg); // WCR1	
+		reg = 0x0E00; // CAS 35%, multiplexed, 10 bit row addr.
+		WriteHalfword(serial_handle, 0x05FFFFA8, reg); // DCR
+		reg = 0x5AB0; // refresh, 4 cycle waitstate
+		WriteHalfword(serial_handle, 0x05FFFFAC, reg); // RCR
+		reg = 0x9605; // refresh constant
+		WriteHalfword(serial_handle, 0x05FFFFB2, reg); // RTCOR
+		reg = 0xA518; // phi/32
+		WriteHalfword(serial_handle, 0x05FFFFAE, reg); // RTCSR
+
+
+		// download Rockbox/gdb
+		pFile = fopen(gCmd.szExecfile, "rb");
+		if (pFile == NULL)
+		{
+			printf("\nExecutable file %s cannot be opened, exiting.\n", gCmd.szExecfile);
+			return -3;
+		}
+
+		size = fread(abFirmware, 1, sizeof(abFirmware), pFile);
+		WriteByteMultiple(serial_handle, 0x09000000, size, abFirmware);
+		fclose (pFile);
+		printf("\b\b\b done.\n");
+
+		// start rockbox/gdb
+		printf("Starting program...");
+		Execute(serial_handle, 0x09000200, false);
+		printf("\b\b\b done.\n");
+	}
+
+
+	if (gCmd.bTest)
+	{
+		// test code: query keypad
+		while (1)
+		{
+			WriteByte(serial_handle, 0x05FFFEE8, 0x24); // ADCSR
+			while (!(ReadByte(serial_handle, 0x05FFFEE8) & 0x80));
+			reg = ReadHalfword(serial_handle, 0x05FFFEE0); // ADDRA
+			printf("ADC(4): %d\n", reg>>6);
+		}
+	}
+
+
+	if (gCmd.bBlink)
+	{
+		// blinking LED
+		UINT8 byte;
+		printf("Flashing red LED forever... (stop with Ctrl-C)\n");
+		byte = ReadByte(serial_handle, 0x05FFFFC3);
+		while (1)
+		{
+			byte ^= 0x40;
+			WriteByte(serial_handle, 0x05FFFFC3, byte);
+			Sleep(200);
+		}
+	}
+
+	return 0;
+}
+
diff --git a/flash/uart_boot/uart_boot.dsp b/flash/uart_boot/uart_boot.dsp
new file mode 100644
index 0000000..4d94c72
--- /dev/null
+++ b/flash/uart_boot/uart_boot.dsp
@@ -0,0 +1,130 @@
+# Microsoft Developer Studio Project File - Name="uart_boot" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=uart_boot - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "uart_boot.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "uart_boot.mak" CFG="uart_boot - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "uart_boot - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "uart_boot - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "uart_boot - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE RSC /l 0x407 /d "NDEBUG"
+# ADD RSC /l 0x407 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "uart_boot - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE RSC /l 0x407 /d "_DEBUG"
+# ADD RSC /l 0x407 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "uart_boot - Win32 Release"
+# Name "uart_boot - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\client.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\flash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\uart_boot.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\uart_win.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\client.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\flash.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\minimon.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\scalar_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\uart.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/flash/uart_boot/uart_win.c b/flash/uart_boot/uart_win.c
new file mode 100644
index 0000000..243017a
--- /dev/null
+++ b/flash/uart_boot/uart_win.c
@@ -0,0 +1,138 @@
+// UART wrapper implementation for the Win32 platform
+// make a new version of this file for different systems, e.g. Linux
+
+#include <windows.h>
+#include "scalar_types.h" // (U)INT8/16/32
+#include "Uart.h"
+
+// COMx for windows, returns NULL on error
+tUartHandle UartOpen(char* szPortName)
+{
+	HANDLE serial_handle; 
+	DCB  dcb;
+	COMMTIMEOUTS cto = { 0, 0, 0, 0, 0 };
+
+	memset(&dcb,0,sizeof(dcb));
+
+	/* -------------------------------------------------------------------- */
+	// set DCB to configure the serial port
+	dcb.DCBlength       = sizeof(dcb);
+
+	dcb.fOutxCtsFlow    = 0;
+	dcb.fOutxDsrFlow    = 0;
+	dcb.fDtrControl     = DTR_CONTROL_ENABLE; // enable for power
+	dcb.fDsrSensitivity = 0;
+	dcb.fRtsControl     = RTS_CONTROL_ENABLE; // enable for power
+	dcb.fOutX           = 0;
+	dcb.fInX            = 0;
+
+	/* ----------------- misc parameters ----- */
+	dcb.fErrorChar      = 0;
+	dcb.fBinary         = 1;
+	dcb.fNull           = 0;
+	dcb.fAbortOnError   = 0;
+	dcb.wReserved       = 0;
+	dcb.XonLim          = 2;
+	dcb.XoffLim         = 4;
+	dcb.XonChar         = 0x13;
+	dcb.XoffChar        = 0x19;
+	dcb.EvtChar         = 0;
+
+	/* ----------------- defaults ----- */
+	dcb.BaudRate = 4800;
+	dcb.Parity   = NOPARITY;
+	dcb.fParity  = 0;
+	dcb.StopBits = ONESTOPBIT;
+	dcb.ByteSize = 8;
+
+
+	/* -------------------------------------------------------------------- */
+	// opening serial port
+	serial_handle = CreateFile(szPortName, GENERIC_READ | GENERIC_WRITE,
+		0, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL);
+
+	if (serial_handle == INVALID_HANDLE_VALUE)
+	{
+		//printf("Cannot open port \n");
+		return NULL;
+	}
+
+	SetCommMask(serial_handle, 0);
+	SetCommTimeouts(serial_handle, &cto);
+
+	if(!SetCommState(serial_handle, &dcb))
+	{
+		//printf("Error setting up COM params\n");
+		CloseHandle(serial_handle);
+		return NULL;
+	}
+
+	return serial_handle;
+}
+
+// returns true on success, false on error
+bool UartConfig(tUartHandle handle, long lBaudRate, tParity nParity, tStopBits nStopBits, int nByteSize)
+{
+	DCB  dcb;
+	
+	if (!GetCommState (handle, &dcb))
+	{
+		return false;
+	}
+
+	dcb.BaudRate = lBaudRate;
+	dcb.Parity	 = nParity;
+	dcb.StopBits = nStopBits;
+	dcb.ByteSize = nByteSize;
+
+	if(!SetCommState(handle, &dcb))
+	{
+		//DWORD dwErr = GetLastError();
+		//printf("Error %d setting up COM params for baudrate byte\n", dwErr);
+		return false;
+	}
+
+	return true;
+}
+
+// returns how much data was actually transmitted
+long UartWrite(tUartHandle handle, unsigned char* pData, long lSize)
+{
+	BOOL success;
+	DWORD result_nbr;
+
+	success = WriteFile(handle, pData, lSize, &result_nbr, NULL);
+
+	if(!success)
+	{
+		return 0;
+	}
+
+	return result_nbr;
+}
+
+// returns how much data was actually received
+long UartRead(tUartHandle handle, unsigned char* pBuffer, long lSize)
+{
+	BOOL success;
+	DWORD read_nbr;
+
+	success = ReadFile(handle, pBuffer, lSize, &read_nbr, NULL);
+	if(!success)
+	{
+		return 0;
+	}
+
+	return read_nbr;
+}
+
+
+void UartClose(tUartHandle handle)
+{
+	if (handle != NULL)
+	{
+		CloseHandle(handle);
+	}
+
+	return;
+}